editor/libeditor/html/nsHTMLObjectResizer.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/editor/libeditor/html/nsHTMLObjectResizer.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1076 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "mozilla/LookAndFeel.h"
    1.10 +#include "mozilla/MathAlgorithms.h"
    1.11 +#include "mozilla/Preferences.h"
    1.12 +#include "mozilla/mozalloc.h"
    1.13 +#include "nsAString.h"
    1.14 +#include "nsAlgorithm.h"
    1.15 +#include "nsAutoPtr.h"
    1.16 +#include "nsCOMArray.h"
    1.17 +#include "nsCOMPtr.h"
    1.18 +#include "nsDebug.h"
    1.19 +#include "nsEditProperty.h"
    1.20 +#include "nsEditorUtils.h"
    1.21 +#include "nsError.h"
    1.22 +#include "nsHTMLCSSUtils.h"
    1.23 +#include "nsHTMLEditUtils.h"
    1.24 +#include "nsHTMLEditor.h"
    1.25 +#include "nsHTMLObjectResizer.h"
    1.26 +#include "nsIAtom.h"
    1.27 +#include "nsIContent.h"
    1.28 +#include "nsID.h"
    1.29 +#include "nsIDOMDocument.h"
    1.30 +#include "nsIDOMElement.h"
    1.31 +#include "nsIDOMEvent.h"
    1.32 +#include "nsIDOMEventTarget.h"
    1.33 +#include "nsIDOMMouseEvent.h"
    1.34 +#include "nsIDOMNode.h"
    1.35 +#include "nsIDOMText.h"
    1.36 +#include "nsIDocument.h"
    1.37 +#include "nsIEditor.h"
    1.38 +#include "nsIHTMLEditor.h"
    1.39 +#include "nsIHTMLObjectResizeListener.h"
    1.40 +#include "nsIHTMLObjectResizer.h"
    1.41 +#include "nsIPresShell.h"
    1.42 +#include "nsISupportsUtils.h"
    1.43 +#include "nsPIDOMWindow.h"
    1.44 +#include "nsReadableUtils.h"
    1.45 +#include "nsString.h"
    1.46 +#include "nsStringFwd.h"
    1.47 +#include "nsSubstringTuple.h"
    1.48 +#include "nscore.h"
    1.49 +#include <algorithm>
    1.50 +
    1.51 +class nsISelection;
    1.52 +
    1.53 +using namespace mozilla;
    1.54 +
    1.55 +class nsHTMLEditUtils;
    1.56 +
    1.57 +// ==================================================================
    1.58 +// DocumentResizeEventListener
    1.59 +// ==================================================================
    1.60 +NS_IMPL_ISUPPORTS(DocumentResizeEventListener, nsIDOMEventListener)
    1.61 +
    1.62 +DocumentResizeEventListener::DocumentResizeEventListener(nsIHTMLEditor * aEditor) 
    1.63 +{
    1.64 +  mEditor = do_GetWeakReference(aEditor);
    1.65 +}
    1.66 +
    1.67 +DocumentResizeEventListener::~DocumentResizeEventListener()
    1.68 +{
    1.69 +}
    1.70 +
    1.71 +NS_IMETHODIMP
    1.72 +DocumentResizeEventListener::HandleEvent(nsIDOMEvent* aMouseEvent)
    1.73 +{
    1.74 +  nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
    1.75 +  if (objectResizer)
    1.76 +    return objectResizer->RefreshResizers();
    1.77 +  return NS_OK;
    1.78 +}
    1.79 +
    1.80 +// ==================================================================
    1.81 +// ResizerSelectionListener
    1.82 +// ==================================================================
    1.83 +
    1.84 +NS_IMPL_ISUPPORTS(ResizerSelectionListener, nsISelectionListener)
    1.85 +
    1.86 +ResizerSelectionListener::ResizerSelectionListener(nsIHTMLEditor * aEditor)
    1.87 +{
    1.88 +  mEditor = do_GetWeakReference(aEditor);
    1.89 +}
    1.90 +
    1.91 +ResizerSelectionListener::~ResizerSelectionListener()
    1.92 +{
    1.93 +}
    1.94 +
    1.95 +NS_IMETHODIMP
    1.96 +ResizerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *aSelection, int16_t aReason)
    1.97 +{
    1.98 +  if ((aReason & (nsISelectionListener::MOUSEDOWN_REASON |
    1.99 +                  nsISelectionListener::KEYPRESS_REASON |
   1.100 +                  nsISelectionListener::SELECTALL_REASON)) && aSelection) 
   1.101 +  {
   1.102 +    // the selection changed and we need to check if we have to
   1.103 +    // hide and/or redisplay resizing handles
   1.104 +    nsCOMPtr<nsIHTMLEditor> editor = do_QueryReferent(mEditor);
   1.105 +    if (editor)
   1.106 +      editor->CheckSelectionStateForAnonymousButtons(aSelection);
   1.107 +  }
   1.108 +
   1.109 +  return NS_OK;
   1.110 +}
   1.111 +
   1.112 +// ==================================================================
   1.113 +// ResizerMouseMotionListener
   1.114 +// ==================================================================
   1.115 +
   1.116 +NS_IMPL_ISUPPORTS(ResizerMouseMotionListener, nsIDOMEventListener)
   1.117 +
   1.118 +ResizerMouseMotionListener::ResizerMouseMotionListener(nsIHTMLEditor * aEditor)
   1.119 +{
   1.120 +  mEditor = do_GetWeakReference(aEditor);
   1.121 +}
   1.122 +
   1.123 +ResizerMouseMotionListener::~ResizerMouseMotionListener() 
   1.124 +{
   1.125 +}
   1.126 +
   1.127 +NS_IMETHODIMP
   1.128 +ResizerMouseMotionListener::HandleEvent(nsIDOMEvent* aMouseEvent)
   1.129 +{
   1.130 +  nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
   1.131 +  if (!mouseEvent) {
   1.132 +    //non-ui event passed in.  bad things.
   1.133 +    return NS_OK;
   1.134 +  }
   1.135 +
   1.136 +  // Don't do anything special if not an HTML object resizer editor
   1.137 +  nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
   1.138 +  if (objectResizer)
   1.139 +  {
   1.140 +    // check if we have to redisplay a resizing shadow
   1.141 +    objectResizer->MouseMove(aMouseEvent);
   1.142 +  }
   1.143 +
   1.144 +  return NS_OK;
   1.145 +}
   1.146 +
   1.147 +// ==================================================================
   1.148 +// nsHTMLEditor
   1.149 +// ==================================================================
   1.150 +
   1.151 +nsresult
   1.152 +nsHTMLEditor::CreateResizer(nsIDOMElement ** aReturn, int16_t aLocation, nsIDOMNode * aParentNode)
   1.153 +{
   1.154 +  nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
   1.155 +                                        aParentNode,
   1.156 +                                        NS_LITERAL_STRING("mozResizer"),
   1.157 +                                        false,
   1.158 +                                        aReturn);
   1.159 +
   1.160 +  NS_ENSURE_SUCCESS(res, res);
   1.161 +  NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
   1.162 +
   1.163 +  // add the mouse listener so we can detect a click on a resizer
   1.164 +  nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
   1.165 +  evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mEventListener,
   1.166 +                              true);
   1.167 +
   1.168 +  nsAutoString locationStr;
   1.169 +  switch (aLocation) {
   1.170 +    case nsIHTMLObjectResizer::eTopLeft:
   1.171 +      locationStr = kTopLeft;
   1.172 +      break;
   1.173 +    case nsIHTMLObjectResizer::eTop:
   1.174 +      locationStr = kTop;
   1.175 +      break;
   1.176 +    case nsIHTMLObjectResizer::eTopRight:
   1.177 +      locationStr = kTopRight;
   1.178 +      break;
   1.179 +
   1.180 +    case nsIHTMLObjectResizer::eLeft:
   1.181 +      locationStr = kLeft;
   1.182 +      break;
   1.183 +    case nsIHTMLObjectResizer::eRight:
   1.184 +      locationStr = kRight;
   1.185 +      break;
   1.186 +
   1.187 +    case nsIHTMLObjectResizer::eBottomLeft:
   1.188 +      locationStr = kBottomLeft;
   1.189 +      break;
   1.190 +    case nsIHTMLObjectResizer::eBottom:
   1.191 +      locationStr = kBottom;
   1.192 +      break;
   1.193 +    case nsIHTMLObjectResizer::eBottomRight:
   1.194 +      locationStr = kBottomRight;
   1.195 +      break;
   1.196 +  }
   1.197 +
   1.198 +  res = (*aReturn)->SetAttribute(NS_LITERAL_STRING("anonlocation"),
   1.199 +                                 locationStr);
   1.200 +  return res;
   1.201 +}
   1.202 +
   1.203 +nsresult
   1.204 +nsHTMLEditor::CreateShadow(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode,
   1.205 +                           nsIDOMElement * aOriginalObject)
   1.206 +{
   1.207 +  // let's create an image through the element factory
   1.208 +  nsAutoString name;
   1.209 +  if (nsHTMLEditUtils::IsImage(aOriginalObject))
   1.210 +    name.AssignLiteral("img");
   1.211 +  else
   1.212 +    name.AssignLiteral("span");
   1.213 +  nsresult res = CreateAnonymousElement(name,
   1.214 +                                        aParentNode,
   1.215 +                                        NS_LITERAL_STRING("mozResizingShadow"),
   1.216 +                                        true,
   1.217 +                                        aReturn);
   1.218 +
   1.219 +  NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
   1.220 +
   1.221 +  return res;
   1.222 +}
   1.223 +
   1.224 +nsresult
   1.225 +nsHTMLEditor::CreateResizingInfo(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode)
   1.226 +{
   1.227 +  // let's create an info box through the element factory
   1.228 +  nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
   1.229 +                                        aParentNode,
   1.230 +                                        NS_LITERAL_STRING("mozResizingInfo"),
   1.231 +                                        true,
   1.232 +                                        aReturn);
   1.233 +
   1.234 +  NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
   1.235 +
   1.236 +  return res;
   1.237 +}
   1.238 +
   1.239 +nsresult
   1.240 +nsHTMLEditor::SetAllResizersPosition()
   1.241 +{
   1.242 +  NS_ENSURE_TRUE(mTopLeftHandle, NS_ERROR_FAILURE);
   1.243 +
   1.244 +  int32_t x = mResizedObjectX;
   1.245 +  int32_t y = mResizedObjectY;
   1.246 +  int32_t w = mResizedObjectWidth;
   1.247 +  int32_t h = mResizedObjectHeight;
   1.248 +
   1.249 +  // now let's place all the resizers around the image
   1.250 +
   1.251 +  // get the size of resizers
   1.252 +  nsAutoString value;
   1.253 +  float resizerWidth, resizerHeight;
   1.254 +  nsCOMPtr<nsIAtom> dummyUnit;
   1.255 +  mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsEditProperty::cssWidth, value);
   1.256 +  mHTMLCSSUtils->ParseLength(value, &resizerWidth, getter_AddRefs(dummyUnit));
   1.257 +  mHTMLCSSUtils->GetComputedProperty(mTopLeftHandle, nsEditProperty::cssHeight, value);
   1.258 +  mHTMLCSSUtils->ParseLength(value, &resizerHeight, getter_AddRefs(dummyUnit));
   1.259 +
   1.260 +  int32_t rw  = (int32_t)((resizerWidth + 1) / 2);
   1.261 +  int32_t rh =  (int32_t)((resizerHeight+ 1) / 2);
   1.262 +
   1.263 +  SetAnonymousElementPosition(x-rw,     y-rh, mTopLeftHandle);
   1.264 +  SetAnonymousElementPosition(x+w/2-rw, y-rh, mTopHandle);
   1.265 +  SetAnonymousElementPosition(x+w-rw-1, y-rh, mTopRightHandle);
   1.266 +
   1.267 +  SetAnonymousElementPosition(x-rw,     y+h/2-rh, mLeftHandle);
   1.268 +  SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, mRightHandle);
   1.269 +
   1.270 +  SetAnonymousElementPosition(x-rw,     y+h-rh-1, mBottomLeftHandle);
   1.271 +  SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, mBottomHandle);
   1.272 +  SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, mBottomRightHandle);
   1.273 +
   1.274 +  return NS_OK;
   1.275 +}
   1.276 +
   1.277 +NS_IMETHODIMP
   1.278 +nsHTMLEditor::RefreshResizers()
   1.279 +{
   1.280 +  // nothing to do if resizers are not displayed...
   1.281 +  NS_ENSURE_TRUE(mResizedObject, NS_OK);
   1.282 +
   1.283 +  nsresult res = GetPositionAndDimensions(mResizedObject,
   1.284 +                                          mResizedObjectX,
   1.285 +                                          mResizedObjectY,
   1.286 +                                          mResizedObjectWidth,
   1.287 +                                          mResizedObjectHeight,
   1.288 +                                          mResizedObjectBorderLeft,
   1.289 +                                          mResizedObjectBorderTop,
   1.290 +                                          mResizedObjectMarginLeft,
   1.291 +                                          mResizedObjectMarginTop);
   1.292 +
   1.293 +  NS_ENSURE_SUCCESS(res, res);
   1.294 +  res = SetAllResizersPosition();
   1.295 +  NS_ENSURE_SUCCESS(res, res);
   1.296 +  return SetShadowPosition(mResizingShadow, mResizedObject,
   1.297 +                           mResizedObjectX, mResizedObjectY);
   1.298 +}
   1.299 +
   1.300 +NS_IMETHODIMP 
   1.301 +nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
   1.302 +{
   1.303 +  nsresult res = ShowResizersInner(aResizedElement);
   1.304 +  if (NS_FAILED(res))
   1.305 +    HideResizers();
   1.306 +  return res;
   1.307 +}
   1.308 +
   1.309 +nsresult 
   1.310 +nsHTMLEditor::ShowResizersInner(nsIDOMElement *aResizedElement)
   1.311 +{
   1.312 +  NS_ENSURE_ARG_POINTER(aResizedElement);
   1.313 +  nsresult res;
   1.314 +
   1.315 +  nsCOMPtr<nsIDOMNode> parentNode;
   1.316 +  res = aResizedElement->GetParentNode(getter_AddRefs(parentNode));
   1.317 +  NS_ENSURE_SUCCESS(res, res);
   1.318 +
   1.319 +  if (mResizedObject) {
   1.320 +    NS_ERROR("call HideResizers first");
   1.321 +    return NS_ERROR_UNEXPECTED;
   1.322 +  }
   1.323 +  mResizedObject = aResizedElement;
   1.324 +
   1.325 +  // The resizers and the shadow will be anonymous siblings of the element.
   1.326 +  res = CreateResizer(getter_AddRefs(mTopLeftHandle),
   1.327 +                      nsIHTMLObjectResizer::eTopLeft,     parentNode);
   1.328 +  NS_ENSURE_SUCCESS(res, res);
   1.329 +  res = CreateResizer(getter_AddRefs(mTopHandle),
   1.330 +                      nsIHTMLObjectResizer::eTop,         parentNode);
   1.331 +  NS_ENSURE_SUCCESS(res, res);
   1.332 +  res = CreateResizer(getter_AddRefs(mTopRightHandle),
   1.333 +                      nsIHTMLObjectResizer::eTopRight,    parentNode);
   1.334 +  NS_ENSURE_SUCCESS(res, res);
   1.335 +
   1.336 +  res = CreateResizer(getter_AddRefs(mLeftHandle),
   1.337 +                      nsIHTMLObjectResizer::eLeft,        parentNode);
   1.338 +  NS_ENSURE_SUCCESS(res, res);
   1.339 +  res = CreateResizer(getter_AddRefs(mRightHandle),
   1.340 +                      nsIHTMLObjectResizer::eRight,       parentNode);
   1.341 +  NS_ENSURE_SUCCESS(res, res);
   1.342 +
   1.343 +  res = CreateResizer(getter_AddRefs(mBottomLeftHandle),
   1.344 +                      nsIHTMLObjectResizer::eBottomLeft,  parentNode);
   1.345 +  NS_ENSURE_SUCCESS(res, res);
   1.346 +  res = CreateResizer(getter_AddRefs(mBottomHandle),
   1.347 +                      nsIHTMLObjectResizer::eBottom,      parentNode);
   1.348 +  NS_ENSURE_SUCCESS(res, res);
   1.349 +  res = CreateResizer(getter_AddRefs(mBottomRightHandle),
   1.350 +                      nsIHTMLObjectResizer::eBottomRight, parentNode);
   1.351 +  NS_ENSURE_SUCCESS(res, res);
   1.352 +
   1.353 +  res = GetPositionAndDimensions(aResizedElement,
   1.354 +                                 mResizedObjectX,
   1.355 +                                 mResizedObjectY,
   1.356 +                                 mResizedObjectWidth,
   1.357 +                                 mResizedObjectHeight,
   1.358 +                                 mResizedObjectBorderLeft,
   1.359 +                                 mResizedObjectBorderTop,
   1.360 +                                 mResizedObjectMarginLeft,
   1.361 +                                 mResizedObjectMarginTop);
   1.362 +  NS_ENSURE_SUCCESS(res, res);
   1.363 +
   1.364 +  // and let's set their absolute positions in the document
   1.365 +  res = SetAllResizersPosition();
   1.366 +  NS_ENSURE_SUCCESS(res, res);
   1.367 +
   1.368 +  // now, let's create the resizing shadow
   1.369 +  res = CreateShadow(getter_AddRefs(mResizingShadow), parentNode,
   1.370 +                     aResizedElement);
   1.371 +  NS_ENSURE_SUCCESS(res, res);
   1.372 +  // and set its position
   1.373 +  res = SetShadowPosition(mResizingShadow, mResizedObject,
   1.374 +                          mResizedObjectX, mResizedObjectY);
   1.375 +  NS_ENSURE_SUCCESS(res, res);
   1.376 +
   1.377 +  // and then the resizing info tooltip
   1.378 +  res = CreateResizingInfo(getter_AddRefs(mResizingInfo), parentNode);
   1.379 +  NS_ENSURE_SUCCESS(res, res);
   1.380 +
   1.381 +  // and listen to the "resize" event on the window first, get the
   1.382 +  // window from the document...
   1.383 +  nsCOMPtr<nsIDocument> doc = GetDocument();
   1.384 +  NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
   1.385 +
   1.386 +  nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc->GetWindow());
   1.387 +  if (!target) { return NS_ERROR_NULL_POINTER; }
   1.388 +
   1.389 +  mResizeEventListenerP = new DocumentResizeEventListener(this);
   1.390 +  if (!mResizeEventListenerP) { return NS_ERROR_OUT_OF_MEMORY; }
   1.391 +  res = target->AddEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, false);
   1.392 +
   1.393 +  aResizedElement->SetAttribute(NS_LITERAL_STRING("_moz_resizing"), NS_LITERAL_STRING("true"));
   1.394 +  return res;
   1.395 +}
   1.396 +
   1.397 +NS_IMETHODIMP 
   1.398 +nsHTMLEditor::HideResizers(void)
   1.399 +{
   1.400 +  NS_ENSURE_TRUE(mResizedObject, NS_OK);
   1.401 +
   1.402 +  // get the presshell's document observer interface.
   1.403 +  nsCOMPtr<nsIPresShell> ps = GetPresShell();
   1.404 +  // We allow the pres shell to be null; when it is, we presume there
   1.405 +  // are no document observers to notify, but we still want to
   1.406 +  // UnbindFromTree.
   1.407 +
   1.408 +  nsresult res;
   1.409 +  nsCOMPtr<nsIDOMNode> parentNode;
   1.410 +  nsCOMPtr<nsIContent> parentContent;
   1.411 +
   1.412 +  if (mTopLeftHandle) {
   1.413 +    res = mTopLeftHandle->GetParentNode(getter_AddRefs(parentNode));
   1.414 +    NS_ENSURE_SUCCESS(res, res);
   1.415 +    parentContent = do_QueryInterface(parentNode);
   1.416 +  }
   1.417 +
   1.418 +  NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
   1.419 +
   1.420 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.421 +                             mTopLeftHandle, parentContent, ps);
   1.422 +  mTopLeftHandle = nullptr;
   1.423 +
   1.424 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.425 +                             mTopHandle, parentContent, ps);
   1.426 +  mTopHandle = nullptr;
   1.427 +
   1.428 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.429 +                             mTopRightHandle, parentContent, ps);
   1.430 +  mTopRightHandle = nullptr;
   1.431 +
   1.432 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.433 +                             mLeftHandle, parentContent, ps);
   1.434 +  mLeftHandle = nullptr;
   1.435 +
   1.436 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.437 +                             mRightHandle, parentContent, ps);
   1.438 +  mRightHandle = nullptr;
   1.439 +
   1.440 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.441 +                             mBottomLeftHandle, parentContent, ps);
   1.442 +  mBottomLeftHandle = nullptr;
   1.443 +
   1.444 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.445 +                             mBottomHandle, parentContent, ps);
   1.446 +  mBottomHandle = nullptr;
   1.447 +
   1.448 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.449 +                             mBottomRightHandle, parentContent, ps);
   1.450 +  mBottomRightHandle = nullptr;
   1.451 +
   1.452 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.453 +                             mResizingShadow, parentContent, ps);
   1.454 +  mResizingShadow = nullptr;
   1.455 +
   1.456 +  RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
   1.457 +                             mResizingInfo, parentContent, ps);
   1.458 +  mResizingInfo = nullptr;
   1.459 +
   1.460 +  if (mActivatedHandle) {
   1.461 +    mActivatedHandle->RemoveAttribute(NS_LITERAL_STRING("_moz_activated"));
   1.462 +    mActivatedHandle = nullptr;
   1.463 +  }
   1.464 +
   1.465 +  // don't forget to remove the listeners !
   1.466 +
   1.467 +  nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
   1.468 +
   1.469 +  if (target && mMouseMotionListenerP)
   1.470 +  {
   1.471 +    res = target->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
   1.472 +                                      mMouseMotionListenerP, true);
   1.473 +    NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
   1.474 +  }
   1.475 +  mMouseMotionListenerP = nullptr;
   1.476 +
   1.477 +  nsCOMPtr<nsIDocument> doc = GetDocument();
   1.478 +  if (!doc) { return NS_ERROR_NULL_POINTER; }
   1.479 +  target = do_QueryInterface(doc->GetWindow());
   1.480 +  if (!target) { return NS_ERROR_NULL_POINTER; }
   1.481 +
   1.482 +  if (mResizeEventListenerP) {
   1.483 +    res = target->RemoveEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, false);
   1.484 +    NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove resize event listener");
   1.485 +  }
   1.486 +  mResizeEventListenerP = nullptr;
   1.487 +
   1.488 +  mResizedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_resizing"));
   1.489 +  mResizedObject = nullptr;
   1.490 +
   1.491 +  return NS_OK;
   1.492 +}
   1.493 +
   1.494 +void
   1.495 +nsHTMLEditor::HideShadowAndInfo()
   1.496 +{
   1.497 +  if (mResizingShadow)
   1.498 +    mResizingShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
   1.499 +  if (mResizingInfo)
   1.500 +    mResizingInfo->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
   1.501 +}
   1.502 +
   1.503 +nsresult
   1.504 +nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
   1.505 +{
   1.506 +  // First notify the listeners if any
   1.507 +  int32_t listenersCount = objectResizeEventListeners.Count();
   1.508 +  if (listenersCount) {
   1.509 +    nsCOMPtr<nsIHTMLObjectResizeListener> listener;
   1.510 +    int32_t index;
   1.511 +    for (index = 0; index < listenersCount; index++) {
   1.512 +      listener = objectResizeEventListeners[index];
   1.513 +      listener->OnStartResizing(mResizedObject);
   1.514 +    }
   1.515 +  }
   1.516 +
   1.517 +  mIsResizing = true;
   1.518 +  mActivatedHandle = aHandle;
   1.519 +  mActivatedHandle->SetAttribute(NS_LITERAL_STRING("_moz_activated"), NS_LITERAL_STRING("true"));
   1.520 +
   1.521 +  // do we want to preserve ratio or not?
   1.522 +  bool preserveRatio = nsHTMLEditUtils::IsImage(mResizedObject) &&
   1.523 +    Preferences::GetBool("editor.resizing.preserve_ratio", true);
   1.524 +
   1.525 +  // the way we change the position/size of the shadow depends on
   1.526 +  // the handle
   1.527 +  nsAutoString locationStr;
   1.528 +  aHandle->GetAttribute(NS_LITERAL_STRING("anonlocation"), locationStr);
   1.529 +  if (locationStr.Equals(kTopLeft)) {
   1.530 +    SetResizeIncrements(1, 1, -1, -1, preserveRatio);
   1.531 +  }
   1.532 +  else if (locationStr.Equals(kTop)) {
   1.533 +    SetResizeIncrements(0, 1, 0, -1, false);
   1.534 +  }
   1.535 +  else if (locationStr.Equals(kTopRight)) {
   1.536 +    SetResizeIncrements(0, 1, 1, -1, preserveRatio);
   1.537 +  }
   1.538 +  else if (locationStr.Equals(kLeft)) {
   1.539 +    SetResizeIncrements(1, 0, -1, 0, false);
   1.540 +  }
   1.541 +  else if (locationStr.Equals(kRight)) {
   1.542 +    SetResizeIncrements(0, 0, 1, 0, false);
   1.543 +  }
   1.544 +  else if (locationStr.Equals(kBottomLeft)) {
   1.545 +    SetResizeIncrements(1, 0, -1, 1, preserveRatio);
   1.546 +  }
   1.547 +  else if (locationStr.Equals(kBottom)) {
   1.548 +    SetResizeIncrements(0, 0, 0, 1, false);
   1.549 +  }
   1.550 +  else if (locationStr.Equals(kBottomRight)) {
   1.551 +    SetResizeIncrements(0, 0, 1, 1, preserveRatio);
   1.552 +  }
   1.553 +
   1.554 +  // make the shadow appear
   1.555 +  mResizingShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
   1.556 +
   1.557 +  // position it
   1.558 +  mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
   1.559 +                                      NS_LITERAL_STRING("width"),
   1.560 +                                      mResizedObjectWidth);
   1.561 +  mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
   1.562 +                                      NS_LITERAL_STRING("height"),
   1.563 +                                      mResizedObjectHeight);
   1.564 +
   1.565 +  // add a mouse move listener to the editor
   1.566 +  nsresult result = NS_OK;
   1.567 +  if (!mMouseMotionListenerP) {
   1.568 +    mMouseMotionListenerP = new ResizerMouseMotionListener(this);
   1.569 +    if (!mMouseMotionListenerP) {
   1.570 +      return NS_ERROR_OUT_OF_MEMORY;
   1.571 +    }
   1.572 +
   1.573 +    nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
   1.574 +    NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
   1.575 +
   1.576 +    result = target->AddEventListener(NS_LITERAL_STRING("mousemove"),
   1.577 +                                      mMouseMotionListenerP, true);
   1.578 +    NS_ASSERTION(NS_SUCCEEDED(result),
   1.579 +                 "failed to register mouse motion listener");
   1.580 +  }
   1.581 +  return result;
   1.582 +}
   1.583 +
   1.584 +
   1.585 +NS_IMETHODIMP 
   1.586 +nsHTMLEditor::MouseDown(int32_t aClientX, int32_t aClientY,
   1.587 +                        nsIDOMElement *aTarget, nsIDOMEvent* aEvent)
   1.588 +{
   1.589 +  bool anonElement = false;
   1.590 +  if (aTarget && NS_SUCCEEDED(aTarget->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)))
   1.591 +    // we caught a click on an anonymous element
   1.592 +    if (anonElement) {
   1.593 +      nsAutoString anonclass;
   1.594 +      nsresult res = aTarget->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
   1.595 +      NS_ENSURE_SUCCESS(res, res);
   1.596 +      if (anonclass.EqualsLiteral("mozResizer")) {
   1.597 +        // and that element is a resizer, let's start resizing!
   1.598 +        aEvent->PreventDefault();
   1.599 +
   1.600 +        mOriginalX = aClientX;
   1.601 +        mOriginalY = aClientY;
   1.602 +        return StartResizing(aTarget);
   1.603 +      }
   1.604 +      if (anonclass.EqualsLiteral("mozGrabber")) {
   1.605 +        // and that element is a grabber, let's start moving the element!
   1.606 +        mOriginalX = aClientX;
   1.607 +        mOriginalY = aClientY;
   1.608 +        return GrabberClicked();
   1.609 +      }
   1.610 +    }
   1.611 +  return NS_OK;
   1.612 +}
   1.613 +
   1.614 +NS_IMETHODIMP 
   1.615 +nsHTMLEditor::MouseUp(int32_t aClientX, int32_t aClientY,
   1.616 +                      nsIDOMElement *aTarget)
   1.617 +{
   1.618 +  if (mIsResizing) {
   1.619 +    // we are resizing and release the mouse button, so let's
   1.620 +    // end the resizing process
   1.621 +    mIsResizing = false;
   1.622 +    HideShadowAndInfo();
   1.623 +    SetFinalSize(aClientX, aClientY);
   1.624 +  }
   1.625 +  else if (mIsMoving || mGrabberClicked) {
   1.626 +    if (mIsMoving) {
   1.627 +      mPositioningShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
   1.628 +      SetFinalPosition(aClientX, aClientY);
   1.629 +    }
   1.630 +    if (mGrabberClicked) {
   1.631 +      EndMoving();
   1.632 +    }
   1.633 +  }
   1.634 +  return NS_OK;
   1.635 +}
   1.636 +
   1.637 +
   1.638 +void
   1.639 +nsHTMLEditor::SetResizeIncrements(int32_t aX, int32_t aY,
   1.640 +                                  int32_t aW, int32_t aH,
   1.641 +                                  bool aPreserveRatio)
   1.642 +{
   1.643 +  mXIncrementFactor = aX;
   1.644 +  mYIncrementFactor = aY;
   1.645 +  mWidthIncrementFactor = aW;
   1.646 +  mHeightIncrementFactor = aH;
   1.647 +  mPreserveRatio = aPreserveRatio;
   1.648 +}
   1.649 +
   1.650 +nsresult
   1.651 +nsHTMLEditor::SetResizingInfoPosition(int32_t aX, int32_t aY, int32_t aW, int32_t aH)
   1.652 +{
   1.653 +  nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
   1.654 +
   1.655 +  NS_NAMED_LITERAL_STRING(leftStr, "left");
   1.656 +  NS_NAMED_LITERAL_STRING(topStr, "top");
   1.657 +
   1.658 +  // Determine the position of the resizing info box based upon the new
   1.659 +  // position and size of the element (aX, aY, aW, aH), and which
   1.660 +  // resizer is the "activated handle".  For example, place the resizing
   1.661 +  // info box at the bottom-right corner of the new element, if the element
   1.662 +  // is being resized by the bottom-right resizer.
   1.663 +  int32_t infoXPosition;
   1.664 +  int32_t infoYPosition;
   1.665 +
   1.666 +  if (mActivatedHandle == mTopLeftHandle ||
   1.667 +      mActivatedHandle == mLeftHandle ||
   1.668 +      mActivatedHandle == mBottomLeftHandle)
   1.669 +    infoXPosition = aX;
   1.670 +  else if (mActivatedHandle == mTopHandle ||
   1.671 +             mActivatedHandle == mBottomHandle)
   1.672 +    infoXPosition = aX + (aW / 2);
   1.673 +  else
   1.674 +    // should only occur when mActivatedHandle is one of the 3 right-side
   1.675 +    // handles, but this is a reasonable default if it isn't any of them (?)
   1.676 +    infoXPosition = aX + aW;
   1.677 +
   1.678 +  if (mActivatedHandle == mTopLeftHandle ||
   1.679 +      mActivatedHandle == mTopHandle ||
   1.680 +      mActivatedHandle == mTopRightHandle)
   1.681 +    infoYPosition = aY;
   1.682 +  else if (mActivatedHandle == mLeftHandle ||
   1.683 +           mActivatedHandle == mRightHandle)
   1.684 +    infoYPosition = aY + (aH / 2);
   1.685 +  else
   1.686 +    // should only occur when mActivatedHandle is one of the 3 bottom-side
   1.687 +    // handles, but this is a reasonable default if it isn't any of them (?)
   1.688 +    infoYPosition = aY + aH;
   1.689 +
   1.690 +  // Offset info box by 20 so it's not directly under the mouse cursor.
   1.691 +  const int mouseCursorOffset = 20;
   1.692 +  mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, leftStr,
   1.693 +                                      infoXPosition + mouseCursorOffset);
   1.694 +  mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, topStr,
   1.695 +                                      infoYPosition + mouseCursorOffset);
   1.696 +
   1.697 +  nsCOMPtr<nsIDOMNode> textInfo;
   1.698 +  nsresult res = mResizingInfo->GetFirstChild(getter_AddRefs(textInfo));
   1.699 +  NS_ENSURE_SUCCESS(res, res);
   1.700 +  nsCOMPtr<nsIDOMNode> junk;
   1.701 +  if (textInfo) {
   1.702 +    res = mResizingInfo->RemoveChild(textInfo, getter_AddRefs(junk));
   1.703 +    NS_ENSURE_SUCCESS(res, res);
   1.704 +    textInfo = nullptr;
   1.705 +    junk = nullptr;
   1.706 +  }
   1.707 +
   1.708 +  nsAutoString widthStr, heightStr, diffWidthStr, diffHeightStr;
   1.709 +  widthStr.AppendInt(aW);
   1.710 +  heightStr.AppendInt(aH);
   1.711 +  int32_t diffWidth  = aW - mResizedObjectWidth;
   1.712 +  int32_t diffHeight = aH - mResizedObjectHeight;
   1.713 +  if (diffWidth > 0)
   1.714 +    diffWidthStr.AssignLiteral("+");
   1.715 +  if (diffHeight > 0)
   1.716 +    diffHeightStr.AssignLiteral("+");
   1.717 +  diffWidthStr.AppendInt(diffWidth);
   1.718 +  diffHeightStr.AppendInt(diffHeight);
   1.719 +
   1.720 +  nsAutoString info(widthStr + NS_LITERAL_STRING(" x ") + heightStr +
   1.721 +                    NS_LITERAL_STRING(" (") + diffWidthStr +
   1.722 +                    NS_LITERAL_STRING(", ") + diffHeightStr +
   1.723 +                    NS_LITERAL_STRING(")"));
   1.724 +
   1.725 +  nsCOMPtr<nsIDOMText> nodeAsText;
   1.726 +  res = domdoc->CreateTextNode(info, getter_AddRefs(nodeAsText));
   1.727 +  NS_ENSURE_SUCCESS(res, res);
   1.728 +  textInfo = do_QueryInterface(nodeAsText);
   1.729 +  res =  mResizingInfo->AppendChild(textInfo, getter_AddRefs(junk));
   1.730 +  NS_ENSURE_SUCCESS(res, res);
   1.731 +
   1.732 +  bool hasClass = false;
   1.733 +  if (NS_SUCCEEDED(mResizingInfo->HasAttribute(NS_LITERAL_STRING("class"), &hasClass )) && hasClass)
   1.734 +    res = mResizingInfo->RemoveAttribute(NS_LITERAL_STRING("class"));
   1.735 +
   1.736 +  return res;
   1.737 +}
   1.738 +
   1.739 +nsresult
   1.740 +nsHTMLEditor::SetShadowPosition(nsIDOMElement * aShadow,
   1.741 +                                nsIDOMElement * aOriginalObject,
   1.742 +                                int32_t aOriginalObjectX,
   1.743 +                                int32_t aOriginalObjectY)
   1.744 +{
   1.745 +  SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, aShadow);
   1.746 +
   1.747 +  if (nsHTMLEditUtils::IsImage(aOriginalObject)) {
   1.748 +    nsAutoString imageSource;
   1.749 +    nsresult res = aOriginalObject->GetAttribute(NS_LITERAL_STRING("src"),
   1.750 +                                                imageSource);
   1.751 +    NS_ENSURE_SUCCESS(res, res);
   1.752 +    res = aShadow->SetAttribute(NS_LITERAL_STRING("src"), imageSource);
   1.753 +    NS_ENSURE_SUCCESS(res, res);
   1.754 +  }
   1.755 +  return NS_OK;
   1.756 +}
   1.757 +
   1.758 +int32_t
   1.759 +nsHTMLEditor::GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID)
   1.760 +{
   1.761 +  int32_t result = 0;
   1.762 +  if (!mPreserveRatio) {
   1.763 +    switch (aID) {
   1.764 +      case kX:
   1.765 +      case kWidth:
   1.766 +        result = aX - mOriginalX;
   1.767 +        break;
   1.768 +      case kY:
   1.769 +      case kHeight:
   1.770 +        result = aY - mOriginalY;
   1.771 +        break;
   1.772 +    }
   1.773 +    return result;
   1.774 +  }
   1.775 +
   1.776 +  int32_t xi = (aX - mOriginalX) * mWidthIncrementFactor;
   1.777 +  int32_t yi = (aY - mOriginalY) * mHeightIncrementFactor;
   1.778 +  float objectSizeRatio = 
   1.779 +              ((float)mResizedObjectWidth) / ((float)mResizedObjectHeight);
   1.780 +  result = (xi > yi) ? xi : yi;
   1.781 +  switch (aID) {
   1.782 +    case kX:
   1.783 +    case kWidth:
   1.784 +      if (result == yi)
   1.785 +        result = (int32_t) (((float) result) * objectSizeRatio);
   1.786 +      result = (int32_t) (((float) result) * mWidthIncrementFactor);
   1.787 +      break;
   1.788 +    case kY:
   1.789 +    case kHeight:
   1.790 +      if (result == xi)
   1.791 +        result =  (int32_t) (((float) result) / objectSizeRatio);
   1.792 +      result = (int32_t) (((float) result) * mHeightIncrementFactor);
   1.793 +      break;
   1.794 +  }
   1.795 +  return result;
   1.796 +}
   1.797 +
   1.798 +int32_t
   1.799 +nsHTMLEditor::GetNewResizingX(int32_t aX, int32_t aY)
   1.800 +{
   1.801 +  int32_t resized = mResizedObjectX +
   1.802 +                    GetNewResizingIncrement(aX, aY, kX) * mXIncrementFactor;
   1.803 +  int32_t max =   mResizedObjectX + mResizedObjectWidth;
   1.804 +  return std::min(resized, max);
   1.805 +}
   1.806 +
   1.807 +int32_t
   1.808 +nsHTMLEditor::GetNewResizingY(int32_t aX, int32_t aY)
   1.809 +{
   1.810 +  int32_t resized = mResizedObjectY +
   1.811 +                    GetNewResizingIncrement(aX, aY, kY) * mYIncrementFactor;
   1.812 +  int32_t max =   mResizedObjectY + mResizedObjectHeight;
   1.813 +  return std::min(resized, max);
   1.814 +}
   1.815 +
   1.816 +int32_t
   1.817 +nsHTMLEditor::GetNewResizingWidth(int32_t aX, int32_t aY)
   1.818 +{
   1.819 +  int32_t resized = mResizedObjectWidth +
   1.820 +                     GetNewResizingIncrement(aX, aY, kWidth) *
   1.821 +                         mWidthIncrementFactor;
   1.822 +  return std::max(resized, 1);
   1.823 +}
   1.824 +
   1.825 +int32_t
   1.826 +nsHTMLEditor::GetNewResizingHeight(int32_t aX, int32_t aY)
   1.827 +{
   1.828 +  int32_t resized = mResizedObjectHeight +
   1.829 +                     GetNewResizingIncrement(aX, aY, kHeight) *
   1.830 +                         mHeightIncrementFactor;
   1.831 +  return std::max(resized, 1);
   1.832 +}
   1.833 +
   1.834 +
   1.835 +NS_IMETHODIMP
   1.836 +nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
   1.837 +{
   1.838 +  NS_NAMED_LITERAL_STRING(leftStr, "left");
   1.839 +  NS_NAMED_LITERAL_STRING(topStr, "top");
   1.840 +
   1.841 +  if (mIsResizing) {
   1.842 +    // we are resizing and the mouse pointer's position has changed
   1.843 +    // we have to resdisplay the shadow
   1.844 +    nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
   1.845 +    int32_t clientX, clientY;
   1.846 +    mouseEvent->GetClientX(&clientX);
   1.847 +    mouseEvent->GetClientY(&clientY);
   1.848 +
   1.849 +    int32_t newX = GetNewResizingX(clientX, clientY);
   1.850 +    int32_t newY = GetNewResizingY(clientX, clientY);
   1.851 +    int32_t newWidth  = GetNewResizingWidth(clientX, clientY);
   1.852 +    int32_t newHeight = GetNewResizingHeight(clientX, clientY);
   1.853 +
   1.854 +    mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
   1.855 +                                        leftStr,
   1.856 +                                        newX);
   1.857 +    mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
   1.858 +                                        topStr,
   1.859 +                                        newY);
   1.860 +    mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
   1.861 +                                        NS_LITERAL_STRING("width"),
   1.862 +                                        newWidth);
   1.863 +    mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
   1.864 +                                        NS_LITERAL_STRING("height"),
   1.865 +                                        newHeight);
   1.866 +
   1.867 +    return SetResizingInfoPosition(newX, newY, newWidth, newHeight);
   1.868 +  }
   1.869 +
   1.870 +  if (mGrabberClicked) {
   1.871 +    nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
   1.872 +    int32_t clientX, clientY;
   1.873 +    mouseEvent->GetClientX(&clientX);
   1.874 +    mouseEvent->GetClientY(&clientY);
   1.875 +
   1.876 +    int32_t xThreshold =
   1.877 +      LookAndFeel::GetInt(LookAndFeel::eIntID_DragThresholdX, 1);
   1.878 +    int32_t yThreshold =
   1.879 +      LookAndFeel::GetInt(LookAndFeel::eIntID_DragThresholdY, 1);
   1.880 +
   1.881 +    if (DeprecatedAbs(clientX - mOriginalX) * 2 >= xThreshold ||
   1.882 +        DeprecatedAbs(clientY - mOriginalY) * 2 >= yThreshold) {
   1.883 +      mGrabberClicked = false;
   1.884 +      StartMoving(nullptr);
   1.885 +    }
   1.886 +  }
   1.887 +  if (mIsMoving) {
   1.888 +    nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
   1.889 +    int32_t clientX, clientY;
   1.890 +    mouseEvent->GetClientX(&clientX);
   1.891 +    mouseEvent->GetClientY(&clientY);
   1.892 +
   1.893 +    int32_t newX = mPositionedObjectX + clientX - mOriginalX;
   1.894 +    int32_t newY = mPositionedObjectY + clientY - mOriginalY;
   1.895 +
   1.896 +    SnapToGrid(newX, newY);
   1.897 +
   1.898 +    mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, leftStr, newX);
   1.899 +    mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, topStr, newY);
   1.900 +  }
   1.901 +  return NS_OK;
   1.902 +}
   1.903 +
   1.904 +void
   1.905 +nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
   1.906 +{
   1.907 +  if (!mResizedObject) {
   1.908 +    // paranoia
   1.909 +    return;
   1.910 +  }
   1.911 +
   1.912 +  if (mActivatedHandle) {
   1.913 +    mActivatedHandle->RemoveAttribute(NS_LITERAL_STRING("_moz_activated"));
   1.914 +    mActivatedHandle = nullptr;
   1.915 +  }
   1.916 +
   1.917 +  // we have now to set the new width and height of the resized object
   1.918 +  // we don't set the x and y position because we don't control that in
   1.919 +  // a normal HTML layout
   1.920 +  int32_t left   = GetNewResizingX(aX, aY);
   1.921 +  int32_t top    = GetNewResizingY(aX, aY);
   1.922 +  int32_t width  = GetNewResizingWidth(aX, aY);
   1.923 +  int32_t height = GetNewResizingHeight(aX, aY);
   1.924 +  bool setWidth  = !mResizedObjectIsAbsolutelyPositioned || (width != mResizedObjectWidth);
   1.925 +  bool setHeight = !mResizedObjectIsAbsolutelyPositioned || (height != mResizedObjectHeight);
   1.926 +  
   1.927 +  int32_t x, y;
   1.928 +  x = left - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderLeft+mResizedObjectMarginLeft : 0);
   1.929 +  y = top - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderTop+mResizedObjectMarginTop : 0);
   1.930 +
   1.931 +  // we want one transaction only from a user's point of view
   1.932 +  nsAutoEditBatch batchIt(this);
   1.933 +
   1.934 +  NS_NAMED_LITERAL_STRING(widthStr,  "width");
   1.935 +  NS_NAMED_LITERAL_STRING(heightStr, "height");
   1.936 +  
   1.937 +  bool hasAttr = false;
   1.938 +  if (mResizedObjectIsAbsolutelyPositioned) {
   1.939 +    if (setHeight)
   1.940 +      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
   1.941 +                                          nsEditProperty::cssTop,
   1.942 +                                          y,
   1.943 +                                          false);
   1.944 +    if (setWidth)
   1.945 +      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
   1.946 +                                          nsEditProperty::cssLeft,
   1.947 +                                          x,
   1.948 +                                          false);
   1.949 +  }
   1.950 +  if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
   1.951 +    if (setWidth && NS_SUCCEEDED(mResizedObject->HasAttribute(widthStr, &hasAttr)) && hasAttr)
   1.952 +      RemoveAttribute(mResizedObject, widthStr);
   1.953 +
   1.954 +    hasAttr = false;
   1.955 +    if (setHeight && NS_SUCCEEDED(mResizedObject->HasAttribute(heightStr, &hasAttr)) && hasAttr)
   1.956 +      RemoveAttribute(mResizedObject, heightStr);
   1.957 +
   1.958 +    if (setWidth)
   1.959 +      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
   1.960 +                                          nsEditProperty::cssWidth,
   1.961 +                                          width,
   1.962 +                                          false);
   1.963 +    if (setHeight)
   1.964 +      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
   1.965 +                                    nsEditProperty::cssHeight,
   1.966 +                                    height,
   1.967 +                                    false);
   1.968 +  }
   1.969 +  else {
   1.970 +    // we use HTML size and remove all equivalent CSS properties
   1.971 +
   1.972 +    // we set the CSS width and height to remove it later,
   1.973 +    // triggering an immediate reflow; otherwise, we have problems
   1.974 +    // with asynchronous reflow
   1.975 +    if (setWidth)
   1.976 +      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
   1.977 +                                          nsEditProperty::cssWidth,
   1.978 +                                          width,
   1.979 +                                          false);
   1.980 +    if (setHeight)
   1.981 +      mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
   1.982 +                                          nsEditProperty::cssHeight,
   1.983 +                                          height,
   1.984 +                                          false);
   1.985 +
   1.986 +    if (setWidth) {
   1.987 +      nsAutoString w;
   1.988 +      w.AppendInt(width);
   1.989 +      SetAttribute(mResizedObject, widthStr, w);
   1.990 +    }
   1.991 +    if (setHeight) {
   1.992 +      nsAutoString h;
   1.993 +      h.AppendInt(height);
   1.994 +      SetAttribute(mResizedObject, heightStr, h);
   1.995 +    }
   1.996 +
   1.997 +    if (setWidth)
   1.998 +      mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
   1.999 +                                       nsEditProperty::cssWidth,
  1.1000 +                                       EmptyString(),
  1.1001 +                                       false);
  1.1002 +    if (setHeight)
  1.1003 +      mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
  1.1004 +                                      nsEditProperty::cssHeight,
  1.1005 +                                      EmptyString(),
  1.1006 +                                      false);
  1.1007 +  }
  1.1008 +  // finally notify the listeners if any
  1.1009 +  int32_t listenersCount = objectResizeEventListeners.Count();
  1.1010 +  if (listenersCount) {
  1.1011 +    nsCOMPtr<nsIHTMLObjectResizeListener> listener;
  1.1012 +    int32_t index;
  1.1013 +    for (index = 0; index < listenersCount; index++) {
  1.1014 +      listener = objectResizeEventListeners[index];
  1.1015 +      listener->OnEndResizing(mResizedObject,
  1.1016 +                              mResizedObjectWidth, mResizedObjectHeight,
  1.1017 +                              width, height);
  1.1018 +    }
  1.1019 +  }
  1.1020 +
  1.1021 +  // keep track of that size
  1.1022 +  mResizedObjectWidth  = width;
  1.1023 +  mResizedObjectHeight = height;
  1.1024 +
  1.1025 +  RefreshResizers();
  1.1026 +}
  1.1027 +
  1.1028 +NS_IMETHODIMP
  1.1029 +nsHTMLEditor::GetResizedObject(nsIDOMElement * *aResizedObject)
  1.1030 +{
  1.1031 +  *aResizedObject = mResizedObject;
  1.1032 +  NS_IF_ADDREF(*aResizedObject);
  1.1033 +  return NS_OK;
  1.1034 +}
  1.1035 +
  1.1036 +NS_IMETHODIMP
  1.1037 +nsHTMLEditor::GetObjectResizingEnabled(bool *aIsObjectResizingEnabled)
  1.1038 +{
  1.1039 +  *aIsObjectResizingEnabled = mIsObjectResizingEnabled;
  1.1040 +  return NS_OK;
  1.1041 +}
  1.1042 +
  1.1043 +NS_IMETHODIMP
  1.1044 +nsHTMLEditor::SetObjectResizingEnabled(bool aObjectResizingEnabled)
  1.1045 +{
  1.1046 +  mIsObjectResizingEnabled = aObjectResizingEnabled;
  1.1047 +  return NS_OK;
  1.1048 +}
  1.1049 +
  1.1050 +NS_IMETHODIMP
  1.1051 +nsHTMLEditor::AddObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
  1.1052 +{
  1.1053 +  NS_ENSURE_ARG_POINTER(aListener);
  1.1054 +  if (objectResizeEventListeners.Count() &&
  1.1055 +      objectResizeEventListeners.IndexOf(aListener) != -1) {
  1.1056 +    /* listener already registered */
  1.1057 +    NS_ASSERTION(false,
  1.1058 +                 "trying to register an already registered object resize event listener");
  1.1059 +    return NS_OK;
  1.1060 +  }
  1.1061 +  objectResizeEventListeners.AppendObject(aListener);
  1.1062 +  return NS_OK;
  1.1063 +}
  1.1064 +
  1.1065 +NS_IMETHODIMP
  1.1066 +nsHTMLEditor::RemoveObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
  1.1067 +{
  1.1068 +  NS_ENSURE_ARG_POINTER(aListener);
  1.1069 +  if (!objectResizeEventListeners.Count() ||
  1.1070 +      objectResizeEventListeners.IndexOf(aListener) == -1) {
  1.1071 +    /* listener was not registered */
  1.1072 +    NS_ASSERTION(false,
  1.1073 +                 "trying to remove an object resize event listener that was not already registered");
  1.1074 +    return NS_OK;
  1.1075 +  }
  1.1076 +  objectResizeEventListeners.RemoveObject(aListener);
  1.1077 +  return NS_OK;
  1.1078 +}
  1.1079 +

mercurial