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
This commit is contained in:
bzbarsky%mit.edu 2003-11-04 02:15:28 +00:00
Родитель 602eb22f1c
Коммит 0fc82ad629
7 изменённых файлов: 278 добавлений и 523 удалений

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

@ -2491,6 +2491,160 @@ nsGenericElement::DoneCreatingElement()
return NS_OK; 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 // Generic DOMNode implementations
@ -3823,153 +3977,3 @@ nsGenericContainerElement::IndexOf(nsIContent* aPossibleChild) const
return mChildren.IndexOf(aPossibleChild); 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<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> 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<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> 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<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> 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;
}

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

@ -393,6 +393,16 @@ public:
NS_IMETHOD GetBaseURL(nsIURI** aBaseURL) const; NS_IMETHOD GetBaseURL(nsIURI** aBaseURL) const;
NS_IMETHOD DoneCreatingElement(); 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 // nsIStyledContent interface methods
NS_IMETHOD GetID(nsIAtom** aResult) const; NS_IMETHOD GetID(nsIAtom** aResult) const;
@ -580,6 +590,29 @@ public:
static PLDHashTable sRangeListsHash; static PLDHashTable sRangeListsHash;
protected: 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 PRBool HasDOMSlots() const
{ {
return !(mFlagsOrSlots & GENERIC_ELEMENT_DOESNT_HAVE_DOMSLOTS); return !(mFlagsOrSlots & GENERIC_ELEMENT_DOESNT_HAVE_DOMSLOTS);
@ -780,14 +813,21 @@ public:
NS_IMETHOD_(PRUint32) GetChildCount() const; NS_IMETHOD_(PRUint32) GetChildCount() const;
NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const; NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const;
NS_IMETHOD_(PRInt32) IndexOf(nsIContent* aPossibleChild) 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 #ifdef DEBUG
void ListAttributes(FILE* out) const; void ListAttributes(FILE* out) const;
#endif #endif

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

@ -3795,169 +3795,6 @@ nsGenericHTMLContainerElement::IndexOf(nsIContent* aPossibleChild) const
return mChildren.IndexOf(aPossibleChild); 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<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> 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<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> 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<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> 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 nsresult
nsGenericHTMLContainerElement::ReplaceContentsWithText(const nsAString& aText, nsGenericHTMLContainerElement::ReplaceContentsWithText(const nsAString& aText,
PRBool aNotify) PRBool aNotify)

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

@ -894,13 +894,20 @@ public:
NS_IMETHOD_(PRUint32) GetChildCount() const; NS_IMETHOD_(PRUint32) GetChildCount() const;
NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const; NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const;
NS_IMETHOD_(PRInt32) IndexOf(nsIContent* aPossibleChild) const; NS_IMETHOD_(PRInt32) IndexOf(nsIContent* aPossibleChild) const;
NS_IMETHOD InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
PRBool aDeepSetDocument); // Child list modification hooks
NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, virtual PRBool InternalInsertChildAt(nsIContent* aKid, PRUint32 aIndex) {
PRBool aDeepSetDocument); return mChildren.InsertElementAt(aKid, aIndex);
NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify, }
PRBool aDeepSetDocument); virtual PRBool InternalReplaceChildAt(nsIContent* aKid, PRUint32 aIndex) {
NS_IMETHOD RemoveChildAt(PRUint32 aIndex, PRBool aNotify); 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 */ /** The list of children */
nsSmallVoidArray mChildren; nsSmallVoidArray mChildren;

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

@ -151,154 +151,6 @@ nsSVGElement::IndexOf(nsIContent* aPossibleChild) const
return mChildren.IndexOf(aPossibleChild); 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<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> 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<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> 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<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> 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*) NS_IMETHODIMP_(nsIAtom*)
nsSVGElement::GetIDAttributeName() const nsSVGElement::GetIDAttributeName() const
{ {

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

@ -75,15 +75,6 @@ public:
NS_IMETHOD_(PRUint32) GetChildCount() const; NS_IMETHOD_(PRUint32) GetChildCount() const;
NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const; NS_IMETHOD_(nsIContent *) GetChildAt(PRUint32 aIndex) const;
NS_IMETHOD_(PRInt32) IndexOf(nsIContent* aPossibleChild) 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_(nsIAtom *) GetIDAttributeName() const;
NS_IMETHOD_(already_AddRefed<nsINodeInfo>) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD_(already_AddRefed<nsINodeInfo>) GetExistingAttrNameFromQName(const nsAString& aStr);
NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@ -110,6 +101,20 @@ public:
NS_IMETHOD DumpContent(FILE* out, PRInt32 aIndent,PRBool aDumpAll) const; NS_IMETHOD DumpContent(FILE* out, PRInt32 aIndent,PRBool aDumpAll) const;
#endif // DEBUG #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 RangeAdd(nsIDOMRange& aRange);
// NS_IMETHOD RangeRemove(nsIDOMRange& aRange); // NS_IMETHOD RangeRemove(nsIDOMRange& aRange);
// NS_IMETHOD GetRangeList(nsVoidArray** aResult) const; // NS_IMETHOD GetRangeList(nsVoidArray** aResult) const;

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

@ -1938,21 +1938,20 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
NS_ADDREF(aKid); NS_ADDREF(aKid);
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(this);
//nsRange::OwnerChildInserted(this, aIndex); //nsRange::OwnerChildInserted(this, aIndex);
aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE);
if (mDocument && HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), if (mDocument && HasMutationListeners(this,
NS_EVENT_BITS_MUTATION_NODEINSERTED)) { NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation; nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT; mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED; mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node; mutation.mTarget = do_QueryInterface(aKid);
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this))); mutation.mRelatedNode =
mutation.mRelatedNode = relNode; do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this));
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); 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) if (oldKid == aKid)
return NS_OK; return NS_OK;
//XXXbz should this fire DOMSubtreeModified?
mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
PRBool replaceOk = mChildren.ReplaceElementAt(aKid, aIndex); PRBool replaceOk = mChildren.ReplaceElementAt(aKid, aIndex);
if (replaceOk) { if (replaceOk) {
NS_ADDREF(aKid); NS_ADDREF(aKid);
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(this);
//nsRange::OwnerChildReplaced(this, aIndex, oldKid); //nsRange::OwnerChildReplaced(this, aIndex, oldKid);
aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE); if (mDocument) {
aKid->SetDocument(mDocument, aDeepSetDocument, PR_TRUE);
if (aNotify && mDocument) { if (aNotify) {
mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex); 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 // 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); PRBool appendOk = mChildren.AppendElement(aKid);
if (appendOk) { if (appendOk) {
NS_ADDREF(aKid); 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 // 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), if (aNotify) {
NS_EVENT_BITS_MUTATION_NODEINSERTED)) { mDocument->ContentAppended(this, mChildren.Count() - 1);
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid)); }
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT; if (HasMutationListeners(this,
mutation.message = NS_MUTATION_NODEINSERTED; NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
mutation.mTarget = node; nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = do_QueryInterface(aKid);
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this))); mutation.mRelatedNode =
mutation.mRelatedNode = relNode; do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this));
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); 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; return NS_OK;
} }
@ -2065,15 +2079,14 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify);
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), NS_EVENT_BITS_MUTATION_NODEREMOVED)) { if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation; nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT; mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED; mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node; mutation.mTarget = do_QueryInterface(oldKid);
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this))); mutation.mRelatedNode =
mutation.mRelatedNode = relNode; do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this));
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
oldKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status); oldKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status);
@ -2141,11 +2154,10 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
} }
if (oldKid) { if (oldKid) {
nsIDocument* doc = mDocument;
PRBool removeOk = mChildren.RemoveElementAt(aIndex); PRBool removeOk = mChildren.RemoveElementAt(aIndex);
//nsRange::OwnerChildRemoved(this, aIndex, oldKid); //nsRange::OwnerChildRemoved(this, aIndex, oldKid);
if (aNotify && removeOk && mDocument) { if (aNotify && removeOk && mDocument) {
doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex); mDocument->ContentRemoved(this, oldKid, aIndex);
} }
if (newCurrentIndex == -2) if (newCurrentIndex == -2)
@ -2398,11 +2410,10 @@ nsXULElement::FinishSetAttr(PRInt32 aAttrNS, nsIAtom* aAttrName,
binding->AttributeChanged(aAttrName, aAttrNS, PR_FALSE, aNotify); binding->AttributeChanged(aAttrName, aAttrNS, PR_FALSE, aNotify);
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
nsMutationEvent mutation; nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT; mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED; mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node; mutation.mTarget = do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this));
nsAutoString attrName2; nsAutoString attrName2;
aAttrName->ToString(attrName2); aAttrName->ToString(attrName2);
@ -2644,12 +2655,11 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID,
// Fire mutation listeners // Fire mutation listeners
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this),
NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
// XXXwaterson ugh, why do we QI() on ourself?
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
nsMutationEvent mutation; nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT; mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED; mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node; mutation.mTarget =
do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this));
nsAutoString attrName2; nsAutoString attrName2;
aName->ToString(attrName2); aName->ToString(attrName2);