meta-fix for image and table resizing bugs in html editor

solves bugs 195412, 196624, 196122, 195849, 197158, 195141, 195126, 199013
r=brade, sr=kin
This commit is contained in:
glazman%netscape.com 2003-03-25 15:24:08 +00:00
Родитель 95ba6eac66
Коммит f720ae0368
7 изменённых файлов: 126 добавлений и 243 удалений

Просмотреть файл

@ -263,8 +263,6 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::DoTransaction(void)
else
mRedoAttributeWasSet = PR_TRUE;
CheckObjectResizing();
return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
}
@ -308,18 +306,12 @@ nsresult ChangeCSSInlineStyleTxn::SetStyle(PRBool aAttributeWasSet,
NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void)
{
nsresult res = SetStyle(mUndoAttributeWasSet, mUndoValue);
if (NS_SUCCEEDED(res))
CheckObjectResizing();
return res;
return SetStyle(mUndoAttributeWasSet, mUndoValue);
}
NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void)
{
nsresult res = SetStyle(mRedoAttributeWasSet, mRedoValue);
if (NS_SUCCEEDED(res))
CheckObjectResizing();
return res;
return SetStyle(mRedoAttributeWasSet, mRedoValue);
}
NS_IMETHODIMP ChangeCSSInlineStyleTxn::Merge(nsITransaction *aTransaction, PRBool *aDidMerge)
@ -373,19 +365,3 @@ ChangeCSSInlineStyleTxn::AddValueToMultivalueProperty(nsAString & aValues, const
}
return NS_OK;
}
void
ChangeCSSInlineStyleTxn::CheckObjectResizing()
{
// HACK !!!!! We absolutely need this because setting an inline CSS
// property does not trigger a DOMAttrModified event related to the
// style attribute (perf reasons I suppose)
nsCOMPtr<nsIHTMLObjectResizer> imageResizer = do_QueryInterface(mEditor);
if (imageResizer) {
nsCOMPtr<nsIDOMElement> resizedObject;
imageResizer->GetResizedObject(getter_AddRefs(resizedObject));
if (resizedObject == mElement)
imageResizer->RefreshResizers();
}
}

Просмотреть файл

@ -124,8 +124,6 @@ private:
*/
nsresult SetStyle(PRBool aAttributeWasSet, nsAString & aValue);
void CheckObjectResizing();
public:
NS_IMETHOD DoTransaction(void);

Просмотреть файл

@ -534,7 +534,7 @@ public:
nsresult GetString(const nsAString& name, nsAString& value);
nsresult BeginUpdateViewBatch(void);
nsresult EndUpdateViewBatch(void);
virtual nsresult EndUpdateViewBatch(void);
PRBool GetShouldTxnSetSelection();

Просмотреть файл

@ -6037,3 +6037,25 @@ nsHTMLEditor::GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 &
return NS_OK;
}
nsresult
nsHTMLEditor::EndUpdateViewBatch()
{
nsresult res = nsEditor::EndUpdateViewBatch();
if (NS_FAILED(res)) return res;
// We may need to show resizing handles or update existing ones after
// all transactions are done. This way of doing is preferred to DOM
// mutation events listeners because all the changes the user can apply
// to a document may result in multiple events, some of them quite hard
// to listen too (in particular when an ancestor of the selection is
// changed but the selection itself is not changed).
if (mUpdateCount == 0) {
nsCOMPtr<nsISelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NOT_INITIALIZED;
res = CheckResizingState(selection);
}
return res;
}

Просмотреть файл

