From 0fc82ad62985e15a3fa0e9eac3c0eef5e7bae819 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Tue, 4 Nov 2003 02:15:28 +0000 Subject: [PATCH] Refactor child element handling such that we don't duplicate event-firing code all over (now we just do it in nsGenericElement and nsXULElement). Bug 223349, r=sicking, sr=peterv --- content/base/src/nsGenericElement.cpp | 304 +++++++++--------- content/base/src/nsGenericElement.h | 54 +++- .../html/content/src/nsGenericHTMLElement.cpp | 163 ---------- .../html/content/src/nsGenericHTMLElement.h | 21 +- content/svg/content/src/nsSVGElement.cpp | 148 --------- content/svg/content/src/nsSVGElement.h | 23 +- content/xul/content/src/nsXULElement.cpp | 88 ++--- 7 files changed, 278 insertions(+), 523 deletions(-) diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index dd43f4f48e4a..d8a35b1ee348 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -2491,6 +2491,160 @@ nsGenericElement::DoneCreatingElement() return NS_OK; } +NS_IMETHODIMP +nsGenericElement::InsertChildAt(nsIContent* aKid, + PRUint32 aIndex, + PRBool aNotify, + PRBool aDeepSetDocument) +{ + NS_PRECONDITION(aKid, "null ptr"); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + + if (!InternalInsertChildAt(aKid, aIndex)) { + return NS_OK; + } + + NS_ADDREF(aKid); + aKid->SetParent(this); + nsRange::OwnerChildInserted(this, aIndex); + if (mDocument) { + aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); + if (aNotify) { + mDocument->ContentInserted(this, aKid, aIndex); + } + + if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_NODEINSERTED; + mutation.mTarget = do_QueryInterface(aKid); + mutation.mRelatedNode = do_QueryInterface(this); + + nsEventStatus status = nsEventStatus_eIgnore; + aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); + } + } + return NS_OK; +} + +NS_IMETHODIMP +nsGenericElement::ReplaceChildAt(nsIContent* aKid, + PRUint32 aIndex, + PRBool aNotify, + PRBool aDeepSetDocument) +{ + NS_PRECONDITION(aKid, "null ptr"); + nsIContent* oldKid = GetChildAt(aIndex); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + + nsRange::OwnerChildReplaced(this, aIndex, oldKid); + if (!InternalReplaceChildAt(aKid, aIndex)) { + return NS_OK; + } + + NS_ADDREF(aKid); + aKid->SetParent(this); + if (mDocument) { + aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); + if (aNotify) { + mDocument->ContentReplaced(this, oldKid, aKid, aIndex); + } + if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED)) { + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_SUBTREEMODIFIED; + mutation.mTarget = do_QueryInterface(this); + mutation.mRelatedNode = do_QueryInterface(oldKid); + + nsEventStatus status = nsEventStatus_eIgnore; + HandleDOMEvent(nsnull, &mutation, nsnull, + NS_EVENT_FLAG_INIT, &status); + } + } + + if (oldKid) { + oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); + oldKid->SetParent(nsnull); + NS_RELEASE(oldKid); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsGenericElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, + PRBool aDeepSetDocument) +{ + NS_PRECONDITION(aKid && this != aKid, "null ptr"); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + + if (!InternalAppendChildTo(aKid)) { + return NS_OK; + } + + NS_ADDREF(aKid); + aKid->SetParent(this); + // ranges don't need adjustment since new child is at end of list + if (mDocument) { + aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); + if (aNotify) { + mDocument->ContentAppended(this, GetChildCount() - 1); + } + + if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_NODEINSERTED; + mutation.mTarget = do_QueryInterface(aKid); + mutation.mRelatedNode = do_QueryInterface(this); + + nsEventStatus status = nsEventStatus_eIgnore; + aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); + } + } + return NS_OK; +} + +NS_IMETHODIMP +nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +{ + nsIContent* oldKid = GetChildAt(aIndex); + if (oldKid) { + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + + if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) { + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_NODEREMOVED; + mutation.mTarget = do_QueryInterface(oldKid); + + mutation.mRelatedNode = do_QueryInterface(this); + + nsEventStatus status = nsEventStatus_eIgnore; + oldKid->HandleDOMEvent(nsnull, &mutation, nsnull, + NS_EVENT_FLAG_INIT, &status); + } + + nsRange::OwnerChildRemoved(this, aIndex, oldKid); + + if (!InternalRemoveChildAt(aIndex)) { + return NS_OK; + } + + if (aNotify && mDocument) { + mDocument->ContentRemoved(this, oldKid, aIndex); + } + + oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); + oldKid->SetParent(nsnull); + NS_RELEASE(oldKid); + } + + return NS_OK; +} + + + //---------------------------------------------------------------------- // Generic DOMNode implementations @@ -3823,153 +3977,3 @@ nsGenericContainerElement::IndexOf(nsIContent* aPossibleChild) const return mChildren.IndexOf(aPossibleChild); } - -nsresult -nsGenericContainerElement::InsertChildAt(nsIContent* aKid, - PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid, "null ptr"); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/ - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - nsRange::OwnerChildInserted(this, aIndex); - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentInserted(this, aKid, aIndex); - } - - if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - aKid->HandleDOMEvent(nsnull, &mutation, nsnull, - NS_EVENT_FLAG_INIT, &status); - } - } - } - - return NS_OK; -} - -nsresult -nsGenericContainerElement::ReplaceChildAt(nsIContent* aKid, - PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid, "null ptr"); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); - nsRange::OwnerChildReplaced(this, aIndex, oldKid); - PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex); - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentReplaced(this, oldKid, aKid, aIndex); - } - } - oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); - oldKid->SetParent(nsnull); - NS_RELEASE(oldKid); - } - - return NS_OK; -} - -nsresult -nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid, "null ptr"); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - PRBool rv = mChildren.AppendElement(aKid); - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - // ranges don't need adjustment since new child is at end of list - if (doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentAppended(this, mChildren.Count() - 1); - } - - if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - aKid->HandleDOMEvent(nsnull, &mutation, nsnull, - NS_EVENT_FLAG_INIT, &status); - } - } - } - - return NS_OK; -} - -nsresult -nsGenericContainerElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) -{ - nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); - if (oldKid) { - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) { - nsCOMPtr node(do_QueryInterface(oldKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEREMOVED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - nsCOMPtr domEvent; - oldKid->HandleDOMEvent(nsnull, &mutation, nsnull, - NS_EVENT_FLAG_INIT, &status); - } - - nsRange::OwnerChildRemoved(this, aIndex, oldKid); - - mChildren.RemoveElementAt(aIndex); - if (aNotify) { - if (doc) { - doc->ContentRemoved(this, oldKid, aIndex); - } - } - oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); - oldKid->SetParent(nsnull); - NS_RELEASE(oldKid); - } - - return NS_OK; -} diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index 987f4c2b9d39..00fd2f35b940 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -393,6 +393,16 @@ public: NS_IMETHOD GetBaseURL(nsIURI** aBaseURL) const; NS_IMETHOD DoneCreatingElement(); + // Declare these here so we can consolidate the implementations. + // Subclasses that don't want to implement these should override. + NS_IMETHOD InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, + PRBool aDeepSetDocument); + NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, + PRBool aDeepSetDocument); + NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify, + PRBool aDeepSetDocument); + NS_IMETHOD RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + // nsIStyledContent interface methods NS_IMETHOD GetID(nsIAtom** aResult) const; @@ -580,6 +590,29 @@ public: static PLDHashTable sRangeListsHash; protected: + /** + * InsertChildAt/ReplaceChildAt/AppendChildTo/RemoveChildAt subclass + * hooks. These methods are called to perform the actual moving + * around of content nodes in child lists. The return value should + * be true if something changed, false otherwise. + * + * These methods should not change the refcount on the kids in question; + * that's handled by the + * InsertChildAt/ReplaceChildAt/AppendChildTo/RemoveChildAt functions. + */ + virtual PRBool InternalInsertChildAt(nsIContent* aKid, PRUint32 aIndex) { + return PR_FALSE; + } + virtual PRBool InternalReplaceChildAt(nsIContent* aKid, PRUint32 aIndex) { + return PR_FALSE; + } + virtual PRBool InternalAppendChildTo(nsIContent* aKid) { + return PR_FALSE; + } + virtual PRBool InternalRemoveChildAt(PRUint32 aIndex) { + return PR_FALSE; + } + PRBool HasDOMSlots() const { return !(mFlagsOrSlots & GENERIC_ELEMENT_DOESNT_HAVE_DOMSLOTS); @@ -780,14 +813,21 @@ public: NS_IMETHOD_(PRUint32) GetChildCount() const; NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const; NS_IMETHOD_(PRInt32) IndexOf(nsIContent* aPossibleChild) const; - NS_IMETHOD InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + // Child list modification hooks + virtual PRBool InternalInsertChildAt(nsIContent* aKid, PRUint32 aIndex) { + return mChildren.InsertElementAt(aKid, aIndex); + } + virtual PRBool InternalReplaceChildAt(nsIContent* aKid, PRUint32 aIndex) { + return mChildren.ReplaceElementAt(aKid, aIndex); + } + virtual PRBool InternalAppendChildTo(nsIContent* aKid) { + return mChildren.AppendElement(aKid); + } + virtual PRBool InternalRemoveChildAt(PRUint32 aIndex) { + return mChildren.RemoveElementAt(aIndex); + } + #ifdef DEBUG void ListAttributes(FILE* out) const; #endif diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 111216deb5bb..45954501e409 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -3795,169 +3795,6 @@ nsGenericHTMLContainerElement::IndexOf(nsIContent* aPossibleChild) const return mChildren.IndexOf(aPossibleChild); } -NS_IMETHODIMP -nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid, - PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid, "null ptr"); - nsIDocument* doc = mDocument; - - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/ - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - nsRange::OwnerChildInserted(this, aIndex); - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentInserted(this, aKid, aIndex); - } - - if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); - } - } - } - return NS_OK; -} - -NS_IMETHODIMP -nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid, - PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid, "null ptr"); - nsIContent* oldKid = NS_STATIC_CAST(nsIContent *, - mChildren.SafeElementAt(aIndex)); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - nsRange::OwnerChildReplaced(this, aIndex, oldKid); - PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex); - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentReplaced(this, oldKid, aKid, aIndex); - } - } - if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED)) { - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_SUBTREEMODIFIED; - mutation.mTarget = do_QueryInterface(this); - mutation.mRelatedNode = do_QueryInterface(oldKid); - - nsEventStatus status = nsEventStatus_eIgnore; - HandleDOMEvent(nsnull, &mutation, nsnull, - NS_EVENT_FLAG_INIT, &status); - } - - if (oldKid) { - oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); - oldKid->SetParent(nsnull); - NS_RELEASE(oldKid); - } - } - - return NS_OK; -} - -NS_IMETHODIMP -nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid && this != aKid, "null ptr"); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - PRBool rv = mChildren.AppendElement(aKid); - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - // ranges don't need adjustment since new child is at end of list - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentAppended(this, mChildren.Count() - 1); - } - - if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); - } - } - } - return NS_OK; -} - -NS_IMETHODIMP -nsGenericHTMLContainerElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) -{ - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - nsIContent* oldKid = NS_STATIC_CAST(nsIContent *, - mChildren.SafeElementAt(aIndex)); - if (nsnull != oldKid ) { - - if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) { - nsCOMPtr node(do_QueryInterface(oldKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEREMOVED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - oldKid->HandleDOMEvent(nsnull, &mutation, nsnull, - NS_EVENT_FLAG_INIT, &status); - } - - nsRange::OwnerChildRemoved(this, aIndex, oldKid); - - mChildren.RemoveElementAt(aIndex); - if (aNotify) { - if (nsnull != doc) { - doc->ContentRemoved(this, oldKid, aIndex); - } - } - oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); - oldKid->SetParent(nsnull); - NS_RELEASE(oldKid); - } - - return NS_OK; -} - nsresult nsGenericHTMLContainerElement::ReplaceContentsWithText(const nsAString& aText, PRBool aNotify) diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 62269acf528a..8ff7e55e12cf 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -894,13 +894,20 @@ public: NS_IMETHOD_(PRUint32) GetChildCount() const; NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const; NS_IMETHOD_(PRInt32) IndexOf(nsIContent* aPossibleChild) const; - NS_IMETHOD InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + + // Child list modification hooks + virtual PRBool InternalInsertChildAt(nsIContent* aKid, PRUint32 aIndex) { + return mChildren.InsertElementAt(aKid, aIndex); + } + virtual PRBool InternalReplaceChildAt(nsIContent* aKid, PRUint32 aIndex) { + return mChildren.ReplaceElementAt(aKid, aIndex); + } + virtual PRBool InternalAppendChildTo(nsIContent* aKid) { + return mChildren.AppendElement(aKid); + } + virtual PRBool InternalRemoveChildAt(PRUint32 aIndex) { + return mChildren.RemoveElementAt(aIndex); + } /** The list of children */ nsSmallVoidArray mChildren; diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index f821930cf357..34bf02e17535 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -151,154 +151,6 @@ nsSVGElement::IndexOf(nsIContent* aPossibleChild) const return mChildren.IndexOf(aPossibleChild); } -NS_IMETHODIMP -nsSVGElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid, "null ptr"); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/ - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - nsRange::OwnerChildInserted(this, aIndex); - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentInserted(this, aKid, aIndex); - } - - if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - nsCOMPtr domEvent; - aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status); - } - } - } - - return NS_OK; -} - -NS_IMETHODIMP -nsSVGElement::ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid, "null ptr"); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); - nsRange::OwnerChildReplaced(this, aIndex, oldKid); - PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex); - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentReplaced(this, oldKid, aKid, aIndex); - } - } - oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); - oldKid->SetParent(nsnull); - NS_RELEASE(oldKid); - } - return NS_OK; -} - -NS_IMETHODIMP -nsSVGElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, - PRBool aDeepSetDocument) -{ - NS_PRECONDITION(nsnull != aKid && this != aKid, "null ptr"); - nsIDocument* doc = mDocument; - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - PRBool rv = mChildren.AppendElement(aKid); - if (rv) { - NS_ADDREF(aKid); - aKid->SetParent(this); - // ranges don't need adjustment since new child is at end of list - if (nsnull != doc) { - aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE); - if (aNotify) { - doc->ContentAppended(this, mChildren.Count() - 1); - } - - if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - nsCOMPtr domEvent; - aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status); - } - } - } - - return NS_OK; -} - -NS_IMETHODIMP -nsSVGElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) -{ - nsIDocument* doc = mDocument; - - nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); - if (nsnull != oldKid ) { - mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); - - if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) { - nsCOMPtr node(do_QueryInterface(oldKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEREMOVED; - mutation.mTarget = node; - - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - mutation.mRelatedNode = relNode; - - nsEventStatus status = nsEventStatus_eIgnore; - nsCOMPtr domEvent; - oldKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), - NS_EVENT_FLAG_INIT, &status); - } - - nsRange::OwnerChildRemoved(this, aIndex, oldKid); - - mChildren.RemoveElementAt(aIndex); - if (aNotify) { - if (nsnull != doc) { - doc->ContentRemoved(this, oldKid, aIndex); - } - } - oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); - oldKid->SetParent(nsnull); - NS_RELEASE(oldKid); - } - - return NS_OK; -} - NS_IMETHODIMP_(nsIAtom*) nsSVGElement::GetIDAttributeName() const { diff --git a/content/svg/content/src/nsSVGElement.h b/content/svg/content/src/nsSVGElement.h index 024d8cdc9eb6..e1667a95f3ca 100644 --- a/content/svg/content/src/nsSVGElement.h +++ b/content/svg/content/src/nsSVGElement.h @@ -75,15 +75,6 @@ public: NS_IMETHOD_(PRUint32) GetChildCount() const; NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const; NS_IMETHOD_(PRInt32) IndexOf(nsIContent* aPossibleChild) const; - NS_IMETHOD InsertChildAt(nsIContent* aKid, PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, - PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify, - PRBool aDeepSetDocument); - NS_IMETHOD RemoveChildAt(PRUint32 aIndex, PRBool aNotify); NS_IMETHOD_(nsIAtom *) GetIDAttributeName() const; NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, @@ -110,6 +101,20 @@ public: NS_IMETHOD DumpContent(FILE* out, PRInt32 aIndent,PRBool aDumpAll) const; #endif // DEBUG + // Child list modification hooks + virtual PRBool InternalInsertChildAt(nsIContent* aKid, PRUint32 aIndex) { + return mChildren.InsertElementAt(aKid, aIndex); + } + virtual PRBool InternalReplaceChildAt(nsIContent* aKid, PRUint32 aIndex) { + return mChildren.ReplaceElementAt(aKid, aIndex); + } + virtual PRBool InternalAppendChildTo(nsIContent* aKid) { + return mChildren.AppendElement(aKid); + } + virtual PRBool InternalRemoveChildAt(PRUint32 aIndex) { + return mChildren.RemoveElementAt(aIndex); + } + // NS_IMETHOD RangeAdd(nsIDOMRange& aRange); // NS_IMETHOD RangeRemove(nsIDOMRange& aRange); // NS_IMETHOD GetRangeList(nsVoidArray** aResult) const; diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index dd05e7da4d46..1eb050caccc3 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -1938,21 +1938,20 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, return NS_ERROR_FAILURE; NS_ADDREF(aKid); - aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); + aKid->SetParent(this); //nsRange::OwnerChildInserted(this, aIndex); aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); - if (mDocument && HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), + if (mDocument && HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); nsMutationEvent mutation; mutation.eventStructType = NS_MUTATION_EVENT; mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; + mutation.mTarget = do_QueryInterface(aKid); - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this))); - mutation.mRelatedNode = relNode; + mutation.mRelatedNode = + do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)); nsEventStatus status = nsEventStatus_eIgnore; aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); @@ -1985,19 +1984,32 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, if (oldKid == aKid) return NS_OK; - //XXXbz should this fire DOMSubtreeModified? mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); PRBool replaceOk = mChildren.ReplaceElementAt(aKid, aIndex); if (replaceOk) { NS_ADDREF(aKid); - aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); + aKid->SetParent(this); //nsRange::OwnerChildReplaced(this, aIndex, oldKid); - aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); + if (mDocument) { + aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); - if (aNotify && mDocument) { - mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex); + if (aNotify) { + mDocument->ContentReplaced(this, oldKid, aKid, aIndex); + } + if (HasMutationListeners(this, + NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED)) { + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_SUBTREEMODIFIED; + mutation.mTarget = do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)); + mutation.mRelatedNode = do_QueryInterface(oldKid); + + nsEventStatus status = nsEventStatus_eIgnore; + HandleDOMEvent(nsnull, &mutation, nsnull, + NS_EVENT_FLAG_INIT, &status); + } } // This will cause the script object to be unrooted for each @@ -2025,29 +2037,31 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, PRBool aDeepSetDoc PRBool appendOk = mChildren.AppendElement(aKid); if (appendOk) { NS_ADDREF(aKid); - aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); + aKid->SetParent(this); // ranges don't need adjustment since new child is at end of list - aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); + if (mDocument) { + aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); - if (mDocument && HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), - NS_EVENT_BITS_MUTATION_NODEINSERTED)) { - nsCOMPtr node(do_QueryInterface(aKid)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_NODEINSERTED; - mutation.mTarget = node; + if (aNotify) { + mDocument->ContentAppended(this, mChildren.Count() - 1); + } + + if (HasMutationListeners(this, + NS_EVENT_BITS_MUTATION_NODEINSERTED)) { + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_NODEINSERTED; + mutation.mTarget = do_QueryInterface(aKid); - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this))); - mutation.mRelatedNode = relNode; + mutation.mRelatedNode = + do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)); - nsEventStatus status = nsEventStatus_eIgnore; - aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); + nsEventStatus status = nsEventStatus_eIgnore; + aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); + } } - if (aNotify && mDocument) { - mDocument->ContentAppended(NS_STATIC_CAST(nsIStyledContent*, this), mChildren.Count() - 1); - } } return NS_OK; } @@ -2065,15 +2079,14 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); - if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), NS_EVENT_BITS_MUTATION_NODEREMOVED)) { - nsCOMPtr node(do_QueryInterface(oldKid)); + if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) { nsMutationEvent mutation; mutation.eventStructType = NS_MUTATION_EVENT; mutation.message = NS_MUTATION_NODEREMOVED; - mutation.mTarget = node; + mutation.mTarget = do_QueryInterface(oldKid); - nsCOMPtr relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this))); - mutation.mRelatedNode = relNode; + mutation.mRelatedNode = + do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)); nsEventStatus status = nsEventStatus_eIgnore; oldKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); @@ -2141,11 +2154,10 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) } if (oldKid) { - nsIDocument* doc = mDocument; PRBool removeOk = mChildren.RemoveElementAt(aIndex); //nsRange::OwnerChildRemoved(this, aIndex, oldKid); if (aNotify && removeOk && mDocument) { - doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex); + mDocument->ContentRemoved(this, oldKid, aIndex); } if (newCurrentIndex == -2) @@ -2398,11 +2410,10 @@ nsXULElement::FinishSetAttr(PRInt32 aAttrNS, nsIAtom* aAttrName, binding->AttributeChanged(aAttrName, aAttrNS, PR_FALSE, aNotify); if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { - nsCOMPtr node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this))); nsMutationEvent mutation; mutation.eventStructType = NS_MUTATION_EVENT; mutation.message = NS_MUTATION_ATTRMODIFIED; - mutation.mTarget = node; + mutation.mTarget = do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)); nsAutoString attrName2; aAttrName->ToString(attrName2); @@ -2644,12 +2655,11 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, // Fire mutation listeners if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { - // XXXwaterson ugh, why do we QI() on ourself? - nsCOMPtr node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this))); nsMutationEvent mutation; mutation.eventStructType = NS_MUTATION_EVENT; mutation.message = NS_MUTATION_ATTRMODIFIED; - mutation.mTarget = node; + mutation.mTarget = + do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)); nsAutoString attrName2; aName->ToString(attrName2);