1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/html/nsHTMLInlineTableEditor.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,272 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "mozilla/dom/Element.h" 1.9 +#include "nsAString.h" 1.10 +#include "nsCOMPtr.h" 1.11 +#include "nsDebug.h" 1.12 +#include "nsError.h" 1.13 +#include "nsHTMLEditUtils.h" 1.14 +#include "nsHTMLEditor.h" 1.15 +#include "nsIContent.h" 1.16 +#include "nsIDOMElement.h" 1.17 +#include "nsIDOMEventTarget.h" 1.18 +#include "nsIDOMHTMLElement.h" 1.19 +#include "nsIDOMNode.h" 1.20 +#include "nsIHTMLEditor.h" 1.21 +#include "nsIHTMLObjectResizer.h" 1.22 +#include "nsIPresShell.h" 1.23 +#include "nsLiteralString.h" 1.24 +#include "nsReadableUtils.h" 1.25 +#include "nsString.h" 1.26 +#include "nscore.h" 1.27 + 1.28 +// Uncomment the following line if you want to disable 1.29 +// table deletion when the only column/row is removed 1.30 +// #define DISABLE_TABLE_DELETION 1 1.31 + 1.32 +NS_IMETHODIMP 1.33 +nsHTMLEditor::SetInlineTableEditingEnabled(bool aIsEnabled) 1.34 +{ 1.35 + mIsInlineTableEditingEnabled = aIsEnabled; 1.36 + return NS_OK; 1.37 +} 1.38 + 1.39 +NS_IMETHODIMP 1.40 +nsHTMLEditor::GetInlineTableEditingEnabled(bool * aIsEnabled) 1.41 +{ 1.42 + *aIsEnabled = mIsInlineTableEditingEnabled; 1.43 + return NS_OK; 1.44 +} 1.45 + 1.46 +NS_IMETHODIMP 1.47 +nsHTMLEditor::ShowInlineTableEditingUI(nsIDOMElement * aCell) 1.48 +{ 1.49 + NS_ENSURE_ARG_POINTER(aCell); 1.50 + 1.51 + // do nothing if aCell is not a table cell... 1.52 + if (!nsHTMLEditUtils::IsTableCell(aCell)) 1.53 + return NS_OK; 1.54 + 1.55 + if (mInlineEditedCell) { 1.56 + NS_ERROR("call HideInlineTableEditingUI first"); 1.57 + return NS_ERROR_UNEXPECTED; 1.58 + } 1.59 + 1.60 + // the resizers and the shadow will be anonymous children of the body 1.61 + nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot()); 1.62 + NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER); 1.63 + 1.64 + CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement, 1.65 + NS_LITERAL_STRING("mozTableAddColumnBefore"), 1.66 + false, getter_AddRefs(mAddColumnBeforeButton)); 1.67 + CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement, 1.68 + NS_LITERAL_STRING("mozTableRemoveColumn"), 1.69 + false, getter_AddRefs(mRemoveColumnButton)); 1.70 + CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement, 1.71 + NS_LITERAL_STRING("mozTableAddColumnAfter"), 1.72 + false, getter_AddRefs(mAddColumnAfterButton)); 1.73 + 1.74 + CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement, 1.75 + NS_LITERAL_STRING("mozTableAddRowBefore"), 1.76 + false, getter_AddRefs(mAddRowBeforeButton)); 1.77 + CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement, 1.78 + NS_LITERAL_STRING("mozTableRemoveRow"), 1.79 + false, getter_AddRefs(mRemoveRowButton)); 1.80 + CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement, 1.81 + NS_LITERAL_STRING("mozTableAddRowAfter"), 1.82 + false, getter_AddRefs(mAddRowAfterButton)); 1.83 + 1.84 + AddMouseClickListener(mAddColumnBeforeButton); 1.85 + AddMouseClickListener(mRemoveColumnButton); 1.86 + AddMouseClickListener(mAddColumnAfterButton); 1.87 + AddMouseClickListener(mAddRowBeforeButton); 1.88 + AddMouseClickListener(mRemoveRowButton); 1.89 + AddMouseClickListener(mAddRowAfterButton); 1.90 + 1.91 + mInlineEditedCell = aCell; 1.92 + return RefreshInlineTableEditingUI(); 1.93 +} 1.94 + 1.95 +NS_IMETHODIMP 1.96 +nsHTMLEditor::HideInlineTableEditingUI() 1.97 +{ 1.98 + mInlineEditedCell = nullptr; 1.99 + 1.100 + RemoveMouseClickListener(mAddColumnBeforeButton); 1.101 + RemoveMouseClickListener(mRemoveColumnButton); 1.102 + RemoveMouseClickListener(mAddColumnAfterButton); 1.103 + RemoveMouseClickListener(mAddRowBeforeButton); 1.104 + RemoveMouseClickListener(mRemoveRowButton); 1.105 + RemoveMouseClickListener(mAddRowAfterButton); 1.106 + 1.107 + // get the presshell's document observer interface. 1.108 + nsCOMPtr<nsIPresShell> ps = GetPresShell(); 1.109 + // We allow the pres shell to be null; when it is, we presume there 1.110 + // are no document observers to notify, but we still want to 1.111 + // UnbindFromTree. 1.112 + 1.113 + // get the root content node. 1.114 + nsCOMPtr<nsIContent> bodyContent = GetRoot(); 1.115 + NS_ENSURE_TRUE(bodyContent, NS_ERROR_FAILURE); 1.116 + 1.117 + DeleteRefToAnonymousNode(mAddColumnBeforeButton, bodyContent, ps); 1.118 + mAddColumnBeforeButton = nullptr; 1.119 + DeleteRefToAnonymousNode(mRemoveColumnButton, bodyContent, ps); 1.120 + mRemoveColumnButton = nullptr; 1.121 + DeleteRefToAnonymousNode(mAddColumnAfterButton, bodyContent, ps); 1.122 + mAddColumnAfterButton = nullptr; 1.123 + DeleteRefToAnonymousNode(mAddRowBeforeButton, bodyContent, ps); 1.124 + mAddRowBeforeButton = nullptr; 1.125 + DeleteRefToAnonymousNode(mRemoveRowButton, bodyContent, ps); 1.126 + mRemoveRowButton = nullptr; 1.127 + DeleteRefToAnonymousNode(mAddRowAfterButton, bodyContent, ps); 1.128 + mAddRowAfterButton = nullptr; 1.129 + 1.130 + return NS_OK; 1.131 +} 1.132 + 1.133 +NS_IMETHODIMP 1.134 +nsHTMLEditor::DoInlineTableEditingAction(nsIDOMElement * aElement) 1.135 +{ 1.136 + NS_ENSURE_ARG_POINTER(aElement); 1.137 + bool anonElement = false; 1.138 + if (aElement && 1.139 + NS_SUCCEEDED(aElement->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)) && 1.140 + anonElement) { 1.141 + nsAutoString anonclass; 1.142 + nsresult res = aElement->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass); 1.143 + NS_ENSURE_SUCCESS(res, res); 1.144 + 1.145 + if (!StringBeginsWith(anonclass, NS_LITERAL_STRING("mozTable"))) 1.146 + return NS_OK; 1.147 + 1.148 + nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell); 1.149 + nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode); 1.150 + int32_t rowCount, colCount; 1.151 + res = GetTableSize(tableElement, &rowCount, &colCount); 1.152 + NS_ENSURE_SUCCESS(res, res); 1.153 + 1.154 + bool hideUI = false; 1.155 + bool hideResizersWithInlineTableUI = (mResizedObject == tableElement); 1.156 + 1.157 + if (anonclass.EqualsLiteral("mozTableAddColumnBefore")) 1.158 + InsertTableColumn(1, false); 1.159 + else if (anonclass.EqualsLiteral("mozTableAddColumnAfter")) 1.160 + InsertTableColumn(1, true); 1.161 + else if (anonclass.EqualsLiteral("mozTableAddRowBefore")) 1.162 + InsertTableRow(1, false); 1.163 + else if (anonclass.EqualsLiteral("mozTableAddRowAfter")) 1.164 + InsertTableRow(1, true); 1.165 + else if (anonclass.EqualsLiteral("mozTableRemoveColumn")) { 1.166 + DeleteTableColumn(1); 1.167 +#ifndef DISABLE_TABLE_DELETION 1.168 + hideUI = (colCount == 1); 1.169 +#endif 1.170 + } 1.171 + else if (anonclass.EqualsLiteral("mozTableRemoveRow")) { 1.172 + DeleteTableRow(1); 1.173 +#ifndef DISABLE_TABLE_DELETION 1.174 + hideUI = (rowCount == 1); 1.175 +#endif 1.176 + } 1.177 + else 1.178 + return NS_OK; 1.179 + 1.180 + if (hideUI) { 1.181 + HideInlineTableEditingUI(); 1.182 + if (hideResizersWithInlineTableUI) 1.183 + HideResizers(); 1.184 + } 1.185 + } 1.186 + 1.187 + return NS_OK; 1.188 +} 1.189 + 1.190 +void 1.191 +nsHTMLEditor::AddMouseClickListener(nsIDOMElement * aElement) 1.192 +{ 1.193 + nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement)); 1.194 + if (evtTarget) { 1.195 + evtTarget->AddEventListener(NS_LITERAL_STRING("click"), 1.196 + mEventListener, true); 1.197 + } 1.198 +} 1.199 + 1.200 +void 1.201 +nsHTMLEditor::RemoveMouseClickListener(nsIDOMElement * aElement) 1.202 +{ 1.203 + nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement)); 1.204 + if (evtTarget) { 1.205 + evtTarget->RemoveEventListener(NS_LITERAL_STRING("click"), 1.206 + mEventListener, true); 1.207 + } 1.208 +} 1.209 + 1.210 +NS_IMETHODIMP 1.211 +nsHTMLEditor::RefreshInlineTableEditingUI() 1.212 +{ 1.213 + nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mInlineEditedCell); 1.214 + if (!htmlElement) { 1.215 + return NS_ERROR_NULL_POINTER; 1.216 + } 1.217 + 1.218 + int32_t xCell, yCell, wCell, hCell; 1.219 + GetElementOrigin(mInlineEditedCell, xCell, yCell); 1.220 + 1.221 + nsresult res = htmlElement->GetOffsetWidth(&wCell); 1.222 + NS_ENSURE_SUCCESS(res, res); 1.223 + res = htmlElement->GetOffsetHeight(&hCell); 1.224 + NS_ENSURE_SUCCESS(res, res); 1.225 + 1.226 + int32_t xHoriz = xCell + wCell/2; 1.227 + int32_t yVert = yCell + hCell/2; 1.228 + 1.229 + nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell); 1.230 + nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode); 1.231 + int32_t rowCount, colCount; 1.232 + res = GetTableSize(tableElement, &rowCount, &colCount); 1.233 + NS_ENSURE_SUCCESS(res, res); 1.234 + 1.235 + SetAnonymousElementPosition(xHoriz-10, yCell-7, mAddColumnBeforeButton); 1.236 +#ifdef DISABLE_TABLE_DELETION 1.237 + NS_NAMED_LITERAL_STRING(classStr, "class"); 1.238 + 1.239 + if (colCount== 1) { 1.240 + mRemoveColumnButton->SetAttribute(classStr, 1.241 + NS_LITERAL_STRING("hidden")); 1.242 + } 1.243 + else { 1.244 + bool hasClass = false; 1.245 + res = mRemoveColumnButton->HasAttribute(classStr, &hasClass); 1.246 + if (NS_SUCCEEDED(res) && hasClass) 1.247 + mRemoveColumnButton->RemoveAttribute(classStr); 1.248 +#endif 1.249 + SetAnonymousElementPosition(xHoriz-4, yCell-7, mRemoveColumnButton); 1.250 +#ifdef DISABLE_TABLE_DELETION 1.251 + } 1.252 +#endif 1.253 + SetAnonymousElementPosition(xHoriz+6, yCell-7, mAddColumnAfterButton); 1.254 + 1.255 + SetAnonymousElementPosition(xCell-7, yVert-10, mAddRowBeforeButton); 1.256 +#ifdef DISABLE_TABLE_DELETION 1.257 + if (rowCount== 1) { 1.258 + mRemoveRowButton->SetAttribute(classStr, 1.259 + NS_LITERAL_STRING("hidden")); 1.260 + } 1.261 + else { 1.262 + bool hasClass = false; 1.263 + res = mRemoveRowButton->HasAttribute(classStr, &hasClass); 1.264 + if (NS_SUCCEEDED(res) && hasClass) 1.265 + mRemoveRowButton->RemoveAttribute(classStr); 1.266 +#endif 1.267 + SetAnonymousElementPosition(xCell-7, yVert-4, mRemoveRowButton); 1.268 +#ifdef DISABLE_TABLE_DELETION 1.269 + } 1.270 +#endif 1.271 + SetAnonymousElementPosition(xCell-7, yVert+6, mAddRowAfterButton); 1.272 + 1.273 + return NS_OK; 1.274 +} 1.275 +