Bumping manifests a=b2g-bump
[gecko.git] / editor / libeditor / nsHTMLInlineTableEditor.cpp
blob8928c148deab3050bafeda4fd8b8f6ffa6be2977
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/dom/Element.h"
6 #include "nsAString.h"
7 #include "nsCOMPtr.h"
8 #include "nsDebug.h"
9 #include "nsError.h"
10 #include "nsHTMLEditUtils.h"
11 #include "nsHTMLEditor.h"
12 #include "nsIContent.h"
13 #include "nsIDOMElement.h"
14 #include "nsIDOMEventTarget.h"
15 #include "nsIDOMHTMLElement.h"
16 #include "nsIDOMNode.h"
17 #include "nsIHTMLEditor.h"
18 #include "nsIHTMLObjectResizer.h"
19 #include "nsIPresShell.h"
20 #include "nsLiteralString.h"
21 #include "nsReadableUtils.h"
22 #include "nsString.h"
23 #include "nscore.h"
25 // Uncomment the following line if you want to disable
26 // table deletion when the only column/row is removed
27 // #define DISABLE_TABLE_DELETION 1
29 NS_IMETHODIMP
30 nsHTMLEditor::SetInlineTableEditingEnabled(bool aIsEnabled)
32 mIsInlineTableEditingEnabled = aIsEnabled;
33 return NS_OK;
36 NS_IMETHODIMP
37 nsHTMLEditor::GetInlineTableEditingEnabled(bool * aIsEnabled)
39 *aIsEnabled = mIsInlineTableEditingEnabled;
40 return NS_OK;
43 NS_IMETHODIMP
44 nsHTMLEditor::ShowInlineTableEditingUI(nsIDOMElement * aCell)
46 NS_ENSURE_ARG_POINTER(aCell);
48 // do nothing if aCell is not a table cell...
49 if (!nsHTMLEditUtils::IsTableCell(aCell))
50 return NS_OK;
52 if (mInlineEditedCell) {
53 NS_ERROR("call HideInlineTableEditingUI first");
54 return NS_ERROR_UNEXPECTED;
57 // the resizers and the shadow will be anonymous children of the body
58 nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
59 NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
61 CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
62 NS_LITERAL_STRING("mozTableAddColumnBefore"),
63 false, getter_AddRefs(mAddColumnBeforeButton));
64 CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
65 NS_LITERAL_STRING("mozTableRemoveColumn"),
66 false, getter_AddRefs(mRemoveColumnButton));
67 CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
68 NS_LITERAL_STRING("mozTableAddColumnAfter"),
69 false, getter_AddRefs(mAddColumnAfterButton));
71 CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
72 NS_LITERAL_STRING("mozTableAddRowBefore"),
73 false, getter_AddRefs(mAddRowBeforeButton));
74 CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
75 NS_LITERAL_STRING("mozTableRemoveRow"),
76 false, getter_AddRefs(mRemoveRowButton));
77 CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
78 NS_LITERAL_STRING("mozTableAddRowAfter"),
79 false, getter_AddRefs(mAddRowAfterButton));
81 AddMouseClickListener(mAddColumnBeforeButton);
82 AddMouseClickListener(mRemoveColumnButton);
83 AddMouseClickListener(mAddColumnAfterButton);
84 AddMouseClickListener(mAddRowBeforeButton);
85 AddMouseClickListener(mRemoveRowButton);
86 AddMouseClickListener(mAddRowAfterButton);
88 mInlineEditedCell = aCell;
89 return RefreshInlineTableEditingUI();
92 NS_IMETHODIMP
93 nsHTMLEditor::HideInlineTableEditingUI()
95 mInlineEditedCell = nullptr;
97 RemoveMouseClickListener(mAddColumnBeforeButton);
98 RemoveMouseClickListener(mRemoveColumnButton);
99 RemoveMouseClickListener(mAddColumnAfterButton);
100 RemoveMouseClickListener(mAddRowBeforeButton);
101 RemoveMouseClickListener(mRemoveRowButton);
102 RemoveMouseClickListener(mAddRowAfterButton);
104 // get the presshell's document observer interface.
105 nsCOMPtr<nsIPresShell> ps = GetPresShell();
106 // We allow the pres shell to be null; when it is, we presume there
107 // are no document observers to notify, but we still want to
108 // UnbindFromTree.
110 // get the root content node.
111 nsCOMPtr<nsIContent> bodyContent = GetRoot();
112 NS_ENSURE_TRUE(bodyContent, NS_ERROR_FAILURE);
114 DeleteRefToAnonymousNode(mAddColumnBeforeButton, bodyContent, ps);
115 mAddColumnBeforeButton = nullptr;
116 DeleteRefToAnonymousNode(mRemoveColumnButton, bodyContent, ps);
117 mRemoveColumnButton = nullptr;
118 DeleteRefToAnonymousNode(mAddColumnAfterButton, bodyContent, ps);
119 mAddColumnAfterButton = nullptr;
120 DeleteRefToAnonymousNode(mAddRowBeforeButton, bodyContent, ps);
121 mAddRowBeforeButton = nullptr;
122 DeleteRefToAnonymousNode(mRemoveRowButton, bodyContent, ps);
123 mRemoveRowButton = nullptr;
124 DeleteRefToAnonymousNode(mAddRowAfterButton, bodyContent, ps);
125 mAddRowAfterButton = nullptr;
127 return NS_OK;
130 NS_IMETHODIMP
131 nsHTMLEditor::DoInlineTableEditingAction(nsIDOMElement * aElement)
133 NS_ENSURE_ARG_POINTER(aElement);
134 bool anonElement = false;
135 if (aElement &&
136 NS_SUCCEEDED(aElement->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)) &&
137 anonElement) {
138 nsAutoString anonclass;
139 nsresult res = aElement->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
140 NS_ENSURE_SUCCESS(res, res);
142 if (!StringBeginsWith(anonclass, NS_LITERAL_STRING("mozTable")))
143 return NS_OK;
145 nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
146 nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
147 int32_t rowCount, colCount;
148 res = GetTableSize(tableElement, &rowCount, &colCount);
149 NS_ENSURE_SUCCESS(res, res);
151 bool hideUI = false;
152 bool hideResizersWithInlineTableUI = (mResizedObject == tableElement);
154 if (anonclass.EqualsLiteral("mozTableAddColumnBefore"))
155 InsertTableColumn(1, false);
156 else if (anonclass.EqualsLiteral("mozTableAddColumnAfter"))
157 InsertTableColumn(1, true);
158 else if (anonclass.EqualsLiteral("mozTableAddRowBefore"))
159 InsertTableRow(1, false);
160 else if (anonclass.EqualsLiteral("mozTableAddRowAfter"))
161 InsertTableRow(1, true);
162 else if (anonclass.EqualsLiteral("mozTableRemoveColumn")) {
163 DeleteTableColumn(1);
164 #ifndef DISABLE_TABLE_DELETION
165 hideUI = (colCount == 1);
166 #endif
168 else if (anonclass.EqualsLiteral("mozTableRemoveRow")) {
169 DeleteTableRow(1);
170 #ifndef DISABLE_TABLE_DELETION
171 hideUI = (rowCount == 1);
172 #endif
174 else
175 return NS_OK;
177 if (hideUI) {
178 HideInlineTableEditingUI();
179 if (hideResizersWithInlineTableUI)
180 HideResizers();
184 return NS_OK;
187 void
188 nsHTMLEditor::AddMouseClickListener(nsIDOMElement * aElement)
190 nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
191 if (evtTarget) {
192 evtTarget->AddEventListener(NS_LITERAL_STRING("click"),
193 mEventListener, true);
197 void
198 nsHTMLEditor::RemoveMouseClickListener(nsIDOMElement * aElement)
200 nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
201 if (evtTarget) {
202 evtTarget->RemoveEventListener(NS_LITERAL_STRING("click"),
203 mEventListener, true);
207 NS_IMETHODIMP
208 nsHTMLEditor::RefreshInlineTableEditingUI()
210 nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mInlineEditedCell);
211 if (!htmlElement) {
212 return NS_ERROR_NULL_POINTER;
215 int32_t xCell, yCell, wCell, hCell;
216 GetElementOrigin(mInlineEditedCell, xCell, yCell);
218 nsresult res = htmlElement->GetOffsetWidth(&wCell);
219 NS_ENSURE_SUCCESS(res, res);
220 res = htmlElement->GetOffsetHeight(&hCell);
221 NS_ENSURE_SUCCESS(res, res);
223 int32_t xHoriz = xCell + wCell/2;
224 int32_t yVert = yCell + hCell/2;
226 nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
227 nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
228 int32_t rowCount, colCount;
229 res = GetTableSize(tableElement, &rowCount, &colCount);
230 NS_ENSURE_SUCCESS(res, res);
232 SetAnonymousElementPosition(xHoriz-10, yCell-7, mAddColumnBeforeButton);
233 #ifdef DISABLE_TABLE_DELETION
234 NS_NAMED_LITERAL_STRING(classStr, "class");
236 if (colCount== 1) {
237 mRemoveColumnButton->SetAttribute(classStr,
238 NS_LITERAL_STRING("hidden"));
240 else {
241 bool hasClass = false;
242 res = mRemoveColumnButton->HasAttribute(classStr, &hasClass);
243 if (NS_SUCCEEDED(res) && hasClass)
244 mRemoveColumnButton->RemoveAttribute(classStr);
245 #endif
246 SetAnonymousElementPosition(xHoriz-4, yCell-7, mRemoveColumnButton);
247 #ifdef DISABLE_TABLE_DELETION
249 #endif
250 SetAnonymousElementPosition(xHoriz+6, yCell-7, mAddColumnAfterButton);
252 SetAnonymousElementPosition(xCell-7, yVert-10, mAddRowBeforeButton);
253 #ifdef DISABLE_TABLE_DELETION
254 if (rowCount== 1) {
255 mRemoveRowButton->SetAttribute(classStr,
256 NS_LITERAL_STRING("hidden"));
258 else {
259 bool hasClass = false;
260 res = mRemoveRowButton->HasAttribute(classStr, &hasClass);
261 if (NS_SUCCEEDED(res) && hasClass)
262 mRemoveRowButton->RemoveAttribute(classStr);
263 #endif
264 SetAnonymousElementPosition(xCell-7, yVert-4, mRemoveRowButton);
265 #ifdef DISABLE_TABLE_DELETION
267 #endif
268 SetAnonymousElementPosition(xCell-7, yVert+6, mAddRowAfterButton);
270 return NS_OK;