@ -48,6 +48,7 @@
#include "nsITableEditor.h"
#include "nsIEditorMailSupport.h"
#include "nsIEditorStyleSheets.h"
#include "nsIDocumentObserver.h"
#include "nsEditor.h"
#include "nsIDOMElement.h"
@ -377,6 +378,8 @@ public:
/* ------------ Overrides of nsEditor interface methods -------------- */
nsresult EndUpdateViewBatch();
/** prepare the editor for use */
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell, nsIContent *aRoot, nsISelectionController *aSelCon, PRUint32 aFlags);
@ -865,7 +868,6 @@ protected:
nsCOMPtr<nsIDOMElement> mResizedObject;
nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
nsCOMPtr<nsIDOMEventListener> mMutationListenerP;
nsCOMPtr<nsISelectionListener> mSelectionListenerP;
nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
@ -900,7 +902,9 @@ protected:
PRInt32 GetNewResizingHeight(PRInt32 aX, PRInt32 aY);
void HideShadowAndInfo();
void SetFinalSize(PRInt32 aX, PRInt32 aY);
void DeleteRefToAnonymousNode(nsIDOMNode * aNode);
void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
nsIContent * aParentContent,
nsIDocumentObserver * aDocObserver);
void SetResizeIncrements(PRInt32 aX, PRInt32 aY, PRInt32 aW, PRInt32 aH, PRBool aPreserveRatio);
nsresult GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY);
public:

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDocumentObserver.h"
#include "nsIEditor.h"
#include "nsIPresShell.h"
#include "nsIScriptGlobalObject.h"
@ -122,106 +123,6 @@ ResizerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection
return NS_OK;
}
// ==================================================================
// ResizerMutationListener
// ==================================================================
NS_IMPL_ADDREF(ResizerMutationListener)
NS_IMPL_RELEASE(ResizerMutationListener)
ResizerMutationListener::ResizerMutationListener(nsIHTMLEditor * aEditor):
mEditor(aEditor)
{
}
ResizerMutationListener::~ResizerMutationListener()
{
}
NS_IMETHODIMP
ResizerMutationListener::SubtreeModified(nsIDOMEvent* aMutationEvent)
{
return NS_OK;
}
NS_IMETHODIMP
ResizerMutationListener::NodeInserted(nsIDOMEvent* aMutationEvent)
{
return NS_OK;
}
NS_IMETHODIMP
ResizerMutationListener::NodeRemoved(nsIDOMEvent* aMutationEvent)
{
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(mEditor);
nsCOMPtr<nsIDOMEventTarget> target;
nsresult res = aMutationEvent->GetTarget(getter_AddRefs(target));
if (NS_FAILED(res)) return res;
if (!target) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMElement> targetElement = do_QueryInterface(target);
nsCOMPtr<nsIDOMElement> resizedElt;
objectResizer->GetResizedObject(getter_AddRefs(resizedElt));
if (resizedElt == targetElement)
return objectResizer->HideResizers();
return NS_OK;
}
NS_IMETHODIMP
ResizerMutationListener::NodeRemovedFromDocument(nsIDOMEvent* aMutationEvent)
{
return NS_OK;
}
NS_IMETHODIMP
ResizerMutationListener::NodeInsertedIntoDocument(nsIDOMEvent* aMutationEvent)
{
return NS_OK;
}
NS_IMETHODIMP
ResizerMutationListener::AttrModified(nsIDOMEvent* aMutationEvent)
{
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(mEditor);
nsCOMPtr<nsIDOMElement> elt;
objectResizer->GetResizedObject(getter_AddRefs(elt));
PRInt32 w, h;
nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(elt);
if (!nsElement) {return NS_ERROR_NULL_POINTER; }
// let's get the size of the resized object
nsElement->GetOffsetWidth(&w);
nsElement->GetOffsetHeight(&h);
// and let's get the last size we dealt with
PRInt32 objectW, objectH;
objectResizer->GetResizedObjectSize(&objectW, &objectH);
// if the sizes are different, let's refresh the resizers
if (w != objectW || h != objectH)
objectResizer->RefreshResizers();
return NS_OK;
}
NS_IMETHODIMP
ResizerMutationListener::CharacterDataModified(nsIDOMEvent* aMutationEvent)
{
return NS_OK;
}
NS_IMETHODIMP
ResizerMutationListener::HandleEvent(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_INTERFACE_MAP_BEGIN(ResizerMutationListener)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMutationListener)
NS_INTERFACE_MAP_END
// ==================================================================
// ResizerMouseMotionListener
// ==================================================================
@ -540,18 +441,6 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
ps->RecreateFramesFor(content);
}
// listen to attribute changes on the resized object
mMutationListenerP = new ResizerMutationListener(this);
nsCOMPtr<nsIDOMEventReceiver> erP = do_QueryInterface(mResizedObject);
res = erP->AddEventListener(NS_LITERAL_STRING("DOMAttrModified"), mMutationListenerP, PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(res), "failed to register DOMAttrModified event listener");
nsCOMPtr<nsIDOMNode> parentNode;
res = mResizedObject->GetParentNode(getter_AddRefs(parentNode));
erP = do_QueryInterface(parentNode);
res = erP->AddEventListener(NS_LITERAL_STRING("DOMNodeRemoved"), mMutationListenerP, PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(res), "failed to register NodeRemoved event listener");
// and listen to the "resize" event on the window
// first, get the script global object from the document...
nsCOMPtr<nsIScriptGlobalObject> global;
@ -568,18 +457,19 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
}
void
nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMNode * aNode)
nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
nsIContent * aParentContent,
nsIDocumentObserver * aDocObserver)
{
nsCOMPtr<nsIDOMElement> elt = do_QueryInterface(aNode);
NS_ASSERTION(elt, "anonymous node is not an element");
// let's destroy element's frame
elt->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
// 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(aNode);
content->SetParent(nsnull);
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
content->SetBindingParent(nsnull);
}
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (content) {
aDocObserver->ContentRemoved(nsnull, aParentContent, content, -1);
}
}
NS_IMETHODIMP
nsHTMLEditor::HideResizers(void)
@ -587,51 +477,54 @@ nsHTMLEditor::HideResizers(void)
if (!mIsShowingResizeHandles || !mResizedObject)
return NS_OK;
DeleteRefToAnonymousNode(mTopLeftHandle);
mTopLeftHandle = nsnull;
DeleteRefToAnonymousNode(mTopHandle);
mTopHandle = nsnull;
DeleteRefToAnonymousNode(mTopRightHandle);
mTopRightHandle = nsnull;
DeleteRefToAnonymousNode(mLeftHandle);
mLeftHandle = nsnull;
DeleteRefToAnonymousNode(mRightHandle);
mRightHandle = nsnull;
DeleteRefToAnonymousNode(mBottomLeftHandle);
mBottomLeftHandle = nsnull;
DeleteRefToAnonymousNode(mBottomHandle);
mBottomHandle = nsnull;
DeleteRefToAnonymousNode(mBottomRightHandle);
mBottomRightHandle = nsnull;
// get the presshell's document observer interface.
DeleteRefToAnonymousNode(mResizingShadow);
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);
mTopLeftHandle = nsnull;
DeleteRefToAnonymousNode(mTopHandle, bodyContent, docObserver);
mTopHandle = nsnull;
DeleteRefToAnonymousNode(mTopRightHandle, bodyContent, docObserver);
mTopRightHandle = nsnull;
DeleteRefToAnonymousNode(mLeftHandle, bodyContent, docObserver);
mLeftHandle = nsnull;
DeleteRefToAnonymousNode(mRightHandle, bodyContent, docObserver);
mRightHandle = nsnull;
DeleteRefToAnonymousNode(mBottomLeftHandle, bodyContent, docObserver);
mBottomLeftHandle = nsnull;
DeleteRefToAnonymousNode(mBottomHandle, bodyContent, docObserver);
mBottomHandle = nsnull;
DeleteRefToAnonymousNode(mBottomRightHandle, bodyContent, docObserver);
mBottomRightHandle = nsnull;
DeleteRefToAnonymousNode(mResizingShadow, bodyContent, docObserver);
mResizingShadow = nsnull;
DeleteRefToAnonymousNode(mResizingInfo);
DeleteRefToAnonymousNode(mResizingInfo, bodyContent, docObserver);
mResizingInfo = nsnull;
// don't forget to remove the listeners !
nsCOMPtr<nsIDOMEventReceiver> erP = do_QueryInterface(mResizedObject);
nsresult res = erP->RemoveEventListener(NS_LITERAL_STRING("DOMAttrModified"), mMutationListenerP, PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove AttrModified mutation event listener");
nsCOMPtr<nsIDOMNode> parentNode;
res = mResizedObject->GetParentNode(getter_AddRefs(parentNode));
erP = do_QueryInterface(parentNode);
NS_ASSERTION(erP, "Failed to get event receiver!");
if (erP)
{
res = erP->RemoveEventListener(NS_LITERAL_STRING("DOMNodeRemoved"),
mMutationListenerP, PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(res),
"failed to remove NodeRemoved event listener");
}
mMutationListenerP = nsnull;
nsCOMPtr<nsIDOMEventReceiver> erP;
res = GetDOMEventReceiver(getter_AddRefs(erP));
if (NS_SUCCEEDED(res))
if (NS_SUCCEEDED(res) && erP && mMouseMotionListenerP)
{
res = erP->RemoveEventListenerByIID(mMouseMotionListenerP, NS_GET_IID(nsIDOMMouseMotionListener));
res = erP->RemoveEventListener(NS_LITERAL_STRING("mousemove"), mMouseMotionListenerP, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
}
mMouseMotionListenerP = nsnull;
@ -646,8 +539,11 @@ nsHTMLEditor::HideResizers(void)
if (!global) { return NS_ERROR_NULL_POINTER; }
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(global);
res = target->RemoveEventListener(NS_LITERAL_STRING("resize"), mResizeEventListenerP, PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove resize event listener");
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;
mIsShowingResizeHandles = PR_FALSE;
mResizedObject = nsnull;
@ -658,8 +554,10 @@ nsHTMLEditor::HideResizers(void)
void
nsHTMLEditor::HideShadowAndInfo()
{
mResizingShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
mResizingInfo->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
if (mResizingShadow)
mResizingShadow->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
if (mResizingInfo)
mResizingInfo->SetAttribute(NS_LITERAL_STRING("class"), NS_LITERAL_STRING("hidden"));
}
nsresult
@ -710,9 +608,9 @@ nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
nsCOMPtr<nsIDOMEventReceiver> erP;
nsresult result = GetDOMEventReceiver(getter_AddRefs(erP));
if (NS_SUCCEEDED(result))
if (NS_SUCCEEDED(result) && erP)
{
result = erP->AddEventListenerByIID(mMouseMotionListenerP, NS_GET_IID(nsIDOMMouseMotionListener));
result = erP->AddEventListener(NS_LITERAL_STRING("mousemove"), mMouseMotionListenerP, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(result), "failed to register mouse motion listener");
}
else
@ -995,10 +893,6 @@ nsHTMLEditor::SetFinalSize(PRInt32 aX, PRInt32 aY)
PRBool useCSS;
GetIsCSSEnabled(&useCSS);
// let's remove the DOMMutationEvent listener for the moment
nsCOMPtr<nsIDOMEventReceiver> erP = do_QueryInterface(mResizedObject);
erP->RemoveEventListener(NS_LITERAL_STRING("DOMAttrModified"), mMutationListenerP, PR_FALSE);
// we want one transaction only from a user's point of view
nsAutoEditBatch batchIt(this);
@ -1051,7 +945,6 @@ nsHTMLEditor::SetFinalSize(PRInt32 aX, PRInt32 aY)
PR_FALSE);
}
RefreshResizers();
erP->AddEventListener(NS_LITERAL_STRING("DOMAttrModified"), mMutationListenerP, PR_FALSE);
}
NS_IMETHODIMP
@ -1079,16 +972,31 @@ nsHTMLEditor::CheckResizingState(nsISelection *aSelection)
if (NS_FAILED(res)) return res;
if (rangeCount == 1) {
nsCOMPtr<nsIDOMElement> focusElement;
res = GetSelectedElement(NS_LITERAL_STRING(""), getter_AddRefs(focusElement));
nsCOMPtr<nsIDOMRange> range;
res = aSelection->GetRangeAt(0, getter_AddRefs(range));
if (NS_FAILED(res)) return res;
if (focusElement)
focusNode = do_QueryInterface(focusElement);
else {
nsCOMPtr<nsIDOMRange> range;
res = aSelection->GetRangeAt(0, getter_AddRefs(range));
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));
if (NS_FAILED(res)) return res;
if (!range) return NS_ERROR_NULL_POINTER;
if (focusElement)
focusNode = do_QueryInterface(focusElement);
}
if (!focusNode) {
res = range->GetCommonAncestorContainer(getter_AddRefs(focusNode));
if (NS_FAILED(res)) return res;
}
@ -1175,6 +1083,8 @@ nsHTMLEditor::CheckResizingState(nsISelection *aSelection)
if (mIsShowingResizeHandles) {
// we were showing resizers but the selection is not an image any longer
res = HideResizers();
// just in case we were resizing... (bug 195412)
mIsResizing = PR_FALSE;
if (NS_FAILED(res)) return res;
// paranoia...
// mIsResizing = PR_FALSE;

Просмотреть файл

@ -52,7 +52,6 @@
#include "nsIDOMEventListener.h"
#include "nsISelectionListener.h"
#include "nsIDOMMutationListener.h"
#include "nsIDOMMouseMotionListener.h"
#define kTopLeft NS_LITERAL_STRING("nw")
@ -79,38 +78,11 @@ public:
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
NS_DECL_NSISELECTIONLISTENER
protected:
nsCOMPtr<nsIHTMLEditor> mEditor;
};
// ==================================================================
// ResizerMutationListener
// ==================================================================
class ResizerMutationListener : public nsIDOMMutationListener
{
public:
ResizerMutationListener (nsIHTMLEditor * aEditor);
virtual ~ResizerMutationListener ();
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
NS_IMETHOD SubtreeModified(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeInserted(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeRemoved(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeRemovedFromDocument(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeInsertedIntoDocument(nsIDOMEvent* aMutationEvent);
NS_IMETHOD AttrModified(nsIDOMEvent* aMutationEvent);
NS_IMETHOD CharacterDataModified(nsIDOMEvent* aMutationEvent);
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
protected:
nsCOMPtr<nsIHTMLEditor> mEditor;
nsIHTMLEditor * mEditor;
};
// ==================================================================
@ -127,12 +99,13 @@ public:
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
protected:
nsCOMPtr<nsIHTMLEditor> mEditor;
nsIHTMLEditor * mEditor;
};
@ -149,10 +122,10 @@ public:
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_DECL_NSIDOMEVENTLISTENER
protected:
nsCOMPtr<nsIHTMLEditor> mEditor;
nsIHTMLEditor * mEditor;
};