1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is Mozilla.org.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corp.
18
* Portions created by the Initial Developer are Copyright (C) 2003
19
* the Initial Developer. All Rights Reserved.
22
* Daniel Glazman (glazman@netscape.com) (Original author)
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
38
#include "nsHTMLEditor.h"
39
#include "nsIDOMNSHTMLElement.h"
40
#include "nsIDOMEventTarget.h"
41
#include "nsIPresShell.h"
42
#include "nsIDocumentObserver.h"
43
#include "nsIContent.h"
44
#include "nsHTMLEditUtils.h"
45
#include "nsReadableUtils.h"
47
// Uncomment the following line if you want to disable
48
// table deletion when the only column/row is removed
49
// #define DISABLE_TABLE_DELETION 1
52
nsHTMLEditor::SetInlineTableEditingEnabled(PRBool aIsEnabled)
54
mIsInlineTableEditingEnabled = aIsEnabled;
59
nsHTMLEditor::GetInlineTableEditingEnabled(PRBool * aIsEnabled)
61
*aIsEnabled = mIsInlineTableEditingEnabled;
66
nsHTMLEditor::ShowInlineTableEditingUI(nsIDOMElement * aCell)
68
NS_ENSURE_ARG_POINTER(aCell);
70
// do nothing if aCell is not a table cell...
71
if (!nsHTMLEditUtils::IsTableCell(aCell))
74
// the resizers and the shadow will be anonymous children of the body
75
nsCOMPtr<nsIDOMElement> bodyElement;
76
nsresult res = nsEditor::GetRootElement(getter_AddRefs(bodyElement));
77
if (NS_FAILED(res)) return res;
78
if (!bodyElement) return NS_ERROR_NULL_POINTER;
80
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
81
NS_LITERAL_STRING("mozTableAddColumnBefore"),
82
PR_FALSE, getter_AddRefs(mAddColumnBeforeButton));
83
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
84
NS_LITERAL_STRING("mozTableRemoveColumn"),
85
PR_FALSE, getter_AddRefs(mRemoveColumnButton));
86
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
87
NS_LITERAL_STRING("mozTableAddColumnAfter"),
88
PR_FALSE, getter_AddRefs(mAddColumnAfterButton));
90
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
91
NS_LITERAL_STRING("mozTableAddRowBefore"),
92
PR_FALSE, getter_AddRefs(mAddRowBeforeButton));
93
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
94
NS_LITERAL_STRING("mozTableRemoveRow"),
95
PR_FALSE, getter_AddRefs(mRemoveRowButton));
96
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
97
NS_LITERAL_STRING("mozTableAddRowAfter"),
98
PR_FALSE, getter_AddRefs(mAddRowAfterButton));
100
AddMouseClickListener(mAddColumnBeforeButton);
101
AddMouseClickListener(mRemoveColumnButton);
102
AddMouseClickListener(mAddColumnAfterButton);
103
AddMouseClickListener(mAddRowBeforeButton);
104
AddMouseClickListener(mRemoveRowButton);
105
AddMouseClickListener(mAddRowAfterButton);
107
mInlineEditedCell = aCell;
108
return RefreshInlineTableEditingUI();
112
nsHTMLEditor::HideInlineTableEditingUI()
114
mInlineEditedCell = nsnull;
116
RemoveMouseClickListener(mAddColumnBeforeButton);
117
RemoveMouseClickListener(mRemoveColumnButton);
118
RemoveMouseClickListener(mAddColumnAfterButton);
119
RemoveMouseClickListener(mAddRowBeforeButton);
120
RemoveMouseClickListener(mRemoveRowButton);
121
RemoveMouseClickListener(mAddRowAfterButton);
123
// get the presshell's document observer interface.
124
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
125
if (!ps) return NS_ERROR_NOT_INITIALIZED;
127
nsCOMPtr<nsIDocumentObserver> docObserver(do_QueryInterface(ps));
128
if (!docObserver) return NS_ERROR_FAILURE;
130
// get the root content node.
132
nsCOMPtr<nsIDOMElement> bodyElement;
133
nsresult res = nsEditor::GetRootElement(getter_AddRefs(bodyElement));
134
if (NS_FAILED(res)) return res;
136
nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
137
if (!bodyContent) return NS_ERROR_FAILURE;
139
DeleteRefToAnonymousNode(mAddColumnBeforeButton, bodyContent, docObserver);
140
mAddColumnBeforeButton = nsnull;
141
DeleteRefToAnonymousNode(mRemoveColumnButton, bodyContent, docObserver);
142
mRemoveColumnButton = nsnull;
143
DeleteRefToAnonymousNode(mAddColumnAfterButton, bodyContent, docObserver);
144
mAddColumnAfterButton = nsnull;
145
DeleteRefToAnonymousNode(mAddRowBeforeButton, bodyContent, docObserver);
146
mAddRowBeforeButton = nsnull;
147
DeleteRefToAnonymousNode(mRemoveRowButton, bodyContent, docObserver);
148
mRemoveRowButton = nsnull;
149
DeleteRefToAnonymousNode(mAddRowAfterButton, bodyContent, docObserver);
150
mAddRowAfterButton = nsnull;
156
nsHTMLEditor::DoInlineTableEditingAction(nsIDOMElement * aElement)
158
NS_ENSURE_ARG_POINTER(aElement);
159
PRBool anonElement = PR_FALSE;
161
NS_SUCCEEDED(aElement->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)) &&
163
nsAutoString anonclass;
164
nsresult res = aElement->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
165
if (NS_FAILED(res)) return res;
167
if (!StringBeginsWith(anonclass, NS_LITERAL_STRING("mozTable")))
170
nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
171
nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
172
PRInt32 rowCount, colCount;
173
res = GetTableSize(tableElement, &rowCount, &colCount);
174
if (NS_FAILED(res)) return res;
176
PRBool hideUI = PR_FALSE;
177
PRBool hideResizersWithInlineTableUI = (mResizedObject == tableElement);
179
if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddColumnBefore")))
180
InsertTableColumn(1, PR_FALSE);
181
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddColumnAfter")))
182
InsertTableColumn(1, PR_TRUE);
183
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddRowBefore")))
184
InsertTableRow(1, PR_FALSE);
185
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableAddRowAfter")))
186
InsertTableRow(1, PR_TRUE);
187
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableRemoveColumn"))) {
188
DeleteTableColumn(1);
189
#ifndef DISABLE_TABLE_DELETION
190
hideUI = (colCount == 1);
193
else if (anonclass.Equals(NS_LITERAL_STRING("mozTableRemoveRow"))) {
195
#ifndef DISABLE_TABLE_DELETION
196
hideUI = (rowCount == 1);
203
HideInlineTableEditingUI();
204
if (hideResizersWithInlineTableUI)
213
nsHTMLEditor::AddMouseClickListener(nsIDOMElement * aElement)
215
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
217
evtTarget->AddEventListener(NS_LITERAL_STRING("click"), mMouseListenerP, PR_TRUE);
221
nsHTMLEditor::RemoveMouseClickListener(nsIDOMElement * aElement)
223
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
225
evtTarget->RemoveEventListener(NS_LITERAL_STRING("click"), mMouseListenerP, PR_TRUE);
229
nsHTMLEditor::RefreshInlineTableEditingUI()
231
nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(mInlineEditedCell);
232
if (!nsElement) {return NS_ERROR_NULL_POINTER; }
234
PRInt32 xCell, yCell, wCell, hCell;
235
GetElementOrigin(mInlineEditedCell, xCell, yCell);
237
nsresult res = nsElement->GetOffsetWidth(&wCell);
238
if (NS_FAILED(res)) return res;
239
res = nsElement->GetOffsetHeight(&hCell);
240
if (NS_FAILED(res)) return res;
242
PRInt32 xHoriz = xCell + wCell/2;
243
PRInt32 yVert = yCell + hCell/2;
245
nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
246
nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
247
PRInt32 rowCount, colCount;
248
res = GetTableSize(tableElement, &rowCount, &colCount);
249
if (NS_FAILED(res)) return res;
251
SetAnonymousElementPosition(xHoriz-10, yCell-7, mAddColumnBeforeButton);
252
#ifdef DISABLE_TABLE_DELETION
253
NS_NAMED_LITERAL_STRING(classStr, "class");
256
mRemoveColumnButton->SetAttribute(classStr,
257
NS_LITERAL_STRING("hidden"));
260
PRBool hasClass = PR_FALSE;
261
res = mRemoveColumnButton->HasAttribute(classStr, &hasClass);
262
if (NS_SUCCEEDED(res) && hasClass)
263
mRemoveColumnButton->RemoveAttribute(classStr);
265
SetAnonymousElementPosition(xHoriz-4, yCell-7, mRemoveColumnButton);
266
#ifdef DISABLE_TABLE_DELETION
269
SetAnonymousElementPosition(xHoriz+6, yCell-7, mAddColumnAfterButton);
271
SetAnonymousElementPosition(xCell-7, yVert-10, mAddRowBeforeButton);
272
#ifdef DISABLE_TABLE_DELETION
274
mRemoveRowButton->SetAttribute(classStr,
275
NS_LITERAL_STRING("hidden"));
278
PRBool hasClass = PR_FALSE;
279
res = mRemoveRowButton->HasAttribute(classStr, &hasClass);
280
if (NS_SUCCEEDED(res) && hasClass)
281
mRemoveRowButton->RemoveAttribute(classStr);
283
SetAnonymousElementPosition(xCell-7, yVert-4, mRemoveRowButton);
284
#ifdef DISABLE_TABLE_DELETION
287
SetAnonymousElementPosition(xCell-7, yVert+6, mAddRowAfterButton);