From d768a81fb7c82c8dc7ecf30e13bcfe478a976e14 Mon Sep 17 00:00:00 2001 From: "waterson%netscape.com" Date: Fri, 17 Sep 1999 04:29:53 +0000 Subject: [PATCH] Bug 13790. Okay, let's try that again, this time without the frills. git-svn-id: svn://10.0.0.236/trunk@47913 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xul/document/src/nsXULDocument.cpp | 220 +++++++++++------- mozilla/rdf/content/src/nsXULDocument.cpp | 220 +++++++++++------- 2 files changed, 280 insertions(+), 160 deletions(-) diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index cadd669d5f1..dadab688bf2 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -206,12 +206,7 @@ static NS_DEFINE_IID(kIWordBreakerFactoryIID, NS_IWORDBREAKERFACTORY_IID); //////////////////////////////////////////////////////////////////////// // Standard vocabulary items -DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf); -DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, type); - #define XUL_NAMESPACE_URI "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" -#define XUL_NAMESPACE_URI_PREFIX XUL_NAMESPACE_URI "#" -DEFINE_RDF_VOCAB(XUL_NAMESPACE_URI_PREFIX, XUL, element); static PRLogModuleInfo* gMapLog; static PRLogModuleInfo* gXULLog; @@ -807,10 +802,16 @@ public: nsresult RebuildWidgetItem(nsIContent* aElement); nsresult - AddElementToMap(nsIContent* aElement, PRBool aDeep); + AddSubtreeToDocument(nsIContent* aElement); nsresult - RemoveElementFromMap(nsIContent* aElement, PRBool aDeep); + RemoveSubtreeFromDocument(nsIContent* aElement); + + nsresult + AddElementToMap(nsIContent* aElement); + + nsresult + RemoveElementFromMap(nsIContent* aElement); static PRIntn RemoveElementsFromMapByContent(nsIRDFResource* aResource, @@ -850,23 +851,21 @@ protected: protected: // pseudo constants static PRInt32 gRefCnt; - static nsIAtom* kContainerContentsGeneratedAtom; + + static nsIAtom* kCommandUpdaterAtom; + static nsIAtom* kEventsAtom; static nsIAtom* kIdAtom; static nsIAtom* kObservesAtom; static nsIAtom* kOpenAtom; static nsIAtom* kPersistAtom; static nsIAtom* kRefAtom; static nsIAtom* kRuleAtom; + static nsIAtom* kTargetsAtom; static nsIAtom* kTemplateAtom; - static nsIAtom* kTemplateContentsGeneratedAtom; - static nsIAtom* kXULContentsGeneratedAtom; static nsIAtom** kIdentityAttrs[]; static nsIRDFService* gRDFService; - static nsIRDFResource* kRDF_instanceOf; - static nsIRDFResource* kRDF_type; - static nsIRDFResource* kXUL_element; static nsINameSpaceManager* gNameSpaceManager; static PRInt32 kNameSpaceID_XUL; @@ -939,21 +938,19 @@ protected: }; PRInt32 XULDocumentImpl::gRefCnt = 0; -nsIAtom* XULDocumentImpl::kContainerContentsGeneratedAtom; + +nsIAtom* XULDocumentImpl::kCommandUpdaterAtom; +nsIAtom* XULDocumentImpl::kEventsAtom; nsIAtom* XULDocumentImpl::kIdAtom; nsIAtom* XULDocumentImpl::kObservesAtom; nsIAtom* XULDocumentImpl::kOpenAtom; nsIAtom* XULDocumentImpl::kPersistAtom; nsIAtom* XULDocumentImpl::kRefAtom; nsIAtom* XULDocumentImpl::kRuleAtom; +nsIAtom* XULDocumentImpl::kTargetsAtom; nsIAtom* XULDocumentImpl::kTemplateAtom; -nsIAtom* XULDocumentImpl::kTemplateContentsGeneratedAtom; -nsIAtom* XULDocumentImpl::kXULContentsGeneratedAtom; nsIRDFService* XULDocumentImpl::gRDFService; -nsIRDFResource* XULDocumentImpl::kRDF_instanceOf; -nsIRDFResource* XULDocumentImpl::kRDF_type; -nsIRDFResource* XULDocumentImpl::kXUL_element; nsINameSpaceManager* XULDocumentImpl::gNameSpaceManager; PRInt32 XULDocumentImpl::kNameSpaceID_XUL; @@ -986,16 +983,16 @@ XULDocumentImpl::XULDocumentImpl(void) }*/ if (gRefCnt++ == 0) { - kContainerContentsGeneratedAtom = NS_NewAtom("containercontentsgenerated"); + kCommandUpdaterAtom = NS_NewAtom("commandupdater"); + kEventsAtom = NS_NewAtom("events"); kIdAtom = NS_NewAtom("id"); kObservesAtom = NS_NewAtom("observes"); kOpenAtom = NS_NewAtom("open"); kPersistAtom = NS_NewAtom("persist"); kRefAtom = NS_NewAtom("ref"); kRuleAtom = NS_NewAtom("rule"); + kTargetsAtom = NS_NewAtom("targets"); kTemplateAtom = NS_NewAtom("template"); - kTemplateContentsGeneratedAtom = NS_NewAtom("templatecontentsgenerated"); - kXULContentsGeneratedAtom = NS_NewAtom("xulcontentsgenerated"); // Keep the RDF service cached in a member variable to make using // it a bit less painful @@ -1005,12 +1002,6 @@ XULDocumentImpl::XULDocumentImpl(void) NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF Service"); - if (gRDFService) { - gRDFService->GetResource(kURIRDF_instanceOf, &kRDF_instanceOf); - gRDFService->GetResource(kURIRDF_type, &kRDF_type); - gRDFService->GetResource(kURIXUL_element, &kXUL_element); - } - rv = nsServiceManager::GetService(kNameSpaceManagerCID, nsCOMTypeInfo::GetIID(), (nsISupports**) &gNameSpaceManager); @@ -1098,26 +1089,22 @@ XULDocumentImpl::~XULDocumentImpl() } if (--gRefCnt == 0) { - NS_IF_RELEASE(kContainerContentsGeneratedAtom); + NS_IF_RELEASE(kCommandUpdaterAtom); + NS_IF_RELEASE(kEventsAtom); NS_IF_RELEASE(kIdAtom); NS_IF_RELEASE(kObservesAtom); NS_IF_RELEASE(kOpenAtom); NS_IF_RELEASE(kPersistAtom); NS_IF_RELEASE(kRefAtom); NS_IF_RELEASE(kRuleAtom); + NS_IF_RELEASE(kTargetsAtom); NS_IF_RELEASE(kTemplateAtom); - NS_IF_RELEASE(kTemplateContentsGeneratedAtom); - NS_IF_RELEASE(kXULContentsGeneratedAtom); if (gRDFService) { nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); gRDFService = nsnull; } - NS_IF_RELEASE(kRDF_instanceOf); - NS_IF_RELEASE(kRDF_type); - NS_IF_RELEASE(kXUL_element); - if (gXULUtils) { nsServiceManager::ReleaseService(kXULContentUtilsCID, gXULUtils); gXULUtils = nsnull; @@ -2080,6 +2067,14 @@ XULDocumentImpl::EndLoad() NS_POSTCONDITION(mRootContent != nsnull, "unable to create root content"); if (! mRootContent) return NS_ERROR_UNEXPECTED; + + // Do any initial hookup that needs to happen. + // + // XXX Because we are now doing this, maybe we can remove all + // the code from the RDFXULBuilderImpl that adds and removes + // elements from the element map? + rv = AddSubtreeToDocument(mRootContent); + if (NS_FAILED(rv)) return rv; } StartLayout(); @@ -2143,7 +2138,7 @@ XULDocumentImpl::AttributeChanged(nsIContent* aElement, // That'll have removed _both_ the 'ref' and 'id' entries from // the map. So add 'em back now. - rv = AddElementToMap(aElement, PR_FALSE); + rv = AddElementToMap(aElement); if (NS_FAILED(rv)) return rv; } } @@ -2218,7 +2213,7 @@ XULDocumentImpl::ContentAppended(nsIContent* aContainer, rv = aContainer->ChildAt(i, *getter_AddRefs(child)); if (NS_FAILED(rv)) return rv; - rv = AddElementToMap(child, PR_TRUE); + rv = AddSubtreeToDocument(child); if (NS_FAILED(rv)) return rv; } } @@ -2239,10 +2234,9 @@ XULDocumentImpl::ContentInserted(nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer) { - // First update our element map { nsresult rv; - rv = AddElementToMap(aChild, PR_TRUE); + rv = AddSubtreeToDocument(aChild); if (NS_FAILED(rv)) return rv; } @@ -2263,13 +2257,12 @@ XULDocumentImpl::ContentReplaced(nsIContent* aContainer, nsIContent* aNewChild, PRInt32 aIndexInContainer) { - // First update our element map { nsresult rv; - rv = RemoveElementFromMap(aOldChild, PR_TRUE); + rv = RemoveSubtreeFromDocument(aOldChild); if (NS_FAILED(rv)) return rv; - rv = AddElementToMap(aNewChild, PR_TRUE); + rv = AddSubtreeToDocument(aNewChild); if (NS_FAILED(rv)) return rv; } @@ -2290,10 +2283,9 @@ XULDocumentImpl::ContentRemoved(nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer) { - // First update our element map { nsresult rv; - rv = RemoveElementFromMap(aChild, PR_TRUE); + rv = RemoveSubtreeFromDocument(aChild); if (NS_FAILED(rv)) return rv; } @@ -3358,11 +3350,112 @@ XULDocumentImpl::GetElementById(const nsString& aId, nsIDOMElement** aReturn) return NS_OK; } +nsresult +XULDocumentImpl::AddSubtreeToDocument(nsIContent* aElement) +{ + // Do a bunch of work that's necessary when an element gets added + // to the XUL Document. + nsresult rv; + + // 1. Add the element to the resource-to-element map + rv = AddElementToMap(aElement); + if (NS_FAILED(rv)) return rv; + + // 2. If the element is a 'command updater' (i.e., has a + // "commandupdater='true'" attribute), then add the element to the + // document's command dispatcher + nsAutoString value; + rv = aElement->GetAttribute(kNameSpaceID_None, kCommandUpdaterAtom, value); + if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && value.Equals("true")) { + nsAutoString events; + rv = aElement->GetAttribute(kNameSpaceID_None, kEventsAtom, events); + + if (rv != NS_CONTENT_ATTR_HAS_VALUE) + events = "*"; + + nsAutoString targets; + rv = aElement->GetAttribute(kNameSpaceID_None, kTargetsAtom, targets); + + if (rv != NS_CONTENT_ATTR_HAS_VALUE) + targets = "*"; + + nsCOMPtr domelement = do_QueryInterface(aElement); + NS_ASSERTION(domelement != nsnull, "not a DOM element"); + if (! domelement) + return NS_ERROR_UNEXPECTED; + + rv = mCommandDispatcher->AddCommandUpdater(domelement, events, targets); + if (NS_FAILED(rv)) return rv; + } + + PRInt32 count; + nsCOMPtr xulcontent = do_QueryInterface(aElement); + rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); + if (NS_FAILED(rv)) return rv; + + while (--count >= 0) { + nsCOMPtr child; + rv = aElement->ChildAt(count, *getter_AddRefs(child)); + if (NS_FAILED(rv)) return rv; + + rv = AddSubtreeToDocument(child); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + +nsresult +XULDocumentImpl::RemoveSubtreeFromDocument(nsIContent* aElement) +{ + // Do a bunch of cleanup to remove an element from the XUL + // document. + nsresult rv; + + PRInt32 count; + nsCOMPtr xulcontent = do_QueryInterface(aElement); + rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); + if (NS_FAILED(rv)) return rv; + + while (--count >= 0) { + nsCOMPtr child; + rv = aElement->ChildAt(count, *getter_AddRefs(child)); + if (NS_FAILED(rv)) return rv; + + rv = RemoveSubtreeFromDocument(child); + if (NS_FAILED(rv)) return rv; + } + + // 1. Remove the element from the resource-to-element map + rv = RemoveElementFromMap(aElement); + if (NS_FAILED(rv)) return rv; + + // 2. If the element is a 'command updater', then remove the + // element from the document's command dispatcher. + nsAutoString value; + rv = aElement->GetAttribute(kNameSpaceID_None, kCommandUpdaterAtom, value); + if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && value.Equals("true")) { + nsCOMPtr domelement = do_QueryInterface(aElement); + NS_ASSERTION(domelement != nsnull, "not a DOM element"); + if (! domelement) + return NS_ERROR_UNEXPECTED; + + rv = mCommandDispatcher->RemoveCommandUpdater(domelement); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + +// Attributes that are used with getElementById() and the +// resource-to-element map. nsIAtom** XULDocumentImpl::kIdentityAttrs[] = { &kIdAtom, &kRefAtom, nsnull }; nsresult -XULDocumentImpl::AddElementToMap(nsIContent* aElement, PRBool aDeep) +XULDocumentImpl::AddElementToMap(nsIContent* aElement) { + // Look at the element's 'id' and 'ref' attributes, and if set, + // add pointers in the resource-to-element map to the element. nsresult rv; PRInt32 nameSpaceID; @@ -3386,29 +3479,14 @@ XULDocumentImpl::AddElementToMap(nsIContent* aElement, PRBool aDeep) } } - if (aDeep) { - PRInt32 count; - nsCOMPtr xulcontent = do_QueryInterface(aElement); - rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); - if (NS_FAILED(rv)) return rv; - - while (--count > 0) { - nsCOMPtr child; - rv = aElement->ChildAt(count, *getter_AddRefs(child)); - if (NS_FAILED(rv)) return rv; - - rv = AddElementToMap(child, PR_TRUE); - if (NS_FAILED(rv)) return rv; - } - } - return NS_OK; } nsresult -XULDocumentImpl::RemoveElementFromMap(nsIContent* aElement, PRBool aDeep) +XULDocumentImpl::RemoveElementFromMap(nsIContent* aElement) { + // Remove the element from the resource-to-element map. nsresult rv; PRInt32 nameSpaceID; @@ -3432,22 +3510,6 @@ XULDocumentImpl::RemoveElementFromMap(nsIContent* aElement, PRBool aDeep) } } - if (aDeep) { - PRInt32 count; - nsCOMPtr xulcontent = do_QueryInterface(aElement); - rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); - if (NS_FAILED(rv)) return rv; - - while (--count > 0) { - nsCOMPtr child; - rv = aElement->ChildAt(count, *getter_AddRefs(child)); - if (NS_FAILED(rv)) return rv; - - rv = RemoveElementFromMap(child, PR_TRUE); - if (NS_FAILED(rv)) return rv; - } - } - return NS_OK; } @@ -4694,5 +4756,3 @@ XULDocumentImpl::RebuildWidgetItem(nsIContent* aElement) } - - diff --git a/mozilla/rdf/content/src/nsXULDocument.cpp b/mozilla/rdf/content/src/nsXULDocument.cpp index cadd669d5f1..dadab688bf2 100644 --- a/mozilla/rdf/content/src/nsXULDocument.cpp +++ b/mozilla/rdf/content/src/nsXULDocument.cpp @@ -206,12 +206,7 @@ static NS_DEFINE_IID(kIWordBreakerFactoryIID, NS_IWORDBREAKERFACTORY_IID); //////////////////////////////////////////////////////////////////////// // Standard vocabulary items -DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf); -DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, type); - #define XUL_NAMESPACE_URI "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" -#define XUL_NAMESPACE_URI_PREFIX XUL_NAMESPACE_URI "#" -DEFINE_RDF_VOCAB(XUL_NAMESPACE_URI_PREFIX, XUL, element); static PRLogModuleInfo* gMapLog; static PRLogModuleInfo* gXULLog; @@ -807,10 +802,16 @@ public: nsresult RebuildWidgetItem(nsIContent* aElement); nsresult - AddElementToMap(nsIContent* aElement, PRBool aDeep); + AddSubtreeToDocument(nsIContent* aElement); nsresult - RemoveElementFromMap(nsIContent* aElement, PRBool aDeep); + RemoveSubtreeFromDocument(nsIContent* aElement); + + nsresult + AddElementToMap(nsIContent* aElement); + + nsresult + RemoveElementFromMap(nsIContent* aElement); static PRIntn RemoveElementsFromMapByContent(nsIRDFResource* aResource, @@ -850,23 +851,21 @@ protected: protected: // pseudo constants static PRInt32 gRefCnt; - static nsIAtom* kContainerContentsGeneratedAtom; + + static nsIAtom* kCommandUpdaterAtom; + static nsIAtom* kEventsAtom; static nsIAtom* kIdAtom; static nsIAtom* kObservesAtom; static nsIAtom* kOpenAtom; static nsIAtom* kPersistAtom; static nsIAtom* kRefAtom; static nsIAtom* kRuleAtom; + static nsIAtom* kTargetsAtom; static nsIAtom* kTemplateAtom; - static nsIAtom* kTemplateContentsGeneratedAtom; - static nsIAtom* kXULContentsGeneratedAtom; static nsIAtom** kIdentityAttrs[]; static nsIRDFService* gRDFService; - static nsIRDFResource* kRDF_instanceOf; - static nsIRDFResource* kRDF_type; - static nsIRDFResource* kXUL_element; static nsINameSpaceManager* gNameSpaceManager; static PRInt32 kNameSpaceID_XUL; @@ -939,21 +938,19 @@ protected: }; PRInt32 XULDocumentImpl::gRefCnt = 0; -nsIAtom* XULDocumentImpl::kContainerContentsGeneratedAtom; + +nsIAtom* XULDocumentImpl::kCommandUpdaterAtom; +nsIAtom* XULDocumentImpl::kEventsAtom; nsIAtom* XULDocumentImpl::kIdAtom; nsIAtom* XULDocumentImpl::kObservesAtom; nsIAtom* XULDocumentImpl::kOpenAtom; nsIAtom* XULDocumentImpl::kPersistAtom; nsIAtom* XULDocumentImpl::kRefAtom; nsIAtom* XULDocumentImpl::kRuleAtom; +nsIAtom* XULDocumentImpl::kTargetsAtom; nsIAtom* XULDocumentImpl::kTemplateAtom; -nsIAtom* XULDocumentImpl::kTemplateContentsGeneratedAtom; -nsIAtom* XULDocumentImpl::kXULContentsGeneratedAtom; nsIRDFService* XULDocumentImpl::gRDFService; -nsIRDFResource* XULDocumentImpl::kRDF_instanceOf; -nsIRDFResource* XULDocumentImpl::kRDF_type; -nsIRDFResource* XULDocumentImpl::kXUL_element; nsINameSpaceManager* XULDocumentImpl::gNameSpaceManager; PRInt32 XULDocumentImpl::kNameSpaceID_XUL; @@ -986,16 +983,16 @@ XULDocumentImpl::XULDocumentImpl(void) }*/ if (gRefCnt++ == 0) { - kContainerContentsGeneratedAtom = NS_NewAtom("containercontentsgenerated"); + kCommandUpdaterAtom = NS_NewAtom("commandupdater"); + kEventsAtom = NS_NewAtom("events"); kIdAtom = NS_NewAtom("id"); kObservesAtom = NS_NewAtom("observes"); kOpenAtom = NS_NewAtom("open"); kPersistAtom = NS_NewAtom("persist"); kRefAtom = NS_NewAtom("ref"); kRuleAtom = NS_NewAtom("rule"); + kTargetsAtom = NS_NewAtom("targets"); kTemplateAtom = NS_NewAtom("template"); - kTemplateContentsGeneratedAtom = NS_NewAtom("templatecontentsgenerated"); - kXULContentsGeneratedAtom = NS_NewAtom("xulcontentsgenerated"); // Keep the RDF service cached in a member variable to make using // it a bit less painful @@ -1005,12 +1002,6 @@ XULDocumentImpl::XULDocumentImpl(void) NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF Service"); - if (gRDFService) { - gRDFService->GetResource(kURIRDF_instanceOf, &kRDF_instanceOf); - gRDFService->GetResource(kURIRDF_type, &kRDF_type); - gRDFService->GetResource(kURIXUL_element, &kXUL_element); - } - rv = nsServiceManager::GetService(kNameSpaceManagerCID, nsCOMTypeInfo::GetIID(), (nsISupports**) &gNameSpaceManager); @@ -1098,26 +1089,22 @@ XULDocumentImpl::~XULDocumentImpl() } if (--gRefCnt == 0) { - NS_IF_RELEASE(kContainerContentsGeneratedAtom); + NS_IF_RELEASE(kCommandUpdaterAtom); + NS_IF_RELEASE(kEventsAtom); NS_IF_RELEASE(kIdAtom); NS_IF_RELEASE(kObservesAtom); NS_IF_RELEASE(kOpenAtom); NS_IF_RELEASE(kPersistAtom); NS_IF_RELEASE(kRefAtom); NS_IF_RELEASE(kRuleAtom); + NS_IF_RELEASE(kTargetsAtom); NS_IF_RELEASE(kTemplateAtom); - NS_IF_RELEASE(kTemplateContentsGeneratedAtom); - NS_IF_RELEASE(kXULContentsGeneratedAtom); if (gRDFService) { nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); gRDFService = nsnull; } - NS_IF_RELEASE(kRDF_instanceOf); - NS_IF_RELEASE(kRDF_type); - NS_IF_RELEASE(kXUL_element); - if (gXULUtils) { nsServiceManager::ReleaseService(kXULContentUtilsCID, gXULUtils); gXULUtils = nsnull; @@ -2080,6 +2067,14 @@ XULDocumentImpl::EndLoad() NS_POSTCONDITION(mRootContent != nsnull, "unable to create root content"); if (! mRootContent) return NS_ERROR_UNEXPECTED; + + // Do any initial hookup that needs to happen. + // + // XXX Because we are now doing this, maybe we can remove all + // the code from the RDFXULBuilderImpl that adds and removes + // elements from the element map? + rv = AddSubtreeToDocument(mRootContent); + if (NS_FAILED(rv)) return rv; } StartLayout(); @@ -2143,7 +2138,7 @@ XULDocumentImpl::AttributeChanged(nsIContent* aElement, // That'll have removed _both_ the 'ref' and 'id' entries from // the map. So add 'em back now. - rv = AddElementToMap(aElement, PR_FALSE); + rv = AddElementToMap(aElement); if (NS_FAILED(rv)) return rv; } } @@ -2218,7 +2213,7 @@ XULDocumentImpl::ContentAppended(nsIContent* aContainer, rv = aContainer->ChildAt(i, *getter_AddRefs(child)); if (NS_FAILED(rv)) return rv; - rv = AddElementToMap(child, PR_TRUE); + rv = AddSubtreeToDocument(child); if (NS_FAILED(rv)) return rv; } } @@ -2239,10 +2234,9 @@ XULDocumentImpl::ContentInserted(nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer) { - // First update our element map { nsresult rv; - rv = AddElementToMap(aChild, PR_TRUE); + rv = AddSubtreeToDocument(aChild); if (NS_FAILED(rv)) return rv; } @@ -2263,13 +2257,12 @@ XULDocumentImpl::ContentReplaced(nsIContent* aContainer, nsIContent* aNewChild, PRInt32 aIndexInContainer) { - // First update our element map { nsresult rv; - rv = RemoveElementFromMap(aOldChild, PR_TRUE); + rv = RemoveSubtreeFromDocument(aOldChild); if (NS_FAILED(rv)) return rv; - rv = AddElementToMap(aNewChild, PR_TRUE); + rv = AddSubtreeToDocument(aNewChild); if (NS_FAILED(rv)) return rv; } @@ -2290,10 +2283,9 @@ XULDocumentImpl::ContentRemoved(nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer) { - // First update our element map { nsresult rv; - rv = RemoveElementFromMap(aChild, PR_TRUE); + rv = RemoveSubtreeFromDocument(aChild); if (NS_FAILED(rv)) return rv; } @@ -3358,11 +3350,112 @@ XULDocumentImpl::GetElementById(const nsString& aId, nsIDOMElement** aReturn) return NS_OK; } +nsresult +XULDocumentImpl::AddSubtreeToDocument(nsIContent* aElement) +{ + // Do a bunch of work that's necessary when an element gets added + // to the XUL Document. + nsresult rv; + + // 1. Add the element to the resource-to-element map + rv = AddElementToMap(aElement); + if (NS_FAILED(rv)) return rv; + + // 2. If the element is a 'command updater' (i.e., has a + // "commandupdater='true'" attribute), then add the element to the + // document's command dispatcher + nsAutoString value; + rv = aElement->GetAttribute(kNameSpaceID_None, kCommandUpdaterAtom, value); + if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && value.Equals("true")) { + nsAutoString events; + rv = aElement->GetAttribute(kNameSpaceID_None, kEventsAtom, events); + + if (rv != NS_CONTENT_ATTR_HAS_VALUE) + events = "*"; + + nsAutoString targets; + rv = aElement->GetAttribute(kNameSpaceID_None, kTargetsAtom, targets); + + if (rv != NS_CONTENT_ATTR_HAS_VALUE) + targets = "*"; + + nsCOMPtr domelement = do_QueryInterface(aElement); + NS_ASSERTION(domelement != nsnull, "not a DOM element"); + if (! domelement) + return NS_ERROR_UNEXPECTED; + + rv = mCommandDispatcher->AddCommandUpdater(domelement, events, targets); + if (NS_FAILED(rv)) return rv; + } + + PRInt32 count; + nsCOMPtr xulcontent = do_QueryInterface(aElement); + rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); + if (NS_FAILED(rv)) return rv; + + while (--count >= 0) { + nsCOMPtr child; + rv = aElement->ChildAt(count, *getter_AddRefs(child)); + if (NS_FAILED(rv)) return rv; + + rv = AddSubtreeToDocument(child); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + +nsresult +XULDocumentImpl::RemoveSubtreeFromDocument(nsIContent* aElement) +{ + // Do a bunch of cleanup to remove an element from the XUL + // document. + nsresult rv; + + PRInt32 count; + nsCOMPtr xulcontent = do_QueryInterface(aElement); + rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); + if (NS_FAILED(rv)) return rv; + + while (--count >= 0) { + nsCOMPtr child; + rv = aElement->ChildAt(count, *getter_AddRefs(child)); + if (NS_FAILED(rv)) return rv; + + rv = RemoveSubtreeFromDocument(child); + if (NS_FAILED(rv)) return rv; + } + + // 1. Remove the element from the resource-to-element map + rv = RemoveElementFromMap(aElement); + if (NS_FAILED(rv)) return rv; + + // 2. If the element is a 'command updater', then remove the + // element from the document's command dispatcher. + nsAutoString value; + rv = aElement->GetAttribute(kNameSpaceID_None, kCommandUpdaterAtom, value); + if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && value.Equals("true")) { + nsCOMPtr domelement = do_QueryInterface(aElement); + NS_ASSERTION(domelement != nsnull, "not a DOM element"); + if (! domelement) + return NS_ERROR_UNEXPECTED; + + rv = mCommandDispatcher->RemoveCommandUpdater(domelement); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + +// Attributes that are used with getElementById() and the +// resource-to-element map. nsIAtom** XULDocumentImpl::kIdentityAttrs[] = { &kIdAtom, &kRefAtom, nsnull }; nsresult -XULDocumentImpl::AddElementToMap(nsIContent* aElement, PRBool aDeep) +XULDocumentImpl::AddElementToMap(nsIContent* aElement) { + // Look at the element's 'id' and 'ref' attributes, and if set, + // add pointers in the resource-to-element map to the element. nsresult rv; PRInt32 nameSpaceID; @@ -3386,29 +3479,14 @@ XULDocumentImpl::AddElementToMap(nsIContent* aElement, PRBool aDeep) } } - if (aDeep) { - PRInt32 count; - nsCOMPtr xulcontent = do_QueryInterface(aElement); - rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); - if (NS_FAILED(rv)) return rv; - - while (--count > 0) { - nsCOMPtr child; - rv = aElement->ChildAt(count, *getter_AddRefs(child)); - if (NS_FAILED(rv)) return rv; - - rv = AddElementToMap(child, PR_TRUE); - if (NS_FAILED(rv)) return rv; - } - } - return NS_OK; } nsresult -XULDocumentImpl::RemoveElementFromMap(nsIContent* aElement, PRBool aDeep) +XULDocumentImpl::RemoveElementFromMap(nsIContent* aElement) { + // Remove the element from the resource-to-element map. nsresult rv; PRInt32 nameSpaceID; @@ -3432,22 +3510,6 @@ XULDocumentImpl::RemoveElementFromMap(nsIContent* aElement, PRBool aDeep) } } - if (aDeep) { - PRInt32 count; - nsCOMPtr xulcontent = do_QueryInterface(aElement); - rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count); - if (NS_FAILED(rv)) return rv; - - while (--count > 0) { - nsCOMPtr child; - rv = aElement->ChildAt(count, *getter_AddRefs(child)); - if (NS_FAILED(rv)) return rv; - - rv = RemoveElementFromMap(child, PR_TRUE); - if (NS_FAILED(rv)) return rv; - } - } - return NS_OK; } @@ -4694,5 +4756,3 @@ XULDocumentImpl::RebuildWidgetItem(nsIContent* aElement) } - -