Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLInlineTableEditor.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla.org.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2003
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Daniel Glazman (glazman@netscape.com) (Original author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsHTMLEditor.h"
00039 #include "nsIDOMNSHTMLElement.h"
00040 #include "nsIDOMEventTarget.h"
00041 #include "nsIPresShell.h"
00042 #include "nsIDocumentObserver.h"
00043 #include "nsIContent.h"
00044 #include "nsHTMLEditUtils.h"
00045 #include "nsReadableUtils.h"
00046 
00047 // Uncomment the following line if you want to disable
00048 // table deletion when the only column/row is removed
00049 // #define DISABLE_TABLE_DELETION 1
00050 
00051 NS_IMETHODIMP
00052 nsHTMLEditor::SetInlineTableEditingEnabled(PRBool aIsEnabled)
00053 {
00054   mIsInlineTableEditingEnabled = aIsEnabled;
00055   return NS_OK;
00056 }
00057 
00058 NS_IMETHODIMP
00059 nsHTMLEditor::GetInlineTableEditingEnabled(PRBool * aIsEnabled)
00060 {
00061   *aIsEnabled = mIsInlineTableEditingEnabled;
00062   return NS_OK;
00063 }
00064 
00065 NS_IMETHODIMP
00066 nsHTMLEditor::ShowInlineTableEditingUI(nsIDOMElement * aCell)
00067 {
00068   NS_ENSURE_ARG_POINTER(aCell);
00069 
00070   // do nothing if aCell is not a table cell...
00071   if (!nsHTMLEditUtils::IsTableCell(aCell))
00072     return NS_OK;
00073 
00074   // the resizers and the shadow will be anonymous children of the body
00075   nsIDOMElement *bodyElement = GetRoot();
00076   if (!bodyElement)   return NS_ERROR_NULL_POINTER;
00077 
00078   CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
00079                          NS_LITERAL_STRING("mozTableAddColumnBefore"),
00080                          PR_FALSE, getter_AddRefs(mAddColumnBeforeButton));
00081   CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
00082                          NS_LITERAL_STRING("mozTableRemoveColumn"),
00083                          PR_FALSE, getter_AddRefs(mRemoveColumnButton));
00084   CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
00085                          NS_LITERAL_STRING("mozTableAddColumnAfter"),
00086                          PR_FALSE, getter_AddRefs(mAddColumnAfterButton));
00087 
00088   CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
00089                          NS_LITERAL_STRING("mozTableAddRowBefore"),
00090                          PR_FALSE, getter_AddRefs(mAddRowBeforeButton));
00091   CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
00092                          NS_LITERAL_STRING("mozTableRemoveRow"),
00093                          PR_FALSE, getter_AddRefs(mRemoveRowButton));
00094   CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
00095                          NS_LITERAL_STRING("mozTableAddRowAfter"),
00096                          PR_FALSE, getter_AddRefs(mAddRowAfterButton));
00097 
00098   AddMouseClickListener(mAddColumnBeforeButton);
00099   AddMouseClickListener(mRemoveColumnButton);
00100   AddMouseClickListener(mAddColumnAfterButton);
00101   AddMouseClickListener(mAddRowBeforeButton);
00102   AddMouseClickListener(mRemoveRowButton);
00103   AddMouseClickListener(mAddRowAfterButton);
00104 
00105   mInlineEditedCell = aCell;
00106   return RefreshInlineTableEditingUI();
00107 }
00108 
00109 NS_IMETHODIMP
00110 nsHTMLEditor::HideInlineTableEditingUI()
00111 {
00112   mInlineEditedCell = nsnull;
00113 
00114   RemoveMouseClickListener(mAddColumnBeforeButton);
00115   RemoveMouseClickListener(mRemoveColumnButton);
00116   RemoveMouseClickListener(mAddColumnAfterButton);
00117   RemoveMouseClickListener(mAddRowBeforeButton);
00118   RemoveMouseClickListener(mRemoveRowButton);
00119   RemoveMouseClickListener(mAddRowAfterButton);
00120 
00121   // get the presshell's document observer interface.
00122   nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
00123   if (!ps) return NS_ERROR_NOT_INITIALIZED;
00124 
00125   // get the root content node.
00126 
00127   nsIDOMElement *bodyElement = GetRoot();
00128 
00129   nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
00130   if (!bodyContent) return NS_ERROR_FAILURE;
00131 
00132   DeleteRefToAnonymousNode(mAddColumnBeforeButton, bodyContent, ps);
00133   mAddColumnBeforeButton = nsnull;
00134   DeleteRefToAnonymousNode(mRemoveColumnButton, bodyContent, ps);
00135   mRemoveColumnButton = nsnull;
00136   DeleteRefToAnonymousNode(mAddColumnAfterButton, bodyContent, ps);
00137   mAddColumnAfterButton = nsnull;
00138   DeleteRefToAnonymousNode(mAddRowBeforeButton, bodyContent, ps);
00139   mAddRowBeforeButton = nsnull;
00140   DeleteRefToAnonymousNode(mRemoveRowButton, bodyContent, ps);
00141   mRemoveRowButton = nsnull;
00142   DeleteRefToAnonymousNode(mAddRowAfterButton, bodyContent, ps);
00143   mAddRowAfterButton = nsnull;
00144 
00145   return NS_OK;
00146 }
00147 
00148 NS_IMETHODIMP
00149 nsHTMLEditor::DoInlineTableEditingAction(nsIDOMElement * aElement)
00150 {
00151   NS_ENSURE_ARG_POINTER(aElement);
00152   PRBool anonElement = PR_FALSE;
00153   if (aElement &&
00154       NS_SUCCEEDED(aElement->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)) &&
00155       anonElement) {
00156     nsAutoString anonclass;
00157     nsresult res = aElement->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
00158     if (NS_FAILED(res)) return res;
00159 
00160     if (!StringBeginsWith(anonclass, NS_LITERAL_STRING("mozTable")))
00161       return NS_OK;
00162 
00163     nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
00164     nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
00165     PRInt32 rowCount, colCount;
00166     res = GetTableSize(tableElement, &rowCount, &colCount);
00167     if (NS_FAILED(res)) return res;
00168 
00169     PRBool hideUI = PR_FALSE;
00170     PRBool hideResizersWithInlineTableUI = (mResizedObject == tableElement);
00171 
00172     if (anonclass.EqualsLiteral("mozTableAddColumnBefore"))
00173       InsertTableColumn(1, PR_FALSE);
00174     else if (anonclass.EqualsLiteral("mozTableAddColumnAfter"))
00175       InsertTableColumn(1, PR_TRUE);
00176     else if (anonclass.EqualsLiteral("mozTableAddRowBefore"))
00177       InsertTableRow(1, PR_FALSE);
00178     else if (anonclass.EqualsLiteral("mozTableAddRowAfter"))
00179       InsertTableRow(1, PR_TRUE);
00180     else if (anonclass.EqualsLiteral("mozTableRemoveColumn")) {
00181       DeleteTableColumn(1);
00182 #ifndef DISABLE_TABLE_DELETION
00183       hideUI = (colCount == 1);
00184 #endif
00185     }
00186     else if (anonclass.EqualsLiteral("mozTableRemoveRow")) {
00187       DeleteTableRow(1);
00188 #ifndef DISABLE_TABLE_DELETION
00189       hideUI = (rowCount == 1);
00190 #endif
00191     }
00192     else
00193       return NS_OK;
00194 
00195     if (hideUI) {
00196       HideInlineTableEditingUI();
00197       if (hideResizersWithInlineTableUI)
00198         HideResizers();
00199     }
00200   }
00201 
00202   return NS_OK;
00203 }
00204 
00205 void
00206 nsHTMLEditor::AddMouseClickListener(nsIDOMElement * aElement)
00207 {
00208   nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
00209   if (evtTarget)
00210     evtTarget->AddEventListener(NS_LITERAL_STRING("click"), mMouseListenerP, PR_TRUE);
00211 }
00212 
00213 void
00214 nsHTMLEditor::RemoveMouseClickListener(nsIDOMElement * aElement)
00215 {
00216   nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
00217   if (evtTarget)
00218     evtTarget->RemoveEventListener(NS_LITERAL_STRING("click"), mMouseListenerP, PR_TRUE);
00219 }
00220 
00221 NS_IMETHODIMP
00222 nsHTMLEditor::RefreshInlineTableEditingUI()
00223 {
00224   nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(mInlineEditedCell);
00225   if (!nsElement) {return NS_ERROR_NULL_POINTER; }
00226 
00227   PRInt32 xCell, yCell, wCell, hCell;
00228   GetElementOrigin(mInlineEditedCell, xCell, yCell);
00229 
00230   nsresult res = nsElement->GetOffsetWidth(&wCell);
00231   if (NS_FAILED(res)) return res;
00232   res = nsElement->GetOffsetHeight(&hCell);
00233   if (NS_FAILED(res)) return res;
00234 
00235   PRInt32 xHoriz = xCell + wCell/2;
00236   PRInt32 yVert  = yCell + hCell/2;
00237 
00238   nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
00239   nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
00240   PRInt32 rowCount, colCount;
00241   res = GetTableSize(tableElement, &rowCount, &colCount);
00242   if (NS_FAILED(res)) return res;
00243 
00244   SetAnonymousElementPosition(xHoriz-10, yCell-7,  mAddColumnBeforeButton);
00245 #ifdef DISABLE_TABLE_DELETION
00246   NS_NAMED_LITERAL_STRING(classStr, "class");
00247 
00248   if (colCount== 1) {
00249     mRemoveColumnButton->SetAttribute(classStr,
00250                                       NS_LITERAL_STRING("hidden"));
00251   }
00252   else {
00253     PRBool hasClass = PR_FALSE;
00254     res = mRemoveColumnButton->HasAttribute(classStr, &hasClass);
00255     if (NS_SUCCEEDED(res) && hasClass)
00256       mRemoveColumnButton->RemoveAttribute(classStr);
00257 #endif
00258     SetAnonymousElementPosition(xHoriz-4, yCell-7,  mRemoveColumnButton);
00259 #ifdef DISABLE_TABLE_DELETION
00260   }
00261 #endif
00262   SetAnonymousElementPosition(xHoriz+6, yCell-7,  mAddColumnAfterButton);
00263 
00264   SetAnonymousElementPosition(xCell-7, yVert-10,  mAddRowBeforeButton);
00265 #ifdef DISABLE_TABLE_DELETION
00266   if (rowCount== 1) {
00267     mRemoveRowButton->SetAttribute(classStr,
00268                                    NS_LITERAL_STRING("hidden"));
00269   }
00270   else {
00271     PRBool hasClass = PR_FALSE;
00272     res = mRemoveRowButton->HasAttribute(classStr, &hasClass);
00273     if (NS_SUCCEEDED(res) && hasClass)
00274       mRemoveRowButton->RemoveAttribute(classStr);
00275 #endif
00276     SetAnonymousElementPosition(xCell-7, yVert-4,  mRemoveRowButton);
00277 #ifdef DISABLE_TABLE_DELETION
00278   }
00279 #endif
00280   SetAnonymousElementPosition(xCell-7, yVert+6,  mAddRowAfterButton);
00281 
00282   return NS_OK;
00283 }
00284