mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
e39f9f88f7
- Bug 1152171 part 2 - Rename AnimationTimeline to DocumentTimeline; r=smaug (26c118319) - Bug 1152171 part 3 - Update web-platform-tests expectations; r=jgraham (b7b4032aa) - Bug 1153734 part 1 - Remove AnimationEffect; r=smaug (9cf67a02e) - Bug 1153734 part 2 - Rename Animation to KeyframeEffectReadonly; r=smaug (b69556ee6) - Bug 1153734 part 3 - Rename AnimationPlayer.source to AnimationPlayer.effect; r=smaug (50d3130ee) - Bug 1153734 part 4 - Rename other uses of 'source' and 'source content'; r=jwatt (b02c4ba36) - Bug 1153734 part 5 - Add AnimationEffectReadonly as a superinterface of KeyframeEffectReadonly; r=smaug (c3395d3f5) - Bug 1149990 - Support replaying of finished CSS transitions by supporting setting of currentTime/startTime. r=birtles (3fb2cb401) - Bug 1154615 part 1 - Rename AnimationPlayer to Animation in WebIDL; r=smaug (6c2125b49) - Bug 1154615 part 2 - Rename PendingPlayerTracker to PendingAnimationTracker; r=jwatt (8d6804def) - Bug 1154615 part 3 - Rename internal members of PendingAnimationTracker; r=jwatt (f348f6355) - Bug 1154615 part 4 - Rename references to players in dom/animation; r=jwatt (0250572e8) - Bug 1117603 part 1 - Don't assume style rules have been refreshed in GetAnimationRule; r=dbaron (a5d340d0f) - remove kungFuDeathGrip (49df758e6) - Bug 1117603 part 2 - Don't unregister from the refresh driver unless we are also queueing events; r=dbaron (715c9caa1) - Bug 1154615 part 5 - Rename AnimationPlayerCollection to AnimationCollection; r=jwatt (4c596f089) - Bug 1154615 part 6 - Rename references to players within layout/; r=jwatt (42405f3fc) - Bug 1154615 part 7 - Rename CSSAnimationPlayer and CSSTransitionPlayer; r=jwatt (49ab272ed) - Bug 1154615 part 8 - Rename references to players in animation observers; r=jwatt (c3fa26d7a) - Bug 1154615 part 9 - Rename test files; r=jwatt (9d9f03e7b) - Bug 1145439 (Part 1) - Throttle requestAnimationFrame for non-visible iframes. r=mstange,mchang (be7d183d6) - Bug 1145439 (Part 2) - Make test_scroll_event_ordering.html wait for rAF to unthrottle. r=roc (9ac8317c9) - Bug 1144324 - Try to register for, and handle, touch events when APZ is enabled. r=dvander,jimm (fb75d1665) - Bug 1144324 - Remove the codepaths that conditionally enable touch events based on touch the presence of touch listeners. r=smaug,jimm (710617e6b) - Bug 1003991 - Disable https:// only load for ServiceWorkers when Developer Tools are open. r=nsm, r=miker (9d6669814) - Bug 1153267 - part 1 - use smart-pointer .forget() instead of NS_ADDREF+assign; r=ehsan (e4555c90c) - Bug 1153267 - part 2 - use smart pointers instead of manual NS_ADDREF'ing outparams; r=ehsan (ae8b60d5a) - Bug 1153267 - fix typo that broke OS X builds on a CLOSED TREE; r=bustage (08fdb3c4f) - Bug 1146843 - Revert part of cset 33c30e283fa8 because the code is used in Fennec. r=snorp (407248257) - Bug 1151940 part 1. Make some readonly properties defined on Window by CSSOM-view replaceable. r=smaug (5cb9b91f0) - Bug 1151940 part 2. Add a convenience function in nsGlobalWindow for replacing a property on the window with a new value. r=smaug (2ba39331c) - Bug 1151940 part 3. Make some writable cssom-view attributes that we only allow setting from chrome act the way readonly replaceables would when called from content. r=smaug (b485e1b44) - Goanna -> Gecko (2c539d7be) - Goanna -> Gecko (25d34e213) - Bug 1148962 - Use TakeOwnershipOfErrorReporting in CPOW code (r=bholley) (96c997639) - pointer style (a07fbffaa) - Bug 1152577: Add 'aReason' argument to AutoEntryScript constructor, and provide plausible names for its instantiations. r=bholley (512fa27e2) - bug 1155691 - Expose WindowRoot to chrome from window in webidl. r=smaug (235281924) - Bug 404828 - No need to assert that the top window isn't reachable. r=smaug (d73154fa0) - Bug 404828 - Followup: remove assertion expectations on a CLOSED TREE. a=tomcat (a5dabe1b7) - Bug 1156102 - Mark nsGlobalWindowObserver::mWindow as MOZ_NON_OWNING_REF; r=baku (c0d4208b7) - Bug 1107801 - Improve gamepad support on MacOS. r=ted (c591bd5ac) - Goanna -> Gecko (d9b81bc9e) - Bug 852944 - Gamepad API IPC; r=ted, r=baku (521892538) - Bug 1143529 part 1. Stop manually calling WrapObject in DataStoreService::GetDataStoresResolve. r=baku (056ad6bfe) - Bug 1143529 part 2. Tighten up the assert in binding Wrap methods. r=peterv (765a13325) - Bug 1152169 - DataStoreService should check if the first revision exists, r=bent (ee371cc5d) - Bug 1152169 followup: Mark FirstRevisionIdCallback methods Run() and HandleEvent() as 'override'. rs=ehsan (8186c4168) - Bug 1143651 - don't use CallQueryInterface when the compiler can do the cast for us; r=ehsan (a50f0a54b) - Bug 1144322 - Handle tabindex in overridden IsInteractiveHTMLContent methods. r=smaug (fd4b9beed) - Bug 1086684 - Stash the full path for file inputs to avoid doing IPC at inopportune times. r=ehsan/bent/gps (b843b1efc) - Bug 1143934 - Disallow mozSetFileNameArray in content processes. r=ehsan (42e5c8c6d) - Bug 1143934 - Fix assorted forms mochitests for e10s-compatibility. r=smaug (7a3babfed) - Bug 1143934 - Work around SessionStore dependency on current brokenness. r=ttaubert (5b0fcb5ce) - Bug 956530 - Clear the delayed caret data when clicking on a selected part of a text control if the focus event handler selects the control; r=roc (2859f07b4) - Bug 956530 follow-up: Fix the test failure on Windows 8 caused by the text box having a glowing outline as a result of being clicked on (d34e8da1a) - Bug 1157898 part 1. Make code of the form "return rv.ErrorCode();" where rv is an ErrorResult use StealNSResult instead. r=peterv (800da50e2) - Bug 1157898 part 2. Make code of the form "NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());" use Failed and StealNSResult instead. r=peterv (472432a83) - Bug 1157898 part 3. Fix the remaining consumers of rv.ErrorCode() in NS_ENSURE_* expressions to not do that. r=peterv (d452807e7) - Bug 1122238 part 1. Switch to using the new stackframe APIs in JSStackFrame. r=bholley (9d87b261a) - Bug 1122238 part 2. Stop caching things in JSStackFrame when we're called over Xrays. r=bholley (83eda7275) - Bug 1122238 part 3. Drop all the DOMException-cloning and sanitization gunk we added in bug 1107592 and bug 1107953 and bug 1117242 . r=bholley (f237aa948) - add support for NetBSD/SPARC64 (065783b70) - Bug 1153484 - Fetch should ignore invalid headers, but still process later headers. r=nsm (8925ddd77) - Bug 1157754 part 2. Convert consumers of ErrorResult::ClearMessage() to the new better APIs we have for suppressing exceptions on ErrorResult. r=bkelly (6519fbd5e) - Bug 1157754 part 3. Make ClearMessage private on ErrorResult. r=peterv (3fb218692) - Bug 1157898 part 4. Add ErrorResult::ErrorCodeIs() and use it in various places to get rid of ErrorCode(). r=peterv (bed7bfb4c) - Bug 1130686 - Refactor PromiseHolder in the service worker clients code. r=nsm (b3dbdcbfe) - Bug 1130686 - Implement client.focus. r=baku (5dee6d850) - Bug 1149163 part 1 - Clean up nsHTMLEditRules::GetInnerContent; r=froydnj (cc8f65b54) - Bug 1149163 part 2 - Make nsDOMIterator infallible; r=froydnj (d975f6c62) - Bug 1149163 part 3 - Clean up nsHTMLEditRules::BustUpInlinesAtBRs; r=froydnj (58155adad) - Bug 1149163 part 4 - Allow use of temporary nsBoolDomIterFunctor; r=froydnj (dbafec00f) - Bug 1149163 part 5 - Clean up nsHTMLEditRules::GetNodesForOperation; r=froydnj (41179d810) - Bug 1149163 part 6 - Clean up nsHTMLEditRules::LookInsideDivBQandList; r=froydnj (0b757bf14) - Bug 1149163 part 7 - Clean up nsHTMLEditRules::PromoteRange; r=froydnj (c49c714b1) - Bug 1149163 part 8 - Clean up nsHTMLEditRules::GetPromotedRanges; r=froydnj (5163a0026) - Bug 1148228 - Stop checking ul twice (43a22088c) - Bug 1141017 - resurrect serif and monospace. r=ehsan (95a1b6fcf) - Bug 1147412 part 1 - Make methods take nsINode*, not just nsIContent*; r=ehsan (7f762cdbe) - Bug 1147412 part 2 - Clean up nsHTMLEditor::SetInlinePropertyOnTextNode; r=ehsan (faf805587) - Bug 1147412 part 3 - Fix completely broken nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet implementation; r=ehsan (73fea67c1) - Bug 1147412 part 4 - Clean up nsHTMLEditor::GetInlinePropertyBase; r=ehsan (3265bfbce) - Bug 1147412 part 5 - Clean up nsHTMLEditor::RemoveInlinePropertyImpl; r=ehsan (0f402bd7e) - Bug 1147412 part 6 - Remove nsHTMLCSSUtils::IsCSSEditableProperty(nsIDOMNode*,...); r=ehsan (100e4038a) - Bug 1147412 part 7 - Remove nsHTMLCSSUtils::GetComputedStyle(nsIDOMElement*); r=ehsan (6c51103bc) - Bug 1147412 part 8 - Clean up nsHTMLCSSUtils::IsCSSInvertible; r=ehsan (01e60c446) - Bug 1147412 part 9 - Convert some nsHTMLEditor members to Element; r=ehsan (e7efb1ac4) - Bug 1147412 part 10 - Clean up nsHTMLCSSUtils::Get*Property, GetCSSInlinePropertyBase; r=ehsan (54154143d) - Bug 1149163 part 9 - Clean up nsHTMLEditRules::GetNodesFromSelection; r=froydnj (5186308b9) - Bug 1154701 part 1 - Clean up nsHTMLEditor::CreateListOfNodesToPaste; r=ehsan (ea95238d5) - Bug 1153629 part 1 - Clean up nsHTMLEditRules::GetListActionNodes; r=ehsan (51f3b3e95) - Bug 1153629 part 2 - Clean up nsHTMLEditRules::GetParagraphFormatNodes; r=ehsan (a27bd7751) - Bug 1153629 part 3 - Clean up nsHTMLEditRules::GetNodesFromPoint; r=ehsan (edc7e4561) - Bug 1153629 part 4 - Clean up nsHTMLEditRules::ListIsEmptyLine; r=ehsan (ce3289bc7) - Bug 1153629 part 5 - Clean up nsHTMLEditRules::GetChildNodesForOperation; r=ehsan (b3a509dbf) - Bug 1153629 part 6 - Clean up nsHTMLEditRules::MakeBlockquote; r=ehsan (cb3808182) - Bug 1153629 part 7 - Clean up nsHTMLEditRules::RemoveBlockStyle, RemovePartOfBlock; r=ehsan (660b9f76e) - Bug 1153629 part 8 - Clean up nsHTMLEditRules::ApplyBlockStyle; r=ehsan (f54f9538c) - Bug 1153629 part 9 - Clean up nsHTMLEditRules::MakeTransitionList; r=ehsan (fb63cf6d8) - Bug 1153629 part 10 - Clean up nsHTMLEditRules::AlignInnerBlocks; r=ehsan (752d2df7a) - Bug 1153629 part 11 - Clean up nsHTMLEditRules::AdjustSpecialBreaks; r=ehsan (16ef0416b) - Bug 1153629 part 12 - Clean up nsHTMLEditRules::RemoveEmptyNodes; r=ehsan (d528e70e6) - Bug 1154701 part 2 - Use more OwningNonNull in editor; r=ehsan (85b1929e6) - Bug 1154701 part 3 - Clean up nsHTMLEditor::GetListAndTableParents, DiscoverPartialListsAndTables, ScanForListAndTableStructure, ReplaceOrphanedStructure; r=ehsan (7fe31f058) - Bug 1154701 part 4 - Switch nsHTMLEditor::mContentFilters to nsTArray; r=ehsan (64e6dd160) - Bug 1154701 part 5 - Switch nsHTMLEditor::objectResizeEventListeners to nsTArray; r=ehsan (036bc65fe) - Bug 1154701 part 6 - Clean up nsHTMLEditor::SetInlinePropertyOnNodeImpl; r=ehsan (2d619ca16) - Bug 1154701 part 7 - Clean up nsHTMLEditor::SetInlineProperty; r=ehsan (7a367d31b) - Bug 1154701 part 8 - Clean up nsHTMLEditor::SetInlinePropertyOnNode; r=ehsan (707c07d93) - Bug 1154701 part 9 - Clean up nsHTMLEditor::RelativeFontChange; r=ehsan (273ae9c64) - Bug 1154701 part 10 - Switch nsEditor::mActionListeners to nsTArray; r=ehsan (d2b5732fe) - Bug 1154701 part 11 - Switch nsEditor::mEditorObservers to nsTArray; r=ehsan (25a5af12e) - Bug 1154701 part 12 - Switch nsEditor::mDocStateListeners to nsTArray; r=ehsan (665af0792) - Bug 1154701 part 13 - Clean up nsHTMLEditor::SetCSSBackgroundColor; r=ehsan (ba424ade8) - Bug 1154701 part 14 - Remove unused nsCOMArray cruft; r=ehsan (3a8679a67) - Bug 1101651 - Part 1: xpcomrt version of dom media library need for standalone webrtcs. r=jesup (ae37b5464) - Bug 1137447 - New app update telemetry for patch type (complete or partial), extended error codes, and general cleanup. r=bbondy (c736ae502)
1041 lines
35 KiB
C++
1041 lines
35 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsHTMLObjectResizer.h"
|
|
|
|
#include "mozilla/DebugOnly.h"
|
|
#include "mozilla/LookAndFeel.h"
|
|
#include "mozilla/MathAlgorithms.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/mozalloc.h"
|
|
#include "nsAString.h"
|
|
#include "nsAlgorithm.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsDebug.h"
|
|
#include "nsEditorUtils.h"
|
|
#include "nsError.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsHTMLCSSUtils.h"
|
|
#include "nsHTMLEditUtils.h"
|
|
#include "nsHTMLEditor.h"
|
|
#include "nsIAtom.h"
|
|
#include "nsIContent.h"
|
|
#include "nsID.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIDOMElement.h"
|
|
#include "nsIDOMEvent.h"
|
|
#include "nsIDOMEventTarget.h"
|
|
#include "nsIDOMMouseEvent.h"
|
|
#include "nsIDOMNode.h"
|
|
#include "nsIDOMText.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIEditor.h"
|
|
#include "nsIHTMLEditor.h"
|
|
#include "nsIHTMLObjectResizeListener.h"
|
|
#include "nsIHTMLObjectResizer.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsISupportsUtils.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsString.h"
|
|
#include "nsStringFwd.h"
|
|
#include "nsSubstringTuple.h"
|
|
#include "nscore.h"
|
|
#include <algorithm>
|
|
|
|
class nsISelection;
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::dom;
|
|
|
|
class nsHTMLEditUtils;
|
|
|
|
// ==================================================================
|
|
// DocumentResizeEventListener
|
|
// ==================================================================
|
|
NS_IMPL_ISUPPORTS(DocumentResizeEventListener, nsIDOMEventListener)
|
|
|
|
DocumentResizeEventListener::DocumentResizeEventListener(nsIHTMLEditor * aEditor)
|
|
{
|
|
mEditor = do_GetWeakReference(aEditor);
|
|
}
|
|
|
|
DocumentResizeEventListener::~DocumentResizeEventListener()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentResizeEventListener::HandleEvent(nsIDOMEvent* aMouseEvent)
|
|
{
|
|
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
|
|
if (objectResizer)
|
|
return objectResizer->RefreshResizers();
|
|
return NS_OK;
|
|
}
|
|
|
|
// ==================================================================
|
|
// ResizerSelectionListener
|
|
// ==================================================================
|
|
|
|
NS_IMPL_ISUPPORTS(ResizerSelectionListener, nsISelectionListener)
|
|
|
|
ResizerSelectionListener::ResizerSelectionListener(nsIHTMLEditor * aEditor)
|
|
{
|
|
mEditor = do_GetWeakReference(aEditor);
|
|
}
|
|
|
|
ResizerSelectionListener::~ResizerSelectionListener()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ResizerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *aSelection, int16_t aReason)
|
|
{
|
|
if ((aReason & (nsISelectionListener::MOUSEDOWN_REASON |
|
|
nsISelectionListener::KEYPRESS_REASON |
|
|
nsISelectionListener::SELECTALL_REASON)) && aSelection)
|
|
{
|
|
// the selection changed and we need to check if we have to
|
|
// hide and/or redisplay resizing handles
|
|
nsCOMPtr<nsIHTMLEditor> editor = do_QueryReferent(mEditor);
|
|
if (editor)
|
|
editor->CheckSelectionStateForAnonymousButtons(aSelection);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// ==================================================================
|
|
// ResizerMouseMotionListener
|
|
// ==================================================================
|
|
|
|
NS_IMPL_ISUPPORTS(ResizerMouseMotionListener, nsIDOMEventListener)
|
|
|
|
ResizerMouseMotionListener::ResizerMouseMotionListener(nsIHTMLEditor * aEditor)
|
|
{
|
|
mEditor = do_GetWeakReference(aEditor);
|
|
}
|
|
|
|
ResizerMouseMotionListener::~ResizerMouseMotionListener()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ResizerMouseMotionListener::HandleEvent(nsIDOMEvent* aMouseEvent)
|
|
{
|
|
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
|
|
if (!mouseEvent) {
|
|
//non-ui event passed in. bad things.
|
|
return NS_OK;
|
|
}
|
|
|
|
// Don't do anything special if not an HTML object resizer editor
|
|
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
|
|
if (objectResizer)
|
|
{
|
|
// check if we have to redisplay a resizing shadow
|
|
objectResizer->MouseMove(aMouseEvent);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// ==================================================================
|
|
// nsHTMLEditor
|
|
// ==================================================================
|
|
|
|
already_AddRefed<Element>
|
|
nsHTMLEditor::CreateResizer(int16_t aLocation, nsIDOMNode* aParentNode)
|
|
{
|
|
nsCOMPtr<nsIDOMElement> retDOM;
|
|
nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
|
|
aParentNode,
|
|
NS_LITERAL_STRING("mozResizer"),
|
|
false,
|
|
getter_AddRefs(retDOM));
|
|
|
|
NS_ENSURE_SUCCESS(res, nullptr);
|
|
NS_ENSURE_TRUE(retDOM, nullptr);
|
|
|
|
// add the mouse listener so we can detect a click on a resizer
|
|
nsCOMPtr<nsIDOMEventTarget> evtTarget = do_QueryInterface(retDOM);
|
|
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mEventListener,
|
|
true);
|
|
|
|
nsAutoString locationStr;
|
|
switch (aLocation) {
|
|
case nsIHTMLObjectResizer::eTopLeft:
|
|
locationStr = kTopLeft;
|
|
break;
|
|
case nsIHTMLObjectResizer::eTop:
|
|
locationStr = kTop;
|
|
break;
|
|
case nsIHTMLObjectResizer::eTopRight:
|
|
locationStr = kTopRight;
|
|
break;
|
|
|
|
case nsIHTMLObjectResizer::eLeft:
|
|
locationStr = kLeft;
|
|
break;
|
|
case nsIHTMLObjectResizer::eRight:
|
|
locationStr = kRight;
|
|
break;
|
|
|
|
case nsIHTMLObjectResizer::eBottomLeft:
|
|
locationStr = kBottomLeft;
|
|
break;
|
|
case nsIHTMLObjectResizer::eBottom:
|
|
locationStr = kBottom;
|
|
break;
|
|
case nsIHTMLObjectResizer::eBottomRight:
|
|
locationStr = kBottomRight;
|
|
break;
|
|
}
|
|
|
|
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
|
|
res = ret->SetAttr(kNameSpaceID_None, nsGkAtoms::anonlocation, locationStr,
|
|
true);
|
|
NS_ENSURE_SUCCESS(res, nullptr);
|
|
return ret.forget();
|
|
}
|
|
|
|
already_AddRefed<Element>
|
|
nsHTMLEditor::CreateShadow(nsIDOMNode* aParentNode,
|
|
nsIDOMElement* aOriginalObject)
|
|
{
|
|
// let's create an image through the element factory
|
|
nsAutoString name;
|
|
if (nsHTMLEditUtils::IsImage(aOriginalObject))
|
|
name.AssignLiteral("img");
|
|
else
|
|
name.AssignLiteral("span");
|
|
nsCOMPtr<nsIDOMElement> retDOM;
|
|
CreateAnonymousElement(name, aParentNode,
|
|
NS_LITERAL_STRING("mozResizingShadow"), true,
|
|
getter_AddRefs(retDOM));
|
|
|
|
NS_ENSURE_TRUE(retDOM, nullptr);
|
|
|
|
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
|
|
return ret.forget();
|
|
}
|
|
|
|
already_AddRefed<Element>
|
|
nsHTMLEditor::CreateResizingInfo(nsIDOMNode* aParentNode)
|
|
{
|
|
// let's create an info box through the element factory
|
|
nsCOMPtr<nsIDOMElement> retDOM;
|
|
CreateAnonymousElement(NS_LITERAL_STRING("span"), aParentNode,
|
|
NS_LITERAL_STRING("mozResizingInfo"), true,
|
|
getter_AddRefs(retDOM));
|
|
|
|
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
|
|
return ret.forget();
|
|
}
|
|
|
|
nsresult
|
|
nsHTMLEditor::SetAllResizersPosition()
|
|
{
|
|
NS_ENSURE_TRUE(mTopLeftHandle, NS_ERROR_FAILURE);
|
|
|
|
int32_t x = mResizedObjectX;
|
|
int32_t y = mResizedObjectY;
|
|
int32_t w = mResizedObjectWidth;
|
|
int32_t h = mResizedObjectHeight;
|
|
|
|
// now let's place all the resizers around the image
|
|
|
|
// get the size of resizers
|
|
nsAutoString value;
|
|
float resizerWidth, resizerHeight;
|
|
nsCOMPtr<nsIAtom> dummyUnit;
|
|
mHTMLCSSUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::width,
|
|
value);
|
|
mHTMLCSSUtils->ParseLength(value, &resizerWidth, getter_AddRefs(dummyUnit));
|
|
mHTMLCSSUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::height,
|
|
value);
|
|
mHTMLCSSUtils->ParseLength(value, &resizerHeight, getter_AddRefs(dummyUnit));
|
|
|
|
int32_t rw = (int32_t)((resizerWidth + 1) / 2);
|
|
int32_t rh = (int32_t)((resizerHeight+ 1) / 2);
|
|
|
|
SetAnonymousElementPosition(x-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopLeftHandle)));
|
|
SetAnonymousElementPosition(x+w/2-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopHandle)));
|
|
SetAnonymousElementPosition(x+w-rw-1, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopRightHandle)));
|
|
|
|
SetAnonymousElementPosition(x-rw, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mLeftHandle)));
|
|
SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mRightHandle)));
|
|
|
|
SetAnonymousElementPosition(x-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomLeftHandle)));
|
|
SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomHandle)));
|
|
SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomRightHandle)));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::RefreshResizers()
|
|
{
|
|
// nothing to do if resizers are not displayed...
|
|
NS_ENSURE_TRUE(mResizedObject, NS_OK);
|
|
|
|
nsresult res = GetPositionAndDimensions(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
|
|
mResizedObjectX,
|
|
mResizedObjectY,
|
|
mResizedObjectWidth,
|
|
mResizedObjectHeight,
|
|
mResizedObjectBorderLeft,
|
|
mResizedObjectBorderTop,
|
|
mResizedObjectMarginLeft,
|
|
mResizedObjectMarginTop);
|
|
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
res = SetAllResizersPosition();
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
return SetShadowPosition(mResizingShadow, mResizedObject,
|
|
mResizedObjectX, mResizedObjectY);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
|
|
{
|
|
nsresult res = ShowResizersInner(aResizedElement);
|
|
if (NS_FAILED(res))
|
|
HideResizers();
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsHTMLEditor::ShowResizersInner(nsIDOMElement *aResizedElement)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResizedElement);
|
|
nsresult res;
|
|
|
|
nsCOMPtr<nsIDOMNode> parentNode;
|
|
res = aResizedElement->GetParentNode(getter_AddRefs(parentNode));
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
|
|
if (mResizedObject) {
|
|
NS_ERROR("call HideResizers first");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
mResizedObject = do_QueryInterface(aResizedElement);
|
|
NS_ENSURE_STATE(mResizedObject);
|
|
|
|
nsCOMPtr<nsINode> resizedNode = do_QueryInterface(aResizedElement);
|
|
if (NS_WARN_IF(!IsDescendantOfEditorRoot(resizedNode))) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
// The resizers and the shadow will be anonymous siblings of the element.
|
|
mTopLeftHandle = CreateResizer(nsIHTMLObjectResizer::eTopLeft, parentNode);
|
|
NS_ENSURE_TRUE(mTopLeftHandle, NS_ERROR_FAILURE);
|
|
mTopHandle = CreateResizer(nsIHTMLObjectResizer::eTop, parentNode);
|
|
NS_ENSURE_TRUE(mTopHandle, NS_ERROR_FAILURE);
|
|
mTopRightHandle = CreateResizer(nsIHTMLObjectResizer::eTopRight, parentNode);
|
|
NS_ENSURE_TRUE(mTopRightHandle, NS_ERROR_FAILURE);
|
|
|
|
mLeftHandle = CreateResizer(nsIHTMLObjectResizer::eLeft, parentNode);
|
|
NS_ENSURE_TRUE(mLeftHandle, NS_ERROR_FAILURE);
|
|
mRightHandle = CreateResizer(nsIHTMLObjectResizer::eRight, parentNode);
|
|
NS_ENSURE_TRUE(mRightHandle, NS_ERROR_FAILURE);
|
|
|
|
mBottomLeftHandle = CreateResizer(nsIHTMLObjectResizer::eBottomLeft, parentNode);
|
|
NS_ENSURE_TRUE(mBottomLeftHandle, NS_ERROR_FAILURE);
|
|
mBottomHandle = CreateResizer(nsIHTMLObjectResizer::eBottom, parentNode);
|
|
NS_ENSURE_TRUE(mBottomHandle, NS_ERROR_FAILURE);
|
|
mBottomRightHandle = CreateResizer(nsIHTMLObjectResizer::eBottomRight, parentNode);
|
|
NS_ENSURE_TRUE(mBottomRightHandle, NS_ERROR_FAILURE);
|
|
|
|
res = GetPositionAndDimensions(aResizedElement,
|
|
mResizedObjectX,
|
|
mResizedObjectY,
|
|
mResizedObjectWidth,
|
|
mResizedObjectHeight,
|
|
mResizedObjectBorderLeft,
|
|
mResizedObjectBorderTop,
|
|
mResizedObjectMarginLeft,
|
|
mResizedObjectMarginTop);
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
|
|
// and let's set their absolute positions in the document
|
|
res = SetAllResizersPosition();
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
|
|
// now, let's create the resizing shadow
|
|
mResizingShadow = CreateShadow(parentNode, aResizedElement);
|
|
NS_ENSURE_TRUE(mResizingShadow, NS_ERROR_FAILURE);
|
|
// and set its position
|
|
res = SetShadowPosition(mResizingShadow, mResizedObject,
|
|
mResizedObjectX, mResizedObjectY);
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
|
|
// and then the resizing info tooltip
|
|
mResizingInfo = CreateResizingInfo(parentNode);
|
|
NS_ENSURE_TRUE(mResizingInfo, NS_ERROR_FAILURE);
|
|
|
|
// and listen to the "resize" event on the window first, get the
|
|
// window from the document...
|
|
nsCOMPtr<nsIDocument> doc = GetDocument();
|
|
NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc->GetWindow());
|
|
if (!target) { return NS_ERROR_NULL_POINTER; }
|
|
|
|
mResizeEventListenerP = new DocumentResizeEventListener(this);
|
|
if (!mResizeEventListenerP) { return NS_ERROR_OUT_OF_MEMORY; }
|
|
res = target->AddEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, false);
|
|
|
|
aResizedElement->SetAttribute(NS_LITERAL_STRING("_moz_resizing"), NS_LITERAL_STRING("true"));
|
|
return res;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::HideResizers(void)
|
|
{
|
|
NS_ENSURE_TRUE(mResizedObject, NS_OK);
|
|
|
|
// get the presshell's document observer interface.
|
|
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
|
// We allow the pres shell to be null; when it is, we presume there
|
|
// are no document observers to notify, but we still want to
|
|
// UnbindFromTree.
|
|
|
|
nsCOMPtr<nsIContent> parentContent;
|
|
|
|
if (mTopLeftHandle) {
|
|
parentContent = mTopLeftHandle->GetParent();
|
|
}
|
|
|
|
NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mTopLeftHandle, parentContent, ps);
|
|
mTopLeftHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mTopHandle, parentContent, ps);
|
|
mTopHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mTopRightHandle, parentContent, ps);
|
|
mTopRightHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mLeftHandle, parentContent, ps);
|
|
mLeftHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mRightHandle, parentContent, ps);
|
|
mRightHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mBottomLeftHandle, parentContent, ps);
|
|
mBottomLeftHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mBottomHandle, parentContent, ps);
|
|
mBottomHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mBottomRightHandle, parentContent, ps);
|
|
mBottomRightHandle = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mResizingShadow, parentContent, ps);
|
|
mResizingShadow = nullptr;
|
|
|
|
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
|
|
mResizingInfo, parentContent, ps);
|
|
mResizingInfo = nullptr;
|
|
|
|
if (mActivatedHandle) {
|
|
mActivatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
|
|
true);
|
|
mActivatedHandle = nullptr;
|
|
}
|
|
|
|
// don't forget to remove the listeners !
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
|
|
|
|
DebugOnly<nsresult> res;
|
|
if (target && mMouseMotionListenerP)
|
|
{
|
|
res = target->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
|
|
mMouseMotionListenerP, true);
|
|
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
|
|
}
|
|
mMouseMotionListenerP = nullptr;
|
|
|
|
nsCOMPtr<nsIDocument> doc = GetDocument();
|
|
if (!doc) { return NS_ERROR_NULL_POINTER; }
|
|
target = do_QueryInterface(doc->GetWindow());
|
|
if (!target) { return NS_ERROR_NULL_POINTER; }
|
|
|
|
if (mResizeEventListenerP) {
|
|
res = target->RemoveEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, false);
|
|
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove resize event listener");
|
|
}
|
|
mResizeEventListenerP = nullptr;
|
|
|
|
mResizedObject->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_resizing, true);
|
|
mResizedObject = nullptr;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsHTMLEditor::HideShadowAndInfo()
|
|
{
|
|
if (mResizingShadow)
|
|
mResizingShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
|
NS_LITERAL_STRING("hidden"), true);
|
|
if (mResizingInfo)
|
|
mResizingInfo->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
|
NS_LITERAL_STRING("hidden"), true);
|
|
}
|
|
|
|
nsresult
|
|
nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
|
|
{
|
|
// First notify the listeners if any
|
|
for (auto& listener : mObjectResizeEventListeners) {
|
|
listener->OnStartResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)));
|
|
}
|
|
|
|
mIsResizing = true;
|
|
mActivatedHandle = do_QueryInterface(aHandle);
|
|
NS_ENSURE_STATE(mActivatedHandle || !aHandle);
|
|
mActivatedHandle->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
|
|
NS_LITERAL_STRING("true"), true);
|
|
|
|
// do we want to preserve ratio or not?
|
|
bool preserveRatio = nsHTMLEditUtils::IsImage(mResizedObject) &&
|
|
Preferences::GetBool("editor.resizing.preserve_ratio", true);
|
|
|
|
// the way we change the position/size of the shadow depends on
|
|
// the handle
|
|
nsAutoString locationStr;
|
|
aHandle->GetAttribute(NS_LITERAL_STRING("anonlocation"), locationStr);
|
|
if (locationStr.Equals(kTopLeft)) {
|
|
SetResizeIncrements(1, 1, -1, -1, preserveRatio);
|
|
}
|
|
else if (locationStr.Equals(kTop)) {
|
|
SetResizeIncrements(0, 1, 0, -1, false);
|
|
}
|
|
else if (locationStr.Equals(kTopRight)) {
|
|
SetResizeIncrements(0, 1, 1, -1, preserveRatio);
|
|
}
|
|
else if (locationStr.Equals(kLeft)) {
|
|
SetResizeIncrements(1, 0, -1, 0, false);
|
|
}
|
|
else if (locationStr.Equals(kRight)) {
|
|
SetResizeIncrements(0, 0, 1, 0, false);
|
|
}
|
|
else if (locationStr.Equals(kBottomLeft)) {
|
|
SetResizeIncrements(1, 0, -1, 1, preserveRatio);
|
|
}
|
|
else if (locationStr.Equals(kBottom)) {
|
|
SetResizeIncrements(0, 0, 0, 1, false);
|
|
}
|
|
else if (locationStr.Equals(kBottomRight)) {
|
|
SetResizeIncrements(0, 0, 1, 1, preserveRatio);
|
|
}
|
|
|
|
// make the shadow appear
|
|
mResizingShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
|
|
|
|
// position it
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::width,
|
|
mResizedObjectWidth);
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::height,
|
|
mResizedObjectHeight);
|
|
|
|
// add a mouse move listener to the editor
|
|
nsresult result = NS_OK;
|
|
if (!mMouseMotionListenerP) {
|
|
mMouseMotionListenerP = new ResizerMouseMotionListener(this);
|
|
if (!mMouseMotionListenerP) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
|
|
NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
|
|
|
|
result = target->AddEventListener(NS_LITERAL_STRING("mousemove"),
|
|
mMouseMotionListenerP, true);
|
|
NS_ASSERTION(NS_SUCCEEDED(result),
|
|
"failed to register mouse motion listener");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::MouseDown(int32_t aClientX, int32_t aClientY,
|
|
nsIDOMElement *aTarget, nsIDOMEvent* aEvent)
|
|
{
|
|
bool anonElement = false;
|
|
if (aTarget && NS_SUCCEEDED(aTarget->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)))
|
|
// we caught a click on an anonymous element
|
|
if (anonElement) {
|
|
nsAutoString anonclass;
|
|
nsresult res = aTarget->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
if (anonclass.EqualsLiteral("mozResizer")) {
|
|
// and that element is a resizer, let's start resizing!
|
|
aEvent->PreventDefault();
|
|
|
|
mOriginalX = aClientX;
|
|
mOriginalY = aClientY;
|
|
return StartResizing(aTarget);
|
|
}
|
|
if (anonclass.EqualsLiteral("mozGrabber")) {
|
|
// and that element is a grabber, let's start moving the element!
|
|
mOriginalX = aClientX;
|
|
mOriginalY = aClientY;
|
|
return GrabberClicked();
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::MouseUp(int32_t aClientX, int32_t aClientY,
|
|
nsIDOMElement *aTarget)
|
|
{
|
|
if (mIsResizing) {
|
|
// we are resizing and release the mouse button, so let's
|
|
// end the resizing process
|
|
mIsResizing = false;
|
|
HideShadowAndInfo();
|
|
SetFinalSize(aClientX, aClientY);
|
|
}
|
|
else if (mIsMoving || mGrabberClicked) {
|
|
if (mIsMoving) {
|
|
mPositioningShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
|
NS_LITERAL_STRING("hidden"), true);
|
|
SetFinalPosition(aClientX, aClientY);
|
|
}
|
|
if (mGrabberClicked) {
|
|
EndMoving();
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
void
|
|
nsHTMLEditor::SetResizeIncrements(int32_t aX, int32_t aY,
|
|
int32_t aW, int32_t aH,
|
|
bool aPreserveRatio)
|
|
{
|
|
mXIncrementFactor = aX;
|
|
mYIncrementFactor = aY;
|
|
mWidthIncrementFactor = aW;
|
|
mHeightIncrementFactor = aH;
|
|
mPreserveRatio = aPreserveRatio;
|
|
}
|
|
|
|
nsresult
|
|
nsHTMLEditor::SetResizingInfoPosition(int32_t aX, int32_t aY, int32_t aW, int32_t aH)
|
|
{
|
|
nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
|
|
|
|
// Determine the position of the resizing info box based upon the new
|
|
// position and size of the element (aX, aY, aW, aH), and which
|
|
// resizer is the "activated handle". For example, place the resizing
|
|
// info box at the bottom-right corner of the new element, if the element
|
|
// is being resized by the bottom-right resizer.
|
|
int32_t infoXPosition;
|
|
int32_t infoYPosition;
|
|
|
|
if (mActivatedHandle == mTopLeftHandle ||
|
|
mActivatedHandle == mLeftHandle ||
|
|
mActivatedHandle == mBottomLeftHandle)
|
|
infoXPosition = aX;
|
|
else if (mActivatedHandle == mTopHandle ||
|
|
mActivatedHandle == mBottomHandle)
|
|
infoXPosition = aX + (aW / 2);
|
|
else
|
|
// should only occur when mActivatedHandle is one of the 3 right-side
|
|
// handles, but this is a reasonable default if it isn't any of them (?)
|
|
infoXPosition = aX + aW;
|
|
|
|
if (mActivatedHandle == mTopLeftHandle ||
|
|
mActivatedHandle == mTopHandle ||
|
|
mActivatedHandle == mTopRightHandle)
|
|
infoYPosition = aY;
|
|
else if (mActivatedHandle == mLeftHandle ||
|
|
mActivatedHandle == mRightHandle)
|
|
infoYPosition = aY + (aH / 2);
|
|
else
|
|
// should only occur when mActivatedHandle is one of the 3 bottom-side
|
|
// handles, but this is a reasonable default if it isn't any of them (?)
|
|
infoYPosition = aY + aH;
|
|
|
|
// Offset info box by 20 so it's not directly under the mouse cursor.
|
|
const int mouseCursorOffset = 20;
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingInfo, *nsGkAtoms::left,
|
|
infoXPosition + mouseCursorOffset);
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingInfo, *nsGkAtoms::top,
|
|
infoYPosition + mouseCursorOffset);
|
|
|
|
nsCOMPtr<nsIContent> textInfo = mResizingInfo->GetFirstChild();
|
|
ErrorResult rv;
|
|
if (textInfo) {
|
|
mResizingInfo->RemoveChild(*textInfo, rv);
|
|
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
|
|
textInfo = nullptr;
|
|
}
|
|
|
|
nsAutoString widthStr, heightStr, diffWidthStr, diffHeightStr;
|
|
widthStr.AppendInt(aW);
|
|
heightStr.AppendInt(aH);
|
|
int32_t diffWidth = aW - mResizedObjectWidth;
|
|
int32_t diffHeight = aH - mResizedObjectHeight;
|
|
if (diffWidth > 0)
|
|
diffWidthStr.Assign('+');
|
|
if (diffHeight > 0)
|
|
diffHeightStr.Assign('+');
|
|
diffWidthStr.AppendInt(diffWidth);
|
|
diffHeightStr.AppendInt(diffHeight);
|
|
|
|
nsAutoString info(widthStr + NS_LITERAL_STRING(" x ") + heightStr +
|
|
NS_LITERAL_STRING(" (") + diffWidthStr +
|
|
NS_LITERAL_STRING(", ") + diffHeightStr +
|
|
NS_LITERAL_STRING(")"));
|
|
|
|
nsCOMPtr<nsIDOMText> nodeAsText;
|
|
nsresult res = domdoc->CreateTextNode(info, getter_AddRefs(nodeAsText));
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
textInfo = do_QueryInterface(nodeAsText);
|
|
mResizingInfo->AppendChild(*textInfo, rv);
|
|
NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode());
|
|
|
|
res = mResizingInfo->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
nsHTMLEditor::SetShadowPosition(Element* aShadow,
|
|
Element* aOriginalObject,
|
|
int32_t aOriginalObjectX,
|
|
int32_t aOriginalObjectY)
|
|
{
|
|
SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, static_cast<nsIDOMElement*>(GetAsDOMNode(aShadow)));
|
|
|
|
if (nsHTMLEditUtils::IsImage(aOriginalObject)) {
|
|
nsAutoString imageSource;
|
|
aOriginalObject->GetAttr(kNameSpaceID_None, nsGkAtoms::src, imageSource);
|
|
nsresult res = aShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::src,
|
|
imageSource, true);
|
|
NS_ENSURE_SUCCESS(res, res);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
int32_t
|
|
nsHTMLEditor::GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID)
|
|
{
|
|
int32_t result = 0;
|
|
if (!mPreserveRatio) {
|
|
switch (aID) {
|
|
case kX:
|
|
case kWidth:
|
|
result = aX - mOriginalX;
|
|
break;
|
|
case kY:
|
|
case kHeight:
|
|
result = aY - mOriginalY;
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int32_t xi = (aX - mOriginalX) * mWidthIncrementFactor;
|
|
int32_t yi = (aY - mOriginalY) * mHeightIncrementFactor;
|
|
float objectSizeRatio =
|
|
((float)mResizedObjectWidth) / ((float)mResizedObjectHeight);
|
|
result = (xi > yi) ? xi : yi;
|
|
switch (aID) {
|
|
case kX:
|
|
case kWidth:
|
|
if (result == yi)
|
|
result = (int32_t) (((float) result) * objectSizeRatio);
|
|
result = (int32_t) (((float) result) * mWidthIncrementFactor);
|
|
break;
|
|
case kY:
|
|
case kHeight:
|
|
if (result == xi)
|
|
result = (int32_t) (((float) result) / objectSizeRatio);
|
|
result = (int32_t) (((float) result) * mHeightIncrementFactor);
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int32_t
|
|
nsHTMLEditor::GetNewResizingX(int32_t aX, int32_t aY)
|
|
{
|
|
int32_t resized = mResizedObjectX +
|
|
GetNewResizingIncrement(aX, aY, kX) * mXIncrementFactor;
|
|
int32_t max = mResizedObjectX + mResizedObjectWidth;
|
|
return std::min(resized, max);
|
|
}
|
|
|
|
int32_t
|
|
nsHTMLEditor::GetNewResizingY(int32_t aX, int32_t aY)
|
|
{
|
|
int32_t resized = mResizedObjectY +
|
|
GetNewResizingIncrement(aX, aY, kY) * mYIncrementFactor;
|
|
int32_t max = mResizedObjectY + mResizedObjectHeight;
|
|
return std::min(resized, max);
|
|
}
|
|
|
|
int32_t
|
|
nsHTMLEditor::GetNewResizingWidth(int32_t aX, int32_t aY)
|
|
{
|
|
int32_t resized = mResizedObjectWidth +
|
|
GetNewResizingIncrement(aX, aY, kWidth) *
|
|
mWidthIncrementFactor;
|
|
return std::max(resized, 1);
|
|
}
|
|
|
|
int32_t
|
|
nsHTMLEditor::GetNewResizingHeight(int32_t aX, int32_t aY)
|
|
{
|
|
int32_t resized = mResizedObjectHeight +
|
|
GetNewResizingIncrement(aX, aY, kHeight) *
|
|
mHeightIncrementFactor;
|
|
return std::max(resized, 1);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
|
|
{
|
|
NS_NAMED_LITERAL_STRING(leftStr, "left");
|
|
NS_NAMED_LITERAL_STRING(topStr, "top");
|
|
|
|
if (mIsResizing) {
|
|
// we are resizing and the mouse pointer's position has changed
|
|
// we have to resdisplay the shadow
|
|
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
|
|
int32_t clientX, clientY;
|
|
mouseEvent->GetClientX(&clientX);
|
|
mouseEvent->GetClientY(&clientY);
|
|
|
|
int32_t newX = GetNewResizingX(clientX, clientY);
|
|
int32_t newY = GetNewResizingY(clientX, clientY);
|
|
int32_t newWidth = GetNewResizingWidth(clientX, clientY);
|
|
int32_t newHeight = GetNewResizingHeight(clientX, clientY);
|
|
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::left,
|
|
newX);
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::top,
|
|
newY);
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::width,
|
|
newWidth);
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::height,
|
|
newHeight);
|
|
|
|
return SetResizingInfoPosition(newX, newY, newWidth, newHeight);
|
|
}
|
|
|
|
if (mGrabberClicked) {
|
|
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
|
|
int32_t clientX, clientY;
|
|
mouseEvent->GetClientX(&clientX);
|
|
mouseEvent->GetClientY(&clientY);
|
|
|
|
int32_t xThreshold =
|
|
LookAndFeel::GetInt(LookAndFeel::eIntID_DragThresholdX, 1);
|
|
int32_t yThreshold =
|
|
LookAndFeel::GetInt(LookAndFeel::eIntID_DragThresholdY, 1);
|
|
|
|
if (DeprecatedAbs(clientX - mOriginalX) * 2 >= xThreshold ||
|
|
DeprecatedAbs(clientY - mOriginalY) * 2 >= yThreshold) {
|
|
mGrabberClicked = false;
|
|
StartMoving(nullptr);
|
|
}
|
|
}
|
|
if (mIsMoving) {
|
|
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
|
|
int32_t clientX, clientY;
|
|
mouseEvent->GetClientX(&clientX);
|
|
mouseEvent->GetClientY(&clientY);
|
|
|
|
int32_t newX = mPositionedObjectX + clientX - mOriginalX;
|
|
int32_t newY = mPositionedObjectY + clientY - mOriginalY;
|
|
|
|
SnapToGrid(newX, newY);
|
|
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::left,
|
|
newX);
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::top,
|
|
newY);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
|
|
{
|
|
if (!mResizedObject) {
|
|
// paranoia
|
|
return;
|
|
}
|
|
|
|
if (mActivatedHandle) {
|
|
mActivatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated, true);
|
|
mActivatedHandle = nullptr;
|
|
}
|
|
|
|
// we have now to set the new width and height of the resized object
|
|
// we don't set the x and y position because we don't control that in
|
|
// a normal HTML layout
|
|
int32_t left = GetNewResizingX(aX, aY);
|
|
int32_t top = GetNewResizingY(aX, aY);
|
|
int32_t width = GetNewResizingWidth(aX, aY);
|
|
int32_t height = GetNewResizingHeight(aX, aY);
|
|
bool setWidth = !mResizedObjectIsAbsolutelyPositioned || (width != mResizedObjectWidth);
|
|
bool setHeight = !mResizedObjectIsAbsolutelyPositioned || (height != mResizedObjectHeight);
|
|
|
|
int32_t x, y;
|
|
x = left - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderLeft+mResizedObjectMarginLeft : 0);
|
|
y = top - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderTop+mResizedObjectMarginTop : 0);
|
|
|
|
// we want one transaction only from a user's point of view
|
|
nsAutoEditBatch batchIt(this);
|
|
|
|
NS_NAMED_LITERAL_STRING(widthStr, "width");
|
|
NS_NAMED_LITERAL_STRING(heightStr, "height");
|
|
|
|
nsCOMPtr<Element> resizedObject = do_QueryInterface(mResizedObject);
|
|
NS_ENSURE_TRUE(resizedObject, );
|
|
if (mResizedObjectIsAbsolutelyPositioned) {
|
|
if (setHeight)
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::top, y);
|
|
if (setWidth)
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::left, x);
|
|
}
|
|
if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
|
|
if (setWidth && mResizedObject->HasAttr(kNameSpaceID_None, nsGkAtoms::width)) {
|
|
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr);
|
|
}
|
|
|
|
if (setHeight && mResizedObject->HasAttr(kNameSpaceID_None,
|
|
nsGkAtoms::height)) {
|
|
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr);
|
|
}
|
|
|
|
if (setWidth)
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
|
|
width);
|
|
if (setHeight)
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
|
|
height);
|
|
}
|
|
else {
|
|
// we use HTML size and remove all equivalent CSS properties
|
|
|
|
// we set the CSS width and height to remove it later,
|
|
// triggering an immediate reflow; otherwise, we have problems
|
|
// with asynchronous reflow
|
|
if (setWidth)
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
|
|
width);
|
|
if (setHeight)
|
|
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
|
|
height);
|
|
|
|
if (setWidth) {
|
|
nsAutoString w;
|
|
w.AppendInt(width);
|
|
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr, w);
|
|
}
|
|
if (setHeight) {
|
|
nsAutoString h;
|
|
h.AppendInt(height);
|
|
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr, h);
|
|
}
|
|
|
|
if (setWidth)
|
|
mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::width,
|
|
EmptyString());
|
|
if (setHeight)
|
|
mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::height,
|
|
EmptyString());
|
|
}
|
|
// finally notify the listeners if any
|
|
for (auto& listener : mObjectResizeEventListeners) {
|
|
listener->OnEndResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
|
|
mResizedObjectWidth, mResizedObjectHeight, width,
|
|
height);
|
|
}
|
|
|
|
// keep track of that size
|
|
mResizedObjectWidth = width;
|
|
mResizedObjectHeight = height;
|
|
|
|
RefreshResizers();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::GetResizedObject(nsIDOMElement * *aResizedObject)
|
|
{
|
|
nsCOMPtr<nsIDOMElement> ret = static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject));
|
|
ret.forget(aResizedObject);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::GetObjectResizingEnabled(bool *aIsObjectResizingEnabled)
|
|
{
|
|
*aIsObjectResizingEnabled = mIsObjectResizingEnabled;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::SetObjectResizingEnabled(bool aObjectResizingEnabled)
|
|
{
|
|
mIsObjectResizingEnabled = aObjectResizingEnabled;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::AddObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aListener);
|
|
if (mObjectResizeEventListeners.Contains(aListener)) {
|
|
/* listener already registered */
|
|
NS_ASSERTION(false,
|
|
"trying to register an already registered object resize event listener");
|
|
return NS_OK;
|
|
}
|
|
mObjectResizeEventListeners.AppendElement(*aListener);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLEditor::RemoveObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aListener);
|
|
if (!mObjectResizeEventListeners.Contains(aListener)) {
|
|
/* listener was not registered */
|
|
NS_ASSERTION(false,
|
|
"trying to remove an object resize event listener that was not already registered");
|
|
return NS_OK;
|
|
}
|
|
mObjectResizeEventListeners.RemoveElement(aListener);
|
|
return NS_OK;
|
|
}
|
|
|