Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLObjectResizer.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla.org.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corp.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Daniel Glazman (glazman@netscape.com) (Original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsHTMLObjectResizer.h"
00040 
00041 #include "nsIDOMEventTarget.h"
00042 #include "nsIDOMNSHTMLElement.h"
00043 #include "nsIDOMEventReceiver.h"
00044 #include "nsIDOMText.h"
00045 
00046 #include "nsIDOMCSSValue.h"
00047 #include "nsIDOMCSSPrimitiveValue.h"
00048 
00049 #include "nsIContent.h"
00050 #include "nsIDocument.h"
00051 #include "nsIDocumentObserver.h"
00052 #include "nsIEditor.h"
00053 #include "nsIPresShell.h"
00054 #include "nsIScriptGlobalObject.h"
00055 
00056 #include "nsHTMLEditor.h"
00057 #include "nsEditor.h"
00058 #include "nsEditorUtils.h"
00059 #include "nsHTMLEditUtils.h"
00060 
00061 #include "nsPoint.h"
00062 
00063 #include "nsIPrefBranch.h"
00064 #include "nsIPrefService.h"
00065 #include "nsIServiceManager.h"
00066 
00067 #include "nsPresContext.h"
00068 #include "nsILookAndFeel.h"
00069 #include "nsWidgetsCID.h"
00070 
00071 class nsHTMLEditUtils;
00072 
00073 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
00074 
00075 // ==================================================================
00076 // DocumentResizeEventListener
00077 // ==================================================================
00078 NS_IMPL_ISUPPORTS1(DocumentResizeEventListener, nsIDOMEventListener)
00079 
00080 DocumentResizeEventListener::DocumentResizeEventListener(nsIHTMLEditor * aEditor) 
00081 {
00082   mEditor = do_GetWeakReference(aEditor);
00083 }
00084 
00085 DocumentResizeEventListener::~DocumentResizeEventListener()
00086 {
00087 }
00088 
00089 NS_IMETHODIMP
00090 DocumentResizeEventListener::HandleEvent(nsIDOMEvent* aMouseEvent)
00091 {
00092   nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
00093   if (objectResizer)
00094     return objectResizer->RefreshResizers();
00095   return NS_OK;
00096 }
00097 
00098 // ==================================================================
00099 // ResizerSelectionListener
00100 // ==================================================================
00101 
00102 NS_IMPL_ISUPPORTS1(ResizerSelectionListener, nsISelectionListener)
00103 
00104 ResizerSelectionListener::ResizerSelectionListener(nsIHTMLEditor * aEditor)
00105 {
00106   mEditor = do_GetWeakReference(aEditor);
00107 }
00108 
00109 ResizerSelectionListener::~ResizerSelectionListener()
00110 {
00111 }
00112 
00113 NS_IMETHODIMP
00114 ResizerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *aSelection, PRInt16 aReason)
00115 {
00116   if ((aReason & (nsISelectionListener::MOUSEDOWN_REASON |
00117                   nsISelectionListener::KEYPRESS_REASON |
00118                   nsISelectionListener::SELECTALL_REASON)) && aSelection) 
00119   {
00120     // the selection changed and we need to check if we have to
00121     // hide and/or redisplay resizing handles
00122     nsCOMPtr<nsIHTMLEditor> editor = do_QueryReferent(mEditor);
00123     if (editor)
00124       editor->CheckSelectionStateForAnonymousButtons(aSelection);
00125   }
00126 
00127   return NS_OK;
00128 }
00129 
00130 // ==================================================================
00131 // ResizerMouseMotionListener
00132 // ==================================================================
00133 
00134 NS_IMPL_ISUPPORTS2(ResizerMouseMotionListener, nsIDOMEventListener, nsIDOMMouseMotionListener)
00135 
00136 ResizerMouseMotionListener::ResizerMouseMotionListener(nsIHTMLEditor * aEditor)
00137 {
00138   mEditor = do_GetWeakReference(aEditor);
00139 }
00140 
00141 ResizerMouseMotionListener::~ResizerMouseMotionListener() 
00142 {
00143 }
00144 
00145 
00146 NS_IMETHODIMP
00147 ResizerMouseMotionListener::MouseMove(nsIDOMEvent* aMouseEvent)
00148 {
00149   nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
00150   if (!mouseEvent) {
00151     //non-ui event passed in.  bad things.
00152     return NS_OK;
00153   }
00154 
00155   // Don't do anything special if not an HTML object resizer editor
00156   nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
00157   if (objectResizer)
00158   {
00159     // check if we have to redisplay a resizing shadow
00160     objectResizer->MouseMove(aMouseEvent);
00161   }
00162 
00163   return NS_OK;
00164 }
00165 
00166 NS_IMETHODIMP
00167 ResizerMouseMotionListener::HandleEvent(nsIDOMEvent* aMouseEvent)
00168 {
00169   return NS_OK;
00170 }
00171 
00172 NS_IMETHODIMP
00173 ResizerMouseMotionListener::DragMove(nsIDOMEvent* aMouseEvent)
00174 {
00175   return NS_OK;
00176 }
00177 
00178 // ==================================================================
00179 // nsHTMLEditor
00180 // ==================================================================
00181 
00182 nsresult
00183 nsHTMLEditor::CreateResizer(nsIDOMElement ** aReturn, PRInt16 aLocation, nsIDOMNode * aParentNode)
00184 {
00185   nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
00186                                         aParentNode,
00187                                         NS_LITERAL_STRING("mozResizer"),
00188                                         PR_FALSE,
00189                                         aReturn);
00190 
00191   if (NS_FAILED(res)) return res;
00192   if (!*aReturn)
00193     return NS_ERROR_FAILURE;
00194 
00195   // add the mouse listener so we can detect a click on a resizer
00196   nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
00197   evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mMouseListenerP, PR_TRUE);
00198 
00199   nsAutoString locationStr;
00200   switch (aLocation) {
00201     case nsIHTMLObjectResizer::eTopLeft:
00202       locationStr = kTopLeft;
00203       break;
00204     case nsIHTMLObjectResizer::eTop:
00205       locationStr = kTop;
00206       break;
00207     case nsIHTMLObjectResizer::eTopRight:
00208       locationStr = kTopRight;
00209       break;
00210 
00211     case nsIHTMLObjectResizer::eLeft:
00212       locationStr = kLeft;
00213       break;
00214     case nsIHTMLObjectResizer::eRight:
00215       locationStr = kRight;
00216       break;
00217 
00218     case nsIHTMLObjectResizer::eBottomLeft:
00219       locationStr = kBottomLeft;
00220       break;
00221     case nsIHTMLObjectResizer::eBottom:
00222       locationStr = kBottom;
00223       break;
00224     case nsIHTMLObjectResizer::eBottomRight:
00225       locationStr = kBottomRight;
00226       break;
00227   }
00228 
00229   res = (*aReturn)->SetAttribute(NS_LITERAL_STRING("anonlocation"),
00230                                  locationStr);
00231   return res;
00232 }
00233 
00234 nsresult
00235 nsHTMLEditor::CreateShadow(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode,
00236                            nsIDOMElement * aOriginalObject)
00237 {
00238   // let's create an image through the element factory
00239   nsAutoString name;
00240   if (nsHTMLEditUtils::IsImage(aOriginalObject))
00241     name.AssignLiteral("img");
00242   else
00243     name.AssignLiteral("span");
00244   nsresult res = CreateAnonymousElement(name,
00245                                         aParentNode,
00246                                         NS_LITERAL_STRING("mozResizingShadow"),
00247                                         PR_TRUE,
00248                                         aReturn);
00249 
00250   if (!*aReturn)
00251     return NS_ERROR_FAILURE;
00252 
00253   return res;
00254 }
00255 
00256 nsresult
00257 nsHTMLEditor::CreateResizingInfo(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode)
00258 {
00259   // let's create an info box through the element factory
00260   nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
00261                                         aParentNode,
00262                                         NS_LITERAL_STRING("mozResizingInfo"),
00263                                         PR_TRUE,
00264                                         aReturn);
00265 
00266   if (!*aReturn)
00267     return NS_ERROR_FAILURE;
00268 
00269   return res;
00270 }
00271 
00272 nsresult
00273 nsHTMLEditor::SetAllResizersPosition()
00274 {
00275   if (!mTopLeftHandle)
00276     return NS_ERROR_FAILURE;
00277 
00278   PRInt32 x = mResizedObjectX;
00279   PRInt32 y = mResizedObjectY;
00280   PRInt32 w = mResizedObjectWidth;
00281   PRInt32 h = mResizedObjectHeight;
00282 
00283   // now let's place all the resizers around the image
00284 
00285   // get the size of resizers
00286   nsAutoString value;
00287   float resizerWidth, resizerHeight;
00288   nsCOMPtr<nsIAtom> dummyUnit;
00289   mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsEditProperty::cssWidth, value);
00290   mHTMLCSSUtils->ParseLength(value, &resizerWidth, getter_AddRefs(dummyUnit));
00291   mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsEditProperty::cssHeight, value);
00292   mHTMLCSSUtils->ParseLength(value, &resizerHeight, getter_AddRefs(dummyUnit));
00293 
00294   PRInt32 rw  = (PRInt32)((resizerWidth + 1) / 2);
00295   PRInt32 rh =  (PRInt32)((resizerHeight+ 1) / 2);
00296 
00297   SetAnonymousElementPosition(x-rw,     y-rh, mTopLeftHandle);
00298   SetAnonymousElementPosition(x+w/2-rw, y-rh, mTopHandle);
00299   SetAnonymousElementPosition(x+w-rw-1, y-rh, mTopRightHandle);
00300 
00301   SetAnonymousElementPosition(x-rw,     y+h/2-rh, mLeftHandle);
00302   SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, mRightHandle);
00303 
00304   SetAnonymousElementPosition(x-rw,     y+h-rh-1, mBottomLeftHandle);
00305   SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, mBottomHandle);
00306   SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, mBottomRightHandle);
00307 
00308   return NS_OK;
00309 }
00310 
00311 NS_IMETHODIMP
00312 nsHTMLEditor::RefreshResizers()
00313 {
00314   // nothing to do if resizers are not displayed...
00315   if (!mResizedObject)
00316     return NS_OK;
00317 
00318   nsresult res = GetPositionAndDimensions(mResizedObject,
00319                                           mResizedObjectX,
00320                                           mResizedObjectY,
00321                                           mResizedObjectWidth,
00322                                           mResizedObjectHeight,
00323                                           mResizedObjectBorderLeft,
00324                                           mResizedObjectBorderTop,
00325                                           mResizedObjectMarginLeft,
00326                                           mResizedObjectMarginTop);
00327 
00328   if (NS_FAILED(res)) return res;
00329   res = SetAllResizersPosition();
00330   if (NS_FAILED(res)) return res;
00331   return SetShadowPosition(mResizingShadow, mResizedObject,
00332                            mResizedObjectX, mResizedObjectY);
00333 }
00334 
00335 NS_IMETHODIMP 
00336 nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
00337 {
00338   NS_ENSURE_ARG_POINTER(aResizedElement);
00339   mResizedObject = aResizedElement;
00340 
00341   // the resizers and the shadow will be anonymous children of the body
00342   nsIDOMElement *bodyElement = GetRoot();
00343   if (!bodyElement)   return NS_ERROR_NULL_POINTER;
00344 
00345   // let's create the resizers
00346   nsresult res;
00347   res = CreateResizer(getter_AddRefs(mTopLeftHandle),
00348                       nsIHTMLObjectResizer::eTopLeft,     bodyElement);
00349   if (NS_FAILED(res)) return res;
00350   res = CreateResizer(getter_AddRefs(mTopHandle),
00351                       nsIHTMLObjectResizer::eTop,         bodyElement);
00352   if (NS_FAILED(res)) return res;
00353   res = CreateResizer(getter_AddRefs(mTopRightHandle),
00354                       nsIHTMLObjectResizer::eTopRight,    bodyElement);
00355   if (NS_FAILED(res)) return res;
00356 
00357   res = CreateResizer(getter_AddRefs(mLeftHandle),
00358                       nsIHTMLObjectResizer::eLeft,        bodyElement);
00359   if (NS_FAILED(res)) return res;
00360   res = CreateResizer(getter_AddRefs(mRightHandle),
00361                       nsIHTMLObjectResizer::eRight,       bodyElement);
00362   if (NS_FAILED(res)) return res;
00363 
00364   res = CreateResizer(getter_AddRefs(mBottomLeftHandle),
00365                       nsIHTMLObjectResizer::eBottomLeft,  bodyElement);
00366   if (NS_FAILED(res)) return res;
00367   res = CreateResizer(getter_AddRefs(mBottomHandle),
00368                       nsIHTMLObjectResizer::eBottom,      bodyElement);
00369   if (NS_FAILED(res)) return res;
00370   res = CreateResizer(getter_AddRefs(mBottomRightHandle),
00371                       nsIHTMLObjectResizer::eBottomRight, bodyElement);
00372   if (NS_FAILED(res)) return res;
00373 
00374   res = GetPositionAndDimensions(aResizedElement,
00375                                  mResizedObjectX,
00376                                  mResizedObjectY,
00377                                  mResizedObjectWidth,
00378                                  mResizedObjectHeight,
00379                                  mResizedObjectBorderLeft,
00380                                  mResizedObjectBorderTop,
00381                                  mResizedObjectMarginLeft,
00382                                  mResizedObjectMarginTop);
00383   if (NS_FAILED(res)) return res;
00384 
00385   // and let's set their absolute positions in the document
00386   res = SetAllResizersPosition();
00387   if (NS_FAILED(res)) return res;
00388 
00389   // now, let's create the resizing shadow
00390   res = CreateShadow(getter_AddRefs(mResizingShadow), bodyElement,
00391                      aResizedElement);
00392   if (NS_FAILED(res)) return res;
00393   // and set its position
00394   res = SetShadowPosition(mResizingShadow, mResizedObject,
00395                           mResizedObjectX, mResizedObjectY);
00396   if (NS_FAILED(res)) return res;
00397 
00398   // and then the resizing info tooltip
00399   res = CreateResizingInfo(getter_AddRefs(mResizingInfo), bodyElement);
00400   if (NS_FAILED(res)) return res;
00401 
00402 
00403   // and listen to the "resize" event on the window
00404   // first, get the script global object from the document...
00405   nsCOMPtr<nsIDOMDocument> domDoc;
00406   GetDocument(getter_AddRefs(domDoc));
00407   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
00408   if (!doc) return NS_ERROR_NULL_POINTER;
00409 
00410   nsIScriptGlobalObject *global = doc->GetScriptGlobalObject();
00411   if (!global) { return NS_ERROR_NULL_POINTER; }
00412 
00413   mResizeEventListenerP = new DocumentResizeEventListener(this);
00414   if (!mResizeEventListenerP) { return NS_ERROR_OUT_OF_MEMORY; }
00415   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(global);
00416   res = target->AddEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, PR_FALSE);
00417 
00418   aResizedElement->SetAttribute(NS_LITERAL_STRING("_moz_resizing"), NS_LITERAL_STRING("true"));
00419   return res;
00420 }
00421 
00422 NS_IMETHODIMP 
00423 nsHTMLEditor::HideResizers(void)
00424 {
00425   if (!mResizedObject)
00426     return NS_OK;
00427 
00428   // get the presshell's document observer interface.
00429   nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
00430   if (!ps) return NS_ERROR_NOT_INITIALIZED;
00431 
00432   // get the root content node.
00433 
00434   nsIDOMElement *bodyElement = GetRoot();
00435 
00436   nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
00437   if (!bodyContent) return NS_ERROR_FAILURE;
00438 
00439   NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
00440   
00441   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00442                              mTopLeftHandle, bodyContent, ps);
00443   mTopLeftHandle = nsnull;
00444 
00445   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00446                              mTopHandle, bodyContent, ps);
00447   mTopHandle = nsnull;
00448 
00449   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00450                              mTopRightHandle, bodyContent, ps);
00451   mTopRightHandle = nsnull;
00452 
00453   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00454                              mLeftHandle, bodyContent, ps);
00455   mLeftHandle = nsnull;
00456 
00457   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00458                              mRightHandle, bodyContent, ps);
00459   mRightHandle = nsnull;
00460 
00461   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00462                              mBottomLeftHandle, bodyContent, ps);
00463   mBottomLeftHandle = nsnull;
00464 
00465   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00466                              mBottomHandle, bodyContent, ps);
00467   mBottomHandle = nsnull;
00468 
00469   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00470                              mBottomRightHandle, bodyContent, ps);
00471   mBottomRightHandle = nsnull;
00472 
00473   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00474                              mResizingShadow, bodyContent, ps);
00475   mResizingShadow = nsnull;
00476 
00477   RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
00478                              mResizingInfo, bodyContent, ps);
00479   mResizingInfo = nsnull;
00480 
00481   // don't forget to remove the listeners !
00482 
00483   nsCOMPtr<nsIDOMEventReceiver> erP = GetDOMEventReceiver();
00484   nsresult res;
00485 
00486   if (erP && mMouseMotionListenerP)
00487   {
00488     res = erP->RemoveEventListener(NS_LITERAL_STRING("mousemove"), mMouseMotionListenerP, PR_TRUE);
00489     NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
00490   }
00491   mMouseMotionListenerP = nsnull;
00492 
00493   nsCOMPtr<nsIDOMDocument> domDoc;
00494   GetDocument(getter_AddRefs(domDoc));
00495   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
00496   if (!doc) { return NS_ERROR_NULL_POINTER; }
00497   nsIScriptGlobalObject *global = doc->GetScriptGlobalObject();
00498   if (!global) { return NS_ERROR_NULL_POINTER; }
00499 
00500   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(global);
00501   if (target && mResizeEventListenerP) {
00502     res = target->RemoveEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, PR_FALSE);
00503     NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove resize event listener");
00504   }
00505   mResizeEventListenerP = nsnull;
00506 
00507   mResizedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_resizing"));
00508   mResizedObject = nsnull;
00509 
00510   return NS_OK;
00511 }
00512 
00513 void
00514 nsHTMLEditor::HideShadowAndInfo()
00515 {
00516   if (mResizingShadow)
00517     mResizingShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
00518   if (mResizingInfo)
00519     mResizingInfo->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
00520 }
00521 
00522 void
00523 nsHTMLEditor::SetInfoIncrements(PRInt8 aX, PRInt8 aY)
00524 {
00525   mInfoXIncrement = aX;
00526   mInfoYIncrement = aY;
00527 }
00528 
00529 nsresult
00530 nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
00531 {
00532   // First notify the listeners if any
00533   PRInt32 listenersCount = objectResizeEventListeners.Count();
00534   if (listenersCount) {
00535     nsCOMPtr<nsIHTMLObjectResizeListener> listener;
00536     PRInt32 index;
00537     for (index = 0; index < listenersCount; index++) {
00538       listener = objectResizeEventListeners[index];
00539       listener->OnStartResizing(mResizedObject);
00540     }
00541   }
00542 
00543   mIsResizing = PR_TRUE;
00544   mActivatedHandle = aHandle;
00545   mActivatedHandle->SetAttribute(NS_LITERAL_STRING("_moz_activated"), NS_LITERAL_STRING("true"));
00546 
00547   // do we want to preserve ratio or not?
00548   PRBool preserveRatio = nsHTMLEditUtils::IsImage(mResizedObject);
00549   nsresult result;
00550   nsCOMPtr<nsIPrefBranch> prefBranch =
00551     do_GetService(NS_PREFSERVICE_CONTRACTID, &result);
00552   if (NS_SUCCEEDED(result) && prefBranch && preserveRatio) {
00553     result = prefBranch->GetBoolPref("editor.resizing.preserve_ratio", &preserveRatio);
00554     if (NS_FAILED(result)) {
00555       // just in case Anvil does not update its prefs file
00556       // and because it really does not make sense to me to allow free
00557       // resizing on corners without a modifier key
00558       preserveRatio = PR_TRUE;
00559     }
00560   }
00561 
00562   // the way we change the position/size of the shadow depends on
00563   // the handle
00564   nsAutoString locationStr;
00565   aHandle->GetAttribute(NS_LITERAL_STRING("anonlocation"), locationStr);
00566   if (locationStr.Equals(kTopLeft)) {
00567     SetResizeIncrements(1, 1, -1, -1, preserveRatio);
00568     SetInfoIncrements(20, 20);
00569   }
00570   else if (locationStr.Equals(kTop)) {
00571     SetResizeIncrements(0, 1, 0, -1, PR_FALSE);
00572     SetInfoIncrements(0, 20);
00573   }
00574   else if (locationStr.Equals(kTopRight)) {
00575     SetResizeIncrements(0, 1, 1, -1, preserveRatio);
00576     SetInfoIncrements(-20, 20);
00577   }
00578   else if (locationStr.Equals(kLeft)) {
00579     SetResizeIncrements(1, 0, -1, 0, PR_FALSE);
00580     SetInfoIncrements(20, 20);
00581   }
00582   else if (locationStr.Equals(kRight)) {
00583     SetResizeIncrements(0, 0, 1, 0, PR_FALSE);
00584     SetInfoIncrements(-20, 0);
00585   }
00586   else if (locationStr.Equals(kBottomLeft)) {
00587     SetResizeIncrements(1, 0, -1, 1, preserveRatio);
00588     SetInfoIncrements(20, -20);
00589   }
00590   else if (locationStr.Equals(kBottom)) {
00591     SetResizeIncrements(0, 0, 0, 1, PR_FALSE);
00592     SetInfoIncrements(0, -20);
00593   }
00594   else if (locationStr.Equals(kBottomRight)) {
00595     SetResizeIncrements(0, 0, 1, 1, preserveRatio);
00596     SetInfoIncrements(-20, -20);
00597   }
00598 
00599   // make the shadow appear
00600   mResizingShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
00601 
00602   // position it
00603   mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
00604                                       NS_LITERAL_STRING("width"),
00605                                       mResizedObjectWidth);
00606   mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
00607                                       NS_LITERAL_STRING("height"),
00608                                       mResizedObjectHeight);
00609 
00610   // add a mouse move listener to the editor
00611   if (!mMouseMotionListenerP) {
00612     mMouseMotionListenerP = new ResizerMouseMotionListener(this);
00613     if (!mMouseMotionListenerP) {
00614       return NS_ERROR_OUT_OF_MEMORY;
00615     }
00616 
00617     nsCOMPtr<nsIDOMEventReceiver> erP = GetDOMEventReceiver();
00618     NS_ENSURE_TRUE(erP, NS_ERROR_FAILURE);
00619 
00620     result = erP->AddEventListener(NS_LITERAL_STRING("mousemove"),
00621                                    mMouseMotionListenerP, PR_TRUE);
00622     NS_ASSERTION(NS_SUCCEEDED(result),
00623                  "failed to register mouse motion listener");
00624   }
00625   return result;
00626 }
00627 
00628 
00629 NS_IMETHODIMP 
00630 nsHTMLEditor::MouseDown(PRInt32 aClientX, PRInt32 aClientY,
00631                         nsIDOMElement *aTarget)
00632 {
00633   PRBool anonElement = PR_FALSE;
00634   if (aTarget && NS_SUCCEEDED(aTarget->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)))
00635     // we caught a click on an anonymous element
00636     if (anonElement) {
00637       nsAutoString anonclass;
00638       nsresult res = aTarget->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
00639       if (NS_FAILED(res)) return res;
00640       if (anonclass.EqualsLiteral("mozResizer")) {
00641         // and that element is a resizer, let's start resizing!
00642         mOriginalX = aClientX;
00643         mOriginalY = aClientY;
00644         return StartResizing(aTarget);
00645       }
00646       if (anonclass.EqualsLiteral("mozGrabber")) {
00647         // and that element is a grabber, let's start moving the element!
00648         mOriginalX = aClientX;
00649         mOriginalY = aClientY;
00650         return GrabberClicked();
00651       }
00652     }
00653   return NS_OK;
00654 }
00655 
00656 NS_IMETHODIMP 
00657 nsHTMLEditor::MouseUp(PRInt32 aClientX, PRInt32 aClientY,
00658                       nsIDOMElement *aTarget)
00659 {
00660   if (mIsResizing) {
00661     // we are resizing and release the mouse button, so let's
00662     // end the resizing process
00663     mIsResizing = PR_FALSE;
00664     HideShadowAndInfo();
00665     SetFinalSize(aClientX, aClientY);
00666   }
00667   else if (mIsMoving || mGrabberClicked) {
00668     if (mIsMoving) {
00669       mPositioningShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
00670       SetFinalPosition(aClientX, aClientY);
00671     }
00672     if (mGrabberClicked) {
00673       EndMoving();
00674       mGrabberClicked = PR_FALSE;
00675       mIsMoving = PR_FALSE;
00676     }
00677   }
00678   return NS_OK;
00679 }
00680 
00681 
00682 void
00683 nsHTMLEditor::SetResizeIncrements(PRInt32 aX, PRInt32 aY,
00684                                   PRInt32 aW, PRInt32 aH,
00685                                   PRBool aPreserveRatio)
00686 {
00687   mXIncrementFactor = aX;
00688   mYIncrementFactor = aY;
00689   mWidthIncrementFactor = aW;
00690   mHeightIncrementFactor = aH;
00691   mPreserveRatio = aPreserveRatio;
00692 }
00693 
00694 nsresult
00695 nsHTMLEditor::SetResizingInfoPosition(PRInt32 aX, PRInt32 aY, PRInt32 aW, PRInt32 aH)
00696 {
00697   nsCOMPtr<nsIDOMDocument> domdoc;
00698   nsEditor::GetDocument(getter_AddRefs(domdoc));
00699 
00700   nsCOMPtr<nsIDocument> doc (do_QueryInterface(domdoc));
00701   if (!doc)
00702     return NS_ERROR_UNEXPECTED;
00703 
00704   // get the root content
00705   nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(doc->GetRootContent());
00706   if (!nsElement) {return NS_ERROR_NULL_POINTER; }
00707 
00708   // let's get the size of the document
00709   PRInt32 w, h;
00710   nsElement->GetOffsetWidth(&w);
00711   nsElement->GetOffsetHeight(&h);
00712   
00713   if (mInfoXIncrement < 0)
00714     aX = w - aX ;
00715   if (mInfoYIncrement < 0)
00716     aY = h - aY;
00717 
00718   NS_NAMED_LITERAL_STRING(rightStr, "right");
00719   NS_NAMED_LITERAL_STRING(leftStr, "left");
00720   NS_NAMED_LITERAL_STRING(topStr, "top");
00721   NS_NAMED_LITERAL_STRING(bottomStr, "bottom");
00722   mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo,
00723                                       (mInfoXIncrement < 0) ? rightStr : leftStr,
00724                                       aX + PR_ABS(mInfoXIncrement));
00725   mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo,
00726                                       (mInfoYIncrement < 0) ? bottomStr : topStr,
00727                                       aY + PR_ABS(mInfoYIncrement));
00728 
00729   mHTMLCSSUtils->RemoveCSSProperty(mResizingInfo,
00730                                    (mInfoXIncrement >= 0) ? rightStr  : leftStr);
00731   mHTMLCSSUtils->RemoveCSSProperty(mResizingInfo,
00732                                    (mInfoYIncrement >= 0) ? bottomStr  : topStr);
00733 
00734   // let's make sure the info box does not go beyond the limits of the viewport
00735   nsAutoString value;
00736   float f;
00737   nsCOMPtr<nsIAtom> unit;
00738   if (mInfoXIncrement < 0) {
00739     mHTMLCSSUtils->GetComputedProperty(mResizingInfo, nsEditProperty::cssLeft, value);
00740     mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
00741     if (f <= 0) {
00742       mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, leftStr, 0);
00743       mHTMLCSSUtils->RemoveCSSProperty(mResizingInfo,
00744                                        rightStr);
00745     }
00746   }
00747   if (mInfoYIncrement < 0) {
00748     mHTMLCSSUtils->GetComputedProperty(mResizingInfo, nsEditProperty::cssTop, value);
00749     mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit));
00750     if (f <= 0) {
00751       mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, topStr, 0);
00752       mHTMLCSSUtils->RemoveCSSProperty(mResizingInfo,
00753                                        bottomStr);
00754     }
00755   }
00756 
00757   nsCOMPtr<nsIDOMNode> textInfo;
00758   nsresult res = mResizingInfo->GetFirstChild(getter_AddRefs(textInfo));
00759   if (NS_FAILED(res)) return res;
00760   nsCOMPtr<nsIDOMNode> junk;
00761   if (textInfo) {
00762     res = mResizingInfo->RemoveChild(textInfo, getter_AddRefs(junk));
00763     if (NS_FAILED(res)) return res;
00764     textInfo = nsnull;
00765     junk = nsnull;
00766   }
00767 
00768   nsAutoString widthStr, heightStr, diffWidthStr, diffHeightStr;
00769   widthStr.AppendInt(aW);
00770   heightStr.AppendInt(aH);
00771   PRInt32 diffWidth  = aW - mResizedObjectWidth;
00772   PRInt32 diffHeight = aH - mResizedObjectHeight;
00773   if (diffWidth > 0)
00774     diffWidthStr.AssignLiteral("+");
00775   if (diffHeight > 0)
00776     diffHeightStr.AssignLiteral("+");
00777   diffWidthStr.AppendInt(diffWidth);
00778   diffHeightStr.AppendInt(diffHeight);
00779 
00780   nsAutoString info(widthStr + NS_LITERAL_STRING(" x ") + heightStr +
00781                     NS_LITERAL_STRING(" (") + diffWidthStr +
00782                     NS_LITERAL_STRING(", ") + diffHeightStr +
00783                     NS_LITERAL_STRING(")"));
00784 
00785   nsCOMPtr<nsIDOMText> nodeAsText;
00786   res = domdoc->CreateTextNode(info, getter_AddRefs(nodeAsText));
00787   if (NS_FAILED(res)) return res;
00788   textInfo = do_QueryInterface(nodeAsText);
00789   res =  mResizingInfo->AppendChild(textInfo, getter_AddRefs(junk));
00790   if (NS_FAILED(res)) return res;
00791 
00792   PRBool hasClass = PR_FALSE;
00793   if (NS_SUCCEEDED(mResizingInfo->HasAttribute(NS_LITERAL_STRING("class"), &hasClass )) && hasClass)
00794     res = mResizingInfo->RemoveAttribute(NS_LITERAL_STRING("class"));
00795 
00796   return res;
00797 }
00798 
00799 nsresult
00800 nsHTMLEditor::SetShadowPosition(nsIDOMElement * aShadow,
00801                                 nsIDOMElement * aOriginalObject,
00802                                 PRInt32 aOriginalObjectX,
00803                                 PRInt32 aOriginalObjectY)
00804 {
00805   SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, aShadow);
00806 
00807   if (nsHTMLEditUtils::IsImage(aOriginalObject)) {
00808     nsAutoString imageSource;
00809     nsresult res = aOriginalObject->GetAttribute(NS_LITERAL_STRING("src"),
00810                                                 imageSource);
00811     if (NS_FAILED(res)) return res;
00812     res = aShadow->SetAttribute(NS_LITERAL_STRING("src"), imageSource);
00813     if (NS_FAILED(res)) return res;
00814   }
00815   return NS_OK;
00816 }
00817 
00818 PRInt32
00819 nsHTMLEditor::GetNewResizingIncrement(PRInt32 aX, PRInt32 aY, PRInt32 aID)
00820 {
00821   PRInt32 result = 0;
00822   if (!mPreserveRatio) {
00823     switch (aID) {
00824       case kX:
00825       case kWidth:
00826         result = aX - mOriginalX;
00827         break;
00828       case kY:
00829       case kHeight:
00830         result = aY - mOriginalY;
00831         break;
00832     }
00833     return result;
00834   }
00835 
00836   PRInt32 xi = (aX - mOriginalX) * mWidthIncrementFactor;
00837   PRInt32 yi = (aY - mOriginalY) * mHeightIncrementFactor;
00838   float objectSizeRatio = 
00839               ((float)mResizedObjectWidth) / ((float)mResizedObjectHeight);
00840   result = (xi > yi) ? xi : yi;
00841   switch (aID) {
00842     case kX:
00843     case kWidth:
00844       if (result == yi)
00845         result = (PRInt32) (((float) result) * objectSizeRatio);
00846       result = (PRInt32) (((float) result) * mWidthIncrementFactor);
00847       break;
00848     case kY:
00849     case kHeight:
00850       if (result == xi)
00851         result =  (PRInt32) (((float) result) / objectSizeRatio);
00852       result = (PRInt32) (((float) result) * mHeightIncrementFactor);
00853       break;
00854   }
00855   return result;
00856 }
00857 
00858 PRInt32
00859 nsHTMLEditor::GetNewResizingX(PRInt32 aX, PRInt32 aY)
00860 {
00861   PRInt32 resized = mResizedObjectX +
00862                     GetNewResizingIncrement(aX, aY, kX) * mXIncrementFactor;
00863   PRInt32 max =   mResizedObjectX + mResizedObjectWidth;
00864   return PR_MIN(resized, max);
00865 }
00866 
00867 PRInt32
00868 nsHTMLEditor::GetNewResizingY(PRInt32 aX, PRInt32 aY)
00869 {
00870   PRInt32 resized = mResizedObjectY +
00871                     GetNewResizingIncrement(aX, aY, kY) * mYIncrementFactor;
00872   PRInt32 max =   mResizedObjectY + mResizedObjectHeight;
00873   return PR_MIN(resized, max);
00874 }
00875 
00876 PRInt32
00877 nsHTMLEditor::GetNewResizingWidth(PRInt32 aX, PRInt32 aY)
00878 {
00879   PRInt32 resized = mResizedObjectWidth +
00880                      GetNewResizingIncrement(aX, aY, kWidth) *
00881                          mWidthIncrementFactor;
00882   return PR_MAX(resized, 1);
00883 }
00884 
00885 PRInt32
00886 nsHTMLEditor::GetNewResizingHeight(PRInt32 aX, PRInt32 aY)
00887 {
00888   PRInt32 resized = mResizedObjectHeight +
00889                      GetNewResizingIncrement(aX, aY, kHeight) *
00890                          mHeightIncrementFactor;
00891   return PR_MAX(resized, 1);
00892 }
00893 
00894 
00895 NS_IMETHODIMP
00896 nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
00897 {
00898   NS_NAMED_LITERAL_STRING(leftStr, "left");
00899   NS_NAMED_LITERAL_STRING(topStr, "top");
00900 
00901   if (mIsResizing) {
00902     // we are resizing and the mouse pointer's position has changed
00903     // we have to resdisplay the shadow
00904     nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
00905     PRInt32 clientX, clientY;
00906     mouseEvent->GetClientX(&clientX);
00907     mouseEvent->GetClientY(&clientY);
00908 
00909     PRInt32 newWidth  = GetNewResizingWidth(clientX, clientY);
00910     PRInt32 newHeight = GetNewResizingHeight(clientX, clientY);
00911 
00912     mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
00913                                         leftStr,
00914                                         GetNewResizingX(clientX, clientY));
00915     mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
00916                                         topStr,
00917                                         GetNewResizingY(clientX, clientY));
00918     mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
00919                                         NS_LITERAL_STRING("width"),
00920                                         newWidth);
00921     mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
00922                                         NS_LITERAL_STRING("height"),
00923                                         newHeight);
00924 
00925     return SetResizingInfoPosition(clientX, clientY, newWidth, newHeight);
00926   }
00927 
00928   if (mGrabberClicked) {
00929     nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
00930     PRInt32 clientX, clientY;
00931     mouseEvent->GetClientX(&clientX);
00932     mouseEvent->GetClientY(&clientY);
00933 
00934     nsCOMPtr<nsILookAndFeel> look = do_GetService(kLookAndFeelCID);
00935     NS_ASSERTION(look, "Look and feel service must be implemented for this toolkit");
00936 
00937     PRInt32 xThreshold=1, yThreshold=1;
00938     look->GetMetric(nsILookAndFeel::eMetric_DragThresholdX, xThreshold);
00939     look->GetMetric(nsILookAndFeel::eMetric_DragThresholdY, yThreshold);
00940 
00941     if (PR_ABS(clientX - mOriginalX ) * 2 >= xThreshold ||
00942         PR_ABS(clientY - mOriginalY ) * 2 >= yThreshold) {
00943       mGrabberClicked = PR_FALSE;
00944       StartMoving(nsnull);
00945     }
00946   }
00947   if (mIsMoving) {
00948     nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
00949     PRInt32 clientX, clientY;
00950     mouseEvent->GetClientX(&clientX);
00951     mouseEvent->GetClientY(&clientY);
00952 
00953     PRInt32 newX = mPositionedObjectX + clientX - mOriginalX;
00954     PRInt32 newY = mPositionedObjectY + clientY - mOriginalY;
00955 
00956     SnapToGrid(newX, newY);
00957 
00958     mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, leftStr, newX);
00959     mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, topStr, newY);
00960   }
00961   return NS_OK;
00962 }
00963 
00964 void
00965 nsHTMLEditor::SetFinalSize(PRInt32 aX, PRInt32 aY)
00966 {
00967   if (!mResizedObject) {
00968     // paranoia
00969     return;
00970   }
00971 
00972   if (mActivatedHandle) {
00973     mActivatedHandle->RemoveAttribute(NS_LITERAL_STRING("_moz_activated"));
00974     mActivatedHandle = nsnull;
00975   }
00976 
00977   // we have now to set the new width and height of the resized object
00978   // we don't set the x and y position because we don't control that in
00979   // a normal HTML layout
00980   PRInt32 left   = GetNewResizingX(aX, aY);
00981   PRInt32 top    = GetNewResizingY(aX, aY);
00982   PRInt32 width  = GetNewResizingWidth(aX, aY);
00983   PRInt32 height = GetNewResizingHeight(aX, aY);
00984   PRBool setWidth  = !mResizedObjectIsAbsolutelyPositioned || (width != mResizedObjectWidth);
00985   PRBool setHeight = !mResizedObjectIsAbsolutelyPositioned || (height != mResizedObjectHeight);
00986   
00987   PRInt32 x, y;
00988   x = left - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderLeft+mResizedObjectMarginLeft : 0);
00989   y = top - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderTop+mResizedObjectMarginTop : 0);
00990 
00991   // we need to know if we're in a CSS-enabled editor or not
00992   PRBool useCSS;
00993   GetIsCSSEnabled(&useCSS);
00994 
00995   // we want one transaction only from a user's point of view
00996   nsAutoEditBatch batchIt(this);
00997 
00998   NS_NAMED_LITERAL_STRING(widthStr,  "width");
00999   NS_NAMED_LITERAL_STRING(heightStr, "height");
01000   
01001   PRBool hasAttr = PR_FALSE;
01002   if (mResizedObjectIsAbsolutelyPositioned) {
01003     if (setHeight)
01004       mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
01005                                           nsEditProperty::cssTop,
01006                                           y,
01007                                           PR_FALSE);
01008     if (setWidth)
01009       mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
01010                                           nsEditProperty::cssLeft,
01011                                           x,
01012                                           PR_FALSE);
01013   }
01014   if (useCSS || mResizedObjectIsAbsolutelyPositioned) {
01015     if (setWidth && NS_SUCCEEDED(mResizedObject->HasAttribute(widthStr, &hasAttr)) && hasAttr)
01016       RemoveAttribute(mResizedObject, widthStr);
01017 
01018     hasAttr = PR_FALSE;
01019     if (setHeight && NS_SUCCEEDED(mResizedObject->HasAttribute(heightStr, &hasAttr)) && hasAttr)
01020       RemoveAttribute(mResizedObject, heightStr);
01021 
01022     if (setWidth)
01023       mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
01024                                           nsEditProperty::cssWidth,
01025                                           width,
01026                                           PR_FALSE);
01027     if (setHeight)
01028       mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
01029                                     nsEditProperty::cssHeight,
01030                                     height,
01031                                     PR_FALSE);
01032   }
01033   else {
01034     // we use HTML size and remove all equivalent CSS properties
01035 
01036     // we set the CSS width and height to remove it later,
01037     // triggering an immediate reflow; otherwise, we have problems
01038     // with asynchronous reflow
01039     if (setWidth)
01040       mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
01041                                           nsEditProperty::cssWidth,
01042                                           width,
01043                                           PR_FALSE);
01044     if (setHeight)
01045       mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
01046                                           nsEditProperty::cssHeight,
01047                                           height,
01048                                           PR_FALSE);
01049 
01050     if (setWidth) {
01051       nsAutoString w;
01052       w.AppendInt(width);
01053       SetAttribute(mResizedObject, widthStr, w);
01054     }
01055     if (setHeight) {
01056       nsAutoString h;
01057       h.AppendInt(height);
01058       SetAttribute(mResizedObject, heightStr, h);
01059     }
01060 
01061     if (setWidth)
01062       mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
01063                                        nsEditProperty::cssWidth,
01064                                        EmptyString(),
01065                                        PR_FALSE);
01066     if (setHeight)
01067       mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
01068                                       nsEditProperty::cssHeight,
01069                                       EmptyString(),
01070                                       PR_FALSE);
01071   }
01072   // finally notify the listeners if any
01073   PRInt32 listenersCount = objectResizeEventListeners.Count();
01074   if (listenersCount) {
01075     nsCOMPtr<nsIHTMLObjectResizeListener> listener;
01076     PRInt32 index;
01077     for (index = 0; index < listenersCount; index++) {
01078       listener = objectResizeEventListeners[index];
01079       listener->OnEndResizing(mResizedObject,
01080                               mResizedObjectWidth, mResizedObjectHeight,
01081                               width, height);
01082     }
01083   }
01084 
01085   // keep track of that size
01086   mResizedObjectWidth  = width;
01087   mResizedObjectHeight = height;
01088 
01089   RefreshResizers();
01090 }
01091 
01092 NS_IMETHODIMP
01093 nsHTMLEditor::GetResizedObject(nsIDOMElement * *aResizedObject)
01094 {
01095   *aResizedObject = mResizedObject;
01096   NS_IF_ADDREF(*aResizedObject);
01097   return NS_OK;
01098 }
01099 
01100 NS_IMETHODIMP
01101 nsHTMLEditor::GetObjectResizingEnabled(PRBool *aIsObjectResizingEnabled)
01102 {
01103   *aIsObjectResizingEnabled = mIsObjectResizingEnabled;
01104   return NS_OK;
01105 }
01106 
01107 NS_IMETHODIMP
01108 nsHTMLEditor::SetObjectResizingEnabled(PRBool aObjectResizingEnabled)
01109 {
01110   mIsObjectResizingEnabled = aObjectResizingEnabled;
01111   return NS_OK;
01112 }
01113 
01114 NS_IMETHODIMP
01115 nsHTMLEditor::AddObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
01116 {
01117   NS_ENSURE_ARG_POINTER(aListener);
01118   if (objectResizeEventListeners.Count() &&
01119       objectResizeEventListeners.IndexOf(aListener) != -1) {
01120     /* listener already registered */
01121     NS_ASSERTION(PR_FALSE,
01122                  "trying to register an already registered object resize event listener");
01123     return NS_OK;
01124   }
01125   objectResizeEventListeners.AppendObject(aListener);
01126   return NS_OK;
01127 }
01128 
01129 NS_IMETHODIMP
01130 nsHTMLEditor::RemoveObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
01131 {
01132   NS_ENSURE_ARG_POINTER(aListener);
01133   if (!objectResizeEventListeners.Count() ||
01134       objectResizeEventListeners.IndexOf(aListener) == -1) {
01135     /* listener was not registered */
01136     NS_ASSERTION(PR_FALSE,
01137                  "trying to remove an object resize event listener that was not already registered");
01138     return NS_OK;
01139   }
01140   objectResizeEventListeners.RemoveObject(aListener);
01141   return NS_OK;
01142 }
01143