2003-02-24 13:18:18 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla.org.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corp.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2003
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Daniel Glazman (glazman@netscape.com) (Original author)
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "nsHTMLObjectResizer.h"
|
|
|
|
|
|
|
|
#include "nsIDOMEventTarget.h"
|
|
|
|
#include "nsIDOMNSHTMLElement.h"
|
|
|
|
#include "nsIDOMEventReceiver.h"
|
|
|
|
#include "nsIDOMText.h"
|
|
|
|
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIDocument.h"
|
2003-03-25 18:24:08 +03:00
|
|
|
#include "nsIDocumentObserver.h"
|
2003-02-24 13:18:18 +03:00
|
|
|
#include "nsIEditor.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
|
|
|
|
#include "nsHTMLEditor.h"
|
|
|
|
#include "nsEditor.h"
|
|
|
|
#include "nsEditorUtils.h"
|
|
|
|
#include "nsHTMLEditUtils.h"
|
|
|
|
|
|
|
|
#include "nsPoint.h"
|
|
|
|
|
|
|
|
class nsHTMLEditUtils;
|
|
|
|
|
|
|
|
// ==================================================================
|
|
|
|
// ResizeEventListener
|
|
|
|
// ==================================================================
|
|
|
|
NS_IMPL_ADDREF(ResizeEventListener)
|
|
|
|
NS_IMPL_RELEASE(ResizeEventListener)
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(ResizeEventListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
ResizeEventListener::ResizeEventListener(nsIHTMLEditor * aEditor) :
|
|
|
|
mEditor(aEditor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ResizeEventListener::~ResizeEventListener()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
ResizeEventListener::HandleEvent(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(mEditor);
|
|
|
|
objectResizer->RefreshResizers();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ==================================================================
|
|
|
|
// ResizerSelectionListener
|
|
|
|
// ==================================================================
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(ResizerSelectionListener)
|
|
|
|
NS_IMPL_RELEASE(ResizerSelectionListener)
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(ResizerSelectionListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
ResizerSelectionListener::ResizerSelectionListener(nsIHTMLEditor * aEditor) :
|
|
|
|
mEditor(aEditor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ResizerSelectionListener::~ResizerSelectionListener()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
ResizerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *aSelection,short 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<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(mEditor);
|
|
|
|
objectResizer->CheckResizingState(aSelection);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ==================================================================
|
|
|
|
// ResizerMouseMotionListener
|
|
|
|
// ==================================================================
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(ResizerMouseMotionListener)
|
|
|
|
|
|
|
|
NS_IMPL_RELEASE(ResizerMouseMotionListener)
|
|
|
|
|
|
|
|
ResizerMouseMotionListener::ResizerMouseMotionListener(nsIHTMLEditor * aEditor):
|
|
|
|
mEditor(aEditor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ResizerMouseMotionListener::~ResizerMouseMotionListener()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
ResizerMouseMotionListener::MouseMove(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(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 editor
|
|
|
|
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
|
|
|
|
if (htmlEditor)
|
|
|
|
{
|
|
|
|
// check if we have to redisplay a resizing shadow
|
|
|
|
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(htmlEditor);
|
|
|
|
objectResizer->MouseMove(aMouseEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
ResizerMouseMotionListener::HandleEvent(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
ResizerMouseMotionListener::DragMove(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(ResizerMouseMotionListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
// ==================================================================
|
|
|
|
// nsHTMLEditor
|
|
|
|
// ==================================================================
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHTMLEditor::CreateResizer(nsIDOMElement ** aReturn, PRInt16 aLocation, nsISupportsArray * aArray)
|
|
|
|
{
|
|
|
|
// let's create a span through the element factory
|
|
|
|
nsCOMPtr<nsIContent> newContent;
|
|
|
|
nsresult res = CreateHTMLContent(NS_LITERAL_STRING("span"), getter_AddRefs(newContent));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
|
|
|
|
if (!newElement)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
*aReturn = newElement;
|
|
|
|
NS_ADDREF(*aReturn);
|
|
|
|
|
|
|
|
// add the mouse listener so we can detect a click on a resizer
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
|
|
|
|
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mMouseListenerP, PR_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
res = newElement->SetAttribute(NS_LITERAL_STRING("_moz_anonclass"),
|
|
|
|
NS_LITERAL_STRING("mozResizer"));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = newElement->SetAttribute(NS_LITERAL_STRING("anonlocation"),
|
|
|
|
locationStr);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
return aArray->AppendElement(newContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHTMLEditor::CreateShadow(nsIDOMElement ** aReturn, nsISupportsArray * aArray)
|
|
|
|
{
|
|
|
|
// let's create an image through the element factory
|
|
|
|
nsCOMPtr<nsIContent> newContent;
|
|
|
|
nsAutoString name;
|
|
|
|
if (NodeIsType(mResizedObject, NS_LITERAL_STRING("img")))
|
|
|
|
name = NS_LITERAL_STRING("img");
|
|
|
|
else
|
|
|
|
name = NS_LITERAL_STRING("span");
|
|
|
|
nsresult res = CreateHTMLContent(name, getter_AddRefs(newContent));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
|
|
|
|
if (!newElement)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
*aReturn = newElement;
|
|
|
|
NS_ADDREF(*aReturn);
|
|
|
|
|
|
|
|
return aArray->AppendElement(newContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHTMLEditor::CreateResizingInfo(nsIDOMElement ** aReturn, nsISupportsArray * aArray)
|
|
|
|
{
|
|
|
|
// let's create an image through the element factory
|
|
|
|
nsCOMPtr<nsIContent> newContent;
|
|
|
|
nsresult res = CreateHTMLContent(NS_LITERAL_STRING("span"), getter_AddRefs(newContent));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
|
|
|
|
if (NS_FAILED(res) || !newElement)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
*aReturn = newElement;
|
|
|
|
NS_ADDREF(*aReturn);
|
|
|
|
|
|
|
|
res = newElement->SetAttribute(NS_LITERAL_STRING("_moz_anonclass"),
|
|
|
|
NS_LITERAL_STRING("mozResizingInfo"));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = newElement->SetAttribute(NS_LITERAL_STRING("class"),
|
|
|
|
NS_LITERAL_STRING("hidden"));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
return aArray->AppendElement(newContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsHTMLEditor::SetResizerPosition(PRInt32 aX, PRInt32 aY, nsIDOMElement *aResizer)
|
|
|
|
{
|
|
|
|
nsAutoString x, y;
|
|
|
|
x.AppendInt(aX);
|
|
|
|
y.AppendInt(aY);
|
|
|
|
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(aResizer,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssLeft,
|
2003-02-24 13:18:18 +03:00
|
|
|
x + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(aResizer,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssTop,
|
2003-02-24 13:18:18 +03:00
|
|
|
y + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHTMLEditor::SetAllResizersPosition(nsIDOMElement * aResizedElement, PRInt32 & aX, PRInt32 & aY)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(aResizedElement);
|
|
|
|
if (!nsElement) {return NS_ERROR_NULL_POINTER; }
|
|
|
|
|
|
|
|
GetElementOrigin(aResizedElement, aX, aY);
|
|
|
|
|
|
|
|
mResizedObjectX = aX;
|
|
|
|
mResizedObjectY = aY;
|
|
|
|
|
|
|
|
nsresult res = nsElement->GetOffsetWidth(&mResizedObjectWidth );
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = nsElement->GetOffsetHeight(&mResizedObjectHeight);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
PRInt32 w = mResizedObjectWidth;
|
|
|
|
PRInt32 h = mResizedObjectHeight;
|
|
|
|
|
|
|
|
// now let's place all the resizers around the image
|
|
|
|
SetResizerPosition(aX-4, aY-4, mTopLeftHandle);
|
|
|
|
SetResizerPosition(aX+w/2-3, aY-4, mTopHandle);
|
|
|
|
SetResizerPosition(aX+w-2, aY-4, mTopRightHandle);
|
|
|
|
|
|
|
|
SetResizerPosition(aX-4, aY+h/2-3, mLeftHandle);
|
|
|
|
SetResizerPosition(aX+w-2, aY+h/2-3, mRightHandle);
|
|
|
|
|
|
|
|
SetResizerPosition(aX-4, aY+h-2, mBottomLeftHandle);
|
|
|
|
SetResizerPosition(aX+w/2-3, aY+h-2, mBottomHandle);
|
|
|
|
SetResizerPosition(aX+w-2, aY+h-2, mBottomRightHandle);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RefreshResizers()
|
|
|
|
{
|
|
|
|
PRInt32 x, y;
|
|
|
|
nsresult res = SetAllResizersPosition(mResizedObject, x, y);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
return SetShadowPosition(mResizedObject, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
|
|
|
|
{
|
|
|
|
// we are going to need the PresShell
|
|
|
|
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
|
|
|
if (!ps) return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupportsArray> anonymousItems;
|
|
|
|
NS_NewISupportsArray(getter_AddRefs(anonymousItems));
|
|
|
|
if (!anonymousItems) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
mResizedObject = aResizedElement;
|
|
|
|
|
|
|
|
// the resizers and the shadow will be anonymous children of the body
|
|
|
|
nsCOMPtr<nsIDOMElement> bodyElement;
|
|
|
|
nsresult res = nsEditor::GetRootElement(getter_AddRefs(bodyElement));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
if (!bodyElement) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
|
|
|
|
|
|
|
|
// let's create the resizers
|
|
|
|
res = CreateResizer(getter_AddRefs(mTopLeftHandle),
|
|
|
|
nsIHTMLObjectResizer::eTopLeft, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = CreateResizer(getter_AddRefs(mTopHandle),
|
|
|
|
nsIHTMLObjectResizer::eTop, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = CreateResizer(getter_AddRefs(mTopRightHandle),
|
|
|
|
nsIHTMLObjectResizer::eTopRight, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
res = CreateResizer(getter_AddRefs(mLeftHandle),
|
|
|
|
nsIHTMLObjectResizer::eLeft, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = CreateResizer(getter_AddRefs(mRightHandle),
|
|
|
|
nsIHTMLObjectResizer::eRight, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
res = CreateResizer(getter_AddRefs(mBottomLeftHandle),
|
|
|
|
nsIHTMLObjectResizer::eBottomLeft, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = CreateResizer(getter_AddRefs(mBottomHandle),
|
|
|
|
nsIHTMLObjectResizer::eBottom, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = CreateResizer(getter_AddRefs(mBottomRightHandle),
|
|
|
|
nsIHTMLObjectResizer::eBottomRight, anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
// and let's set their absolute positions in the document
|
|
|
|
PRInt32 x, y;
|
|
|
|
res = SetAllResizersPosition(aResizedElement, x, y);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
// now, let's create the resizing shadow
|
|
|
|
res = CreateShadow(getter_AddRefs(mResizingShadow), anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
// and set its position
|
|
|
|
res = SetShadowPosition(aResizedElement, x, y);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
mResizingShadow->SetAttribute(NS_LITERAL_STRING("class"),
|
|
|
|
NS_LITERAL_STRING("hidden"));
|
|
|
|
|
|
|
|
|
|
|
|
// and then the resizing info tooltip
|
|
|
|
res = CreateResizingInfo(getter_AddRefs(mResizingInfo), anonymousItems);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
PRUint32 count = 0;
|
|
|
|
anonymousItems->Count(&count);
|
|
|
|
|
|
|
|
// we are going to need the document too
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
|
|
GetDocument(getter_AddRefs(domDoc));
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
|
|
|
if (!doc) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
for (PRUint32 i=0; i < count; i++) {
|
|
|
|
// for each anonymous node we created, set what's needed to make it work
|
|
|
|
// and create its frames
|
|
|
|
nsCOMPtr<nsIContent> content;
|
|
|
|
if (NS_FAILED(anonymousItems->QueryElementAt(i, NS_GET_IID(nsIContent), getter_AddRefs(content))))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
content->SetNativeAnonymous(PR_TRUE);
|
|
|
|
content->SetParent(bodyContent);
|
|
|
|
content->SetDocument(doc, PR_TRUE, PR_TRUE);
|
|
|
|
content->SetBindingParent(content);
|
|
|
|
ps->RecreateFramesFor(content);
|
|
|
|
}
|
|
|
|
|
|
|
|
// and listen to the "resize" event on the window
|
|
|
|
// first, get the script global object from the document...
|
|
|
|
nsCOMPtr<nsIScriptGlobalObject> global;
|
|
|
|
res = doc->GetScriptGlobalObject(getter_AddRefs(global));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
if (!global) { return NS_ERROR_NULL_POINTER; }
|
|
|
|
|
|
|
|
mResizeEventListenerP = new ResizeEventListener(this);
|
|
|
|
if (!mResizeEventListenerP) { return NS_ERROR_NULL_POINTER; }
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(global);
|
|
|
|
res = target->AddEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, PR_FALSE);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-03-25 18:24:08 +03:00
|
|
|
nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
|
|
|
|
nsIContent * aParentContent,
|
|
|
|
nsIDocumentObserver * aDocObserver)
|
2003-02-24 13:18:18 +03:00
|
|
|
{
|
2003-03-25 18:24:08 +03:00
|
|
|
// call ContentRemoved() for the anonymous content
|
|
|
|
// node so its references get removed from the frame manager's
|
|
|
|
// undisplay map, and its layout frames get destroyed!
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
|
|
|
if (content) {
|
|
|
|
aDocObserver->ContentRemoved(nsnull, aParentContent, content, -1);
|
2003-04-05 00:51:36 +04:00
|
|
|
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
|
|
|
|
content->SetParent(nsnull);
|
2003-03-25 18:24:08 +03:00
|
|
|
}
|
|
|
|
}
|
2003-02-24 13:18:18 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::HideResizers(void)
|
|
|
|
{
|
|
|
|
if (!mIsShowingResizeHandles || !mResizedObject)
|
|
|
|
return NS_OK;
|
|
|
|
|
2003-03-25 18:24:08 +03:00
|
|
|
// get the presshell's document observer interface.
|
|
|
|
|
|
|
|
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
|
|
|
if (!ps) return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocumentObserver> docObserver(do_QueryInterface(ps));
|
|
|
|
if (!docObserver) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// get the root content node.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> bodyElement;
|
|
|
|
nsresult res = nsEditor::GetRootElement(getter_AddRefs(bodyElement));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
if (!bodyElement) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
|
|
|
|
if (!bodyContent) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
DeleteRefToAnonymousNode(mTopLeftHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mTopLeftHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mTopHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mTopHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mTopRightHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mTopRightHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mLeftHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mLeftHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mRightHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mRightHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mBottomLeftHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mBottomLeftHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mBottomHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mBottomHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mBottomRightHandle, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mBottomRightHandle = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mResizingShadow, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mResizingShadow = nsnull;
|
2003-03-25 18:24:08 +03:00
|
|
|
DeleteRefToAnonymousNode(mResizingInfo, bodyContent, docObserver);
|
2003-02-24 13:18:18 +03:00
|
|
|
mResizingInfo = nsnull;
|
|
|
|
|
|
|
|
// don't forget to remove the listeners !
|
|
|
|
|
2003-03-25 18:24:08 +03:00
|
|
|
nsCOMPtr<nsIDOMEventReceiver> erP;
|
2003-02-24 13:18:18 +03:00
|
|
|
res = GetDOMEventReceiver(getter_AddRefs(erP));
|
2003-03-25 18:24:08 +03:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(res) && erP && mMouseMotionListenerP)
|
2003-02-24 13:18:18 +03:00
|
|
|
{
|
2003-03-25 18:24:08 +03:00
|
|
|
res = erP->RemoveEventListener(NS_LITERAL_STRING("mousemove"), mMouseMotionListenerP, PR_TRUE);
|
2003-02-24 13:18:18 +03:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
|
|
|
|
}
|
|
|
|
mMouseMotionListenerP = nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
|
|
GetDocument(getter_AddRefs(domDoc));
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
|
|
|
if (!doc) { return NS_ERROR_NULL_POINTER; }
|
|
|
|
nsCOMPtr<nsIScriptGlobalObject> global;
|
|
|
|
res = doc->GetScriptGlobalObject(getter_AddRefs(global));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
if (!global) { return NS_ERROR_NULL_POINTER; }
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(global);
|
2003-03-25 18:24:08 +03:00
|
|
|
if (target && mResizeEventListenerP) {
|
|
|
|
res = target->RemoveEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, PR_FALSE);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove resize event listener");
|
|
|
|
}
|
|
|
|
mResizeEventListenerP = nsnull;
|
2003-02-24 13:18:18 +03:00
|
|
|
|
|
|
|
mIsShowingResizeHandles = PR_FALSE;
|
|
|
|
mResizedObject = nsnull;
|
2003-04-10 01:10:58 +04:00
|
|
|
mIsResizing = PR_FALSE;
|
2003-02-24 13:18:18 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsHTMLEditor::HideShadowAndInfo()
|
|
|
|
{
|
2003-03-25 18:24:08 +03:00
|
|
|
if (mResizingShadow)
|
|
|
|
mResizingShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
|
|
|
|
if (mResizingInfo)
|
|
|
|
mResizingInfo->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
|
2003-02-24 13:18:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
|
|
|
|
{
|
|
|
|
mIsResizing = PR_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, PR_TRUE);
|
|
|
|
else if (locationStr.Equals(kTop))
|
|
|
|
SetResizeIncrements(0, 1, 0, -1, PR_FALSE);
|
|
|
|
else if (locationStr.Equals(kTopRight))
|
|
|
|
SetResizeIncrements(0, 1, 1, -1, PR_TRUE);
|
|
|
|
else if (locationStr.Equals(kLeft))
|
|
|
|
SetResizeIncrements(1, 0, -1, 0, PR_FALSE);
|
|
|
|
else if (locationStr.Equals(kRight))
|
|
|
|
SetResizeIncrements(0, 0, 1, 0, PR_FALSE);
|
|
|
|
else if (locationStr.Equals(kBottomLeft))
|
|
|
|
SetResizeIncrements(1, 0, -1, 1, PR_TRUE);
|
|
|
|
else if (locationStr.Equals(kBottom))
|
|
|
|
SetResizeIncrements(0, 0, 0, 1, PR_FALSE);
|
|
|
|
else if (locationStr.Equals(kBottomRight))
|
|
|
|
SetResizeIncrements(0, 0, 1, 1, PR_TRUE);
|
|
|
|
|
|
|
|
// make the shadow appear
|
|
|
|
mResizingShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
|
|
|
|
|
|
|
|
// position it
|
|
|
|
nsAutoString w, h;
|
|
|
|
w.AppendInt(mResizedObjectWidth);
|
|
|
|
h.AppendInt(mResizedObjectHeight);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssWidth,
|
2003-02-24 13:18:18 +03:00
|
|
|
w + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssHeight,
|
2003-02-24 13:18:18 +03:00
|
|
|
h + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
|
2003-04-10 01:10:58 +04:00
|
|
|
nsresult result = NS_OK;
|
2003-02-24 13:18:18 +03:00
|
|
|
|
2003-04-10 01:10:58 +04:00
|
|
|
if (!mMouseMotionListenerP)
|
2003-02-24 13:18:18 +03:00
|
|
|
{
|
2003-04-10 01:10:58 +04:00
|
|
|
// add a mouse move listener to the editor
|
|
|
|
mMouseMotionListenerP = new ResizerMouseMotionListener(this);
|
|
|
|
if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventReceiver> erP;
|
|
|
|
result = GetDOMEventReceiver(getter_AddRefs(erP));
|
|
|
|
if (NS_SUCCEEDED(result) && erP)
|
|
|
|
{
|
|
|
|
result = erP->AddEventListener(NS_LITERAL_STRING("mousemove"), mMouseMotionListenerP, PR_TRUE);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(result), "failed to register mouse motion listener");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleEventListenerError();
|
2003-02-24 13:18:18 +03:00
|
|
|
}
|
2003-04-10 01:10:58 +04:00
|
|
|
|
2003-02-24 13:18:18 +03:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::MouseDown(PRInt32 aClientX, PRInt32 aClientY,
|
|
|
|
nsIDOMElement *aTarget)
|
|
|
|
{
|
|
|
|
PRBool anonElement = PR_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);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
if (anonclass.Equals(NS_LITERAL_STRING("mozResizer"))) {
|
|
|
|
// and that element is a resizer, let's start resizing!
|
|
|
|
mOriginalX = aClientX;
|
|
|
|
mOriginalY = aClientY;
|
|
|
|
res = StartResizing(aTarget);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::MouseUp(PRInt32 aClientX, PRInt32 aClientY,
|
|
|
|
nsIDOMElement *aResizedObject)
|
|
|
|
{
|
|
|
|
if (mIsResizing) {
|
|
|
|
// we are resizing and release the mouse button, so let's
|
|
|
|
// end the resizing process
|
|
|
|
mIsResizing = PR_FALSE;
|
|
|
|
HideShadowAndInfo();
|
|
|
|
SetFinalSize(aClientX, aClientY);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
nsHTMLEditor::SetResizeIncrements(PRInt32 aX, PRInt32 aY,
|
|
|
|
PRInt32 aW, PRInt32 aH,
|
|
|
|
PRBool aPreserveRatio)
|
|
|
|
{
|
|
|
|
mXIncrementFactor = aX;
|
|
|
|
mYIncrementFactor = aY;
|
|
|
|
mWidthIncrementFactor = aW;
|
|
|
|
mHeightIncrementFactor = aH;
|
|
|
|
mPreserveRatio = aPreserveRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHTMLEditor::SetResizingInfoPosition(PRInt32 aX, PRInt32 aY, PRInt32 aW, PRInt32 aH)
|
|
|
|
{
|
|
|
|
nsAutoString x, y;
|
|
|
|
x.AppendInt(aX + 20);
|
|
|
|
y.AppendInt(aY + 20);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingInfo,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssLeft,
|
2003-02-24 13:18:18 +03:00
|
|
|
x + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingInfo,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssTop,
|
2003-02-24 13:18:18 +03:00
|
|
|
y + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> textInfo;
|
|
|
|
nsresult res = mResizingInfo->GetFirstChild(getter_AddRefs(textInfo));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
nsCOMPtr<nsIDOMNode> junk;
|
|
|
|
if (textInfo) {
|
|
|
|
res = mResizingInfo->RemoveChild(textInfo, getter_AddRefs(junk));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
textInfo = nsnull;
|
|
|
|
junk = nsnull;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
|
|
GetDocument(getter_AddRefs(domDoc));
|
|
|
|
|
|
|
|
nsAutoString widthStr, heightStr, diffWidthStr, diffHeightStr;
|
|
|
|
widthStr.AppendInt(aW);
|
|
|
|
heightStr.AppendInt(aH);
|
|
|
|
PRInt32 diffWidth = aW - mResizedObjectWidth;
|
|
|
|
PRInt32 diffHeight = aH - mResizedObjectHeight;
|
|
|
|
if (diffWidth > 0)
|
|
|
|
diffWidthStr = NS_LITERAL_STRING("+");
|
|
|
|
if (diffHeight > 0)
|
|
|
|
diffHeightStr = NS_LITERAL_STRING("+");
|
|
|
|
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;
|
|
|
|
res = domDoc->CreateTextNode(info, getter_AddRefs(nodeAsText));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
textInfo = do_QueryInterface(nodeAsText);
|
|
|
|
res = mResizingInfo->AppendChild(textInfo, getter_AddRefs(junk));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
PRBool hasClass = PR_FALSE;
|
|
|
|
if (NS_SUCCEEDED(mResizingInfo->HasAttribute(NS_LITERAL_STRING("class"), &hasClass )) && hasClass)
|
|
|
|
res = mResizingInfo->RemoveAttribute(NS_LITERAL_STRING("class"));
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHTMLEditor::SetShadowPosition(nsIDOMElement *aResizedObject,
|
|
|
|
PRInt32 aX, PRInt32 aY)
|
|
|
|
{
|
|
|
|
nsAutoString x, y;
|
|
|
|
x.AppendInt(aX);
|
|
|
|
y.AppendInt(aY);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssLeft,
|
2003-02-24 13:18:18 +03:00
|
|
|
x + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssTop,
|
2003-02-24 13:18:18 +03:00
|
|
|
y + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
|
|
|
|
if(NodeIsType(mResizedObject, NS_LITERAL_STRING("img"))) {
|
|
|
|
nsAutoString imageSource;
|
|
|
|
nsresult res = aResizedObject->GetAttribute(NS_LITERAL_STRING("src"),
|
|
|
|
imageSource);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = mResizingShadow->SetAttribute(NS_LITERAL_STRING("src"), imageSource);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
}
|
|
|
|
return mResizingShadow->SetAttribute(NS_LITERAL_STRING("_moz_anonclass"),
|
|
|
|
NS_LITERAL_STRING("mozResizingShadow"));
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
nsHTMLEditor::GetNewResizingIncrement(PRInt32 aX, PRInt32 aY, PRInt32 aID)
|
|
|
|
{
|
|
|
|
PRInt32 result = 0;
|
|
|
|
if (!mPreserveRatio) {
|
|
|
|
switch (aID) {
|
|
|
|
case kX:
|
|
|
|
case kWidth:
|
|
|
|
result = aX - mOriginalX;
|
|
|
|
break;
|
|
|
|
case kY:
|
|
|
|
case kHeight:
|
|
|
|
result = aY - mOriginalY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32 xi = (aX - mOriginalX) * mWidthIncrementFactor;
|
|
|
|
PRInt32 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 *= objectSizeRatio;
|
|
|
|
result *= mWidthIncrementFactor;
|
|
|
|
break;
|
|
|
|
case kY:
|
|
|
|
case kHeight:
|
|
|
|
if (result == xi)
|
|
|
|
result /= objectSizeRatio;
|
|
|
|
result *= mHeightIncrementFactor;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
nsHTMLEditor::GetNewResizingX(PRInt32 aX, PRInt32 aY)
|
|
|
|
{
|
|
|
|
PRInt32 resized = mResizedObjectX +
|
|
|
|
GetNewResizingIncrement(aX, aY, kX) * mXIncrementFactor;
|
|
|
|
PRInt32 max = mResizedObjectX + mResizedObjectWidth;
|
|
|
|
return PR_MIN(resized, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
nsHTMLEditor::GetNewResizingY(PRInt32 aX, PRInt32 aY)
|
|
|
|
{
|
|
|
|
PRInt32 resized = mResizedObjectY +
|
|
|
|
GetNewResizingIncrement(aX, aY, kY) * mYIncrementFactor;
|
|
|
|
PRInt32 max = mResizedObjectY + mResizedObjectHeight;
|
|
|
|
return PR_MIN(resized, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
nsHTMLEditor::GetNewResizingWidth(PRInt32 aX, PRInt32 aY)
|
|
|
|
{
|
|
|
|
PRInt32 resized = mResizedObjectWidth +
|
|
|
|
GetNewResizingIncrement(aX, aY, kWidth) *
|
|
|
|
mWidthIncrementFactor;
|
|
|
|
return PR_MAX(resized, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32
|
|
|
|
nsHTMLEditor::GetNewResizingHeight(PRInt32 aX, PRInt32 aY)
|
|
|
|
{
|
|
|
|
PRInt32 resized = mResizedObjectHeight +
|
|
|
|
GetNewResizingIncrement(aX, aY, kHeight) *
|
|
|
|
mHeightIncrementFactor;
|
|
|
|
return PR_MAX(resized, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
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) );
|
|
|
|
PRInt32 clientX, clientY;
|
|
|
|
mouseEvent->GetClientX(&clientX);
|
|
|
|
mouseEvent->GetClientY(&clientY);
|
|
|
|
|
|
|
|
nsAutoString x, y, w, h;
|
|
|
|
PRInt32 newWidth = GetNewResizingWidth(clientX, clientY);
|
|
|
|
PRInt32 newHeight = GetNewResizingHeight(clientX, clientY);
|
|
|
|
x.AppendInt(GetNewResizingX(clientX, clientY));
|
|
|
|
y.AppendInt(GetNewResizingY(clientX, clientY));
|
|
|
|
w.AppendInt(newWidth);
|
|
|
|
h.AppendInt(newHeight);
|
|
|
|
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssLeft,
|
2003-02-24 13:18:18 +03:00
|
|
|
x + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssTop,
|
2003-02-24 13:18:18 +03:00
|
|
|
y + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssWidth,
|
2003-02-24 13:18:18 +03:00
|
|
|
w + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizingShadow,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssHeight,
|
2003-02-24 13:18:18 +03:00
|
|
|
h + NS_LITERAL_STRING("px"),
|
|
|
|
PR_TRUE);
|
|
|
|
|
|
|
|
SetResizingInfoPosition(clientX, clientY, newWidth, newHeight);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsHTMLEditor::SetFinalSize(PRInt32 aX, PRInt32 aY)
|
|
|
|
{
|
2003-04-10 01:10:58 +04:00
|
|
|
NS_ASSERTION(mResizedObject, "SetFinalSize() called with null mResizedObject ptr!");
|
|
|
|
if (!mResizedObject) return;
|
|
|
|
|
2003-02-24 13:18:18 +03:00
|
|
|
// 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
|
|
|
|
PRInt32 width = GetNewResizingWidth(aX, aY);
|
|
|
|
PRInt32 height = GetNewResizingHeight(aX, aY);
|
|
|
|
nsAutoString w, h;
|
|
|
|
w.AppendInt(width);
|
|
|
|
h.AppendInt(height);
|
|
|
|
// keep track of that size
|
|
|
|
mResizedObjectWidth = width;
|
|
|
|
mResizedObjectHeight = height;
|
|
|
|
|
|
|
|
// we need to know if we're in a CSS-enabled editor or not
|
|
|
|
PRBool useCSS;
|
|
|
|
GetIsCSSEnabled(&useCSS);
|
|
|
|
|
|
|
|
// 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");
|
|
|
|
|
|
|
|
PRBool hasAttr = PR_FALSE;
|
|
|
|
if (useCSS) {
|
|
|
|
if (NS_SUCCEEDED(mResizedObject->HasAttribute(widthStr, &hasAttr)) && hasAttr)
|
|
|
|
RemoveAttribute(mResizedObject, widthStr);
|
|
|
|
|
|
|
|
hasAttr = PR_FALSE;
|
|
|
|
if (NS_SUCCEEDED(mResizedObject->HasAttribute(heightStr, &hasAttr)) && hasAttr)
|
|
|
|
RemoveAttribute(mResizedObject, heightStr);
|
|
|
|
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizedObject,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssWidth,
|
2003-02-24 13:18:18 +03:00
|
|
|
w + NS_LITERAL_STRING("px"),
|
|
|
|
PR_FALSE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizedObject,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssHeight,
|
2003-02-24 13:18:18 +03:00
|
|
|
h + NS_LITERAL_STRING("px"),
|
|
|
|
PR_FALSE);
|
|
|
|
}
|
|
|
|
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
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizedObject,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssWidth,
|
2003-02-24 13:18:18 +03:00
|
|
|
w + NS_LITERAL_STRING("px"),
|
|
|
|
PR_FALSE);
|
|
|
|
mHTMLCSSUtils->SetCSSProperty(mResizedObject,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssHeight,
|
2003-02-24 13:18:18 +03:00
|
|
|
h + NS_LITERAL_STRING("px"),
|
|
|
|
PR_FALSE);
|
|
|
|
|
|
|
|
SetAttribute(mResizedObject, widthStr, w);
|
|
|
|
SetAttribute(mResizedObject, heightStr, h);
|
|
|
|
|
|
|
|
mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssWidth,
|
2003-02-24 13:18:18 +03:00
|
|
|
NS_LITERAL_STRING(""),
|
|
|
|
PR_FALSE);
|
|
|
|
mHTMLCSSUtils->RemoveCSSProperty(mResizedObject,
|
2003-04-17 09:42:33 +04:00
|
|
|
nsEditProperty::cssHeight,
|
2003-02-24 13:18:18 +03:00
|
|
|
NS_LITERAL_STRING(""),
|
|
|
|
PR_FALSE);
|
|
|
|
}
|
|
|
|
RefreshResizers();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::CheckResizingState(nsISelection *aSelection)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aSelection);
|
|
|
|
|
|
|
|
if (!mIsImageResizingEnabled)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
PRBool bCollapsed;
|
|
|
|
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> focusNode;
|
|
|
|
|
|
|
|
if (bCollapsed) {
|
|
|
|
res = aSelection->GetFocusNode(getter_AddRefs(focusNode));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
PRInt32 rangeCount;
|
|
|
|
res = aSelection->GetRangeCount(&rangeCount);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
if (rangeCount == 1) {
|
2003-03-25 18:24:08 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMRange> range;
|
|
|
|
res = aSelection->GetRangeAt(0, getter_AddRefs(range));
|
2003-02-24 13:18:18 +03:00
|
|
|
if (NS_FAILED(res)) return res;
|
2003-03-25 18:24:08 +03:00
|
|
|
if (!range) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> startContainer, endContainer;
|
|
|
|
res = range->GetStartContainer(getter_AddRefs(startContainer));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = range->GetEndContainer(getter_AddRefs(endContainer));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
PRInt32 startOffset, endOffset;
|
|
|
|
res = range->GetStartOffset(&startOffset);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
res = range->GetEndOffset(&endOffset);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> focusElement;
|
|
|
|
if (startContainer == endContainer && startOffset + 1 == endOffset) {
|
|
|
|
res = GetSelectedElement(NS_LITERAL_STRING(""), getter_AddRefs(focusElement));
|
2003-02-24 13:18:18 +03:00
|
|
|
if (NS_FAILED(res)) return res;
|
2003-03-25 18:24:08 +03:00
|
|
|
if (focusElement)
|
|
|
|
focusNode = do_QueryInterface(focusElement);
|
|
|
|
}
|
|
|
|
if (!focusNode) {
|
2003-02-24 13:18:18 +03:00
|
|
|
res = range->GetCommonAncestorContainer(getter_AddRefs(focusNode));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
PRInt32 i;
|
|
|
|
nsCOMPtr<nsIDOMRange> range;
|
|
|
|
for (i = 0; i < rangeCount; i++)
|
|
|
|
{
|
|
|
|
res = aSelection->GetRangeAt(i, getter_AddRefs(range));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
nsCOMPtr<nsIDOMNode> startContainer;
|
|
|
|
range->GetStartContainer(getter_AddRefs(startContainer));
|
|
|
|
if (!focusNode)
|
|
|
|
focusNode = startContainer;
|
|
|
|
else if (focusNode != startContainer) {
|
|
|
|
res = startContainer->GetParentNode(getter_AddRefs(focusNode));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (focusNode) {
|
2003-05-16 13:08:03 +04:00
|
|
|
PRUint16 nodeType;
|
|
|
|
focusNode->GetNodeType(&nodeType);
|
|
|
|
if (nsIDOMNode::TEXT_NODE == nodeType) {
|
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
|
|
res = focusNode->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
focusNode = parent;
|
|
|
|
}
|
2003-02-24 13:18:18 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement>element;
|
|
|
|
element = do_QueryInterface(focusNode);
|
|
|
|
nsAutoString tagName;
|
|
|
|
res = element->GetTagName(tagName);
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
|
|
|
|
ToLowerCase(tagName);
|
|
|
|
nsCOMPtr<nsIAtom> tagAtom = getter_AddRefs(NS_NewAtom(tagName));
|
|
|
|
if (!tagAtom) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> tableContainer = GetEnclosingTable(focusNode);
|
|
|
|
|
2003-04-17 09:42:33 +04:00
|
|
|
if (nsEditProperty::img == tagAtom ||
|
2003-02-24 13:18:18 +03:00
|
|
|
tableContainer) {
|
|
|
|
mResizedObjectIsAnImage = PR_FALSE;
|
|
|
|
|
2003-04-17 09:42:33 +04:00
|
|
|
if (nsEditProperty::img == tagAtom)
|
2003-02-24 13:18:18 +03:00
|
|
|
mResizedObjectIsAnImage = PR_TRUE;
|
|
|
|
else {
|
|
|
|
focusNode = tableContainer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// that node is an image, we have to show resizers
|
|
|
|
element = do_QueryInterface(focusNode);
|
|
|
|
if (mIsShowingResizeHandles) {
|
|
|
|
// we were already displaying resizers and we only have to
|
|
|
|
// refresh the position
|
|
|
|
nsCOMPtr<nsIDOMNode> resizedNode = do_QueryInterface(mResizedObject);
|
|
|
|
if (!NodesSameType(focusNode, resizedNode)) {
|
|
|
|
res = HideResizers();
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
mResizedObject = element;
|
|
|
|
res = ShowResizers(element);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mResizedObject = element;
|
|
|
|
res = RefreshResizers();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// run through the whole thing
|
|
|
|
res = ShowResizers(element);
|
|
|
|
}
|
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
mIsShowingResizeHandles = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mIsShowingResizeHandles) {
|
|
|
|
// we were showing resizers but the selection is not an image any longer
|
|
|
|
res = HideResizers();
|
2003-03-25 18:24:08 +03:00
|
|
|
// just in case we were resizing... (bug 195412)
|
|
|
|
mIsResizing = PR_FALSE;
|
2003-02-24 13:18:18 +03:00
|
|
|
if (NS_FAILED(res)) return res;
|
|
|
|
// paranoia...
|
|
|
|
// mIsResizing = PR_FALSE;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::GetResizedObject(nsIDOMElement * *aResizedObject)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aResizedObject = mResizedObject);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::GetResizedObjectSize(PRInt32 *aWidth, PRInt32 *aHeight)
|
|
|
|
{
|
|
|
|
*aWidth = mResizedObjectWidth;
|
|
|
|
*aHeight = mResizedObjectHeight;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::GetIsImageResizingEnabled(PRBool *aIsImageResizingEnabled)
|
|
|
|
{
|
|
|
|
*aIsImageResizingEnabled = mIsImageResizingEnabled;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::SetIsImageResizingEnabled(PRBool aIsImageResizingEnabled)
|
|
|
|
{
|
|
|
|
mIsImageResizingEnabled = aIsImageResizingEnabled;
|
|
|
|
return NS_OK;
|
|
|
|
}
|