diff --git a/content/xbl/public/nsIBindingManager.h b/content/xbl/public/nsIBindingManager.h index 9246b92d83ac..e751984e8bf4 100644 --- a/content/xbl/public/nsIBindingManager.h +++ b/content/xbl/public/nsIBindingManager.h @@ -89,9 +89,6 @@ public: NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0; NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList) = 0; - // Encapsulates logic for handling both of above - NS_IMETHOD GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0; - NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex) = 0; NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints) = 0; diff --git a/content/xbl/src/nsBindingManager.cpp b/content/xbl/src/nsBindingManager.cpp index 26eb85794718..c55a47e3f0b6 100644 --- a/content/xbl/src/nsBindingManager.cpp +++ b/content/xbl/src/nsBindingManager.cpp @@ -348,8 +348,6 @@ public: NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult); NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList); - NS_IMETHOD GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult); - NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex); NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints); @@ -782,28 +780,6 @@ nsBindingManager::SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* a return NS_OK; } -NS_IMETHODIMP -nsBindingManager::GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) -{ - PRUint32 length; - - // Retrieve the anonymous content that we should build. - GetAnonymousNodesFor(aContent, aResult); - if (*aResult) { - (*aResult)->GetLength(&length); - if (length == 0) - *aResult = nsnull; - } - - // We may have an altered list of children from XBL insertion points. - // If we don't have any anonymous kids, we next check to see if we have - // insertion points. - if (! *aResult) - GetContentListFor(aContent, aResult); - - return NS_OK; -} - NS_IMETHODIMP nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex) { diff --git a/content/xbl/src/nsXBLBinding.cpp b/content/xbl/src/nsXBLBinding.cpp index b9ec6b7b612d..1b5dd2a88867 100644 --- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -41,7 +41,6 @@ #include "nsIDocument.h" #include "nsIXMLContent.h" #include "nsIXULContent.h" -#include "nsIXULDocument.h" #include "nsIXMLContentSink.h" #include "nsLayoutCID.h" #include "nsXMLDocument.h" @@ -362,9 +361,7 @@ nsXBLBinding::SetAnonymousContent(nsIContent* aParent) mBoundElement->GetDocument(*getter_AddRefs(doc)); mContent->SetDocument(doc, PR_TRUE, AllowScripts()); - - nsCOMPtr xuldoc(do_QueryInterface(doc)); - + // (2) The children's parent back pointer should not be to this synthetic root // but should instead point to the bound element. PRInt32 childCount; @@ -374,12 +371,6 @@ nsXBLBinding::SetAnonymousContent(nsIContent* aParent) mContent->ChildAt(i, *getter_AddRefs(child)); child->SetParent(mBoundElement); child->SetBindingParent(mBoundElement); - - // To make XUL templates work (and other goodies that happen when - // an element is added to a XUL document), we need to notify the - // XUL document using its special API. - if (xuldoc) - xuldoc->AddSubtreeToDocument(child); } return NS_OK; @@ -1298,25 +1289,9 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen nsCOMPtr anonymous; GetAnonymousContent(getter_AddRefs(anonymous)); if (anonymous) { - // To make XUL templates work (and other XUL-specific stuff), - // we'll need to notify it using its add & remove APIs. Grab the - // interface now... - nsCOMPtr xuldoc(do_QueryInterface(aOldDocument)); - - if (mIsStyleBinding) { + if (mIsStyleBinding) anonymous->SetDocument(nsnull, PR_TRUE, PR_TRUE); // Kill it. - if (xuldoc) - xuldoc->RemoveSubtreeFromDocument(anonymous); - } - else { - anonymous->SetDocument(aNewDocument, PR_TRUE, AllowScripts()); // Keep it around. - if (xuldoc) - xuldoc->RemoveSubtreeFromDocument(anonymous); - - xuldoc = do_QueryInterface(aNewDocument); - if (xuldoc) - xuldoc->AddSubtreeToDocument(anonymous); - } + else anonymous->SetDocument(aNewDocument, PR_TRUE, AllowScripts()); // Keep it around. } } diff --git a/content/xul/document/public/nsIXULDocument.h b/content/xul/document/public/nsIXULDocument.h index b79ce89aa3e9..6e8b12beb77e 100644 --- a/content/xul/document/public/nsIXULDocument.h +++ b/content/xul/document/public/nsIXULDocument.h @@ -126,16 +126,6 @@ public: * Load inline and attribute style sheets */ NS_IMETHOD PrepareStyleSheets(nsIURI* aURI) = 0; - - /** - * Notify the XUL document that a subtree has been added - */ - NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement) = 0; - - /** - * Notify the XUL document that a subtree has been removed - */ - NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement) = 0; }; // factory functions diff --git a/content/xul/document/src/nsXULContentSink.cpp b/content/xul/document/src/nsXULContentSink.cpp index 5c01d0e6e7c2..0ec24ee0da50 100644 --- a/content/xul/document/src/nsXULContentSink.cpp +++ b/content/xul/document/src/nsXULContentSink.cpp @@ -228,6 +228,8 @@ protected: nsresult GetTopNode(nsXULPrototypeNode** aNode); nsresult GetTopChildren(nsVoidArray** aChildren); + + PRBool IsInsideXULTemplate(); }; friend class ContextStack; @@ -328,6 +330,31 @@ XULContentSinkImpl::ContextStack::GetTopChildren(nsVoidArray** aChildren) } +PRBool +XULContentSinkImpl::ContextStack::IsInsideXULTemplate() +{ + if (mDepth) { + Entry* entry = mTop; + while (entry) { + nsXULPrototypeNode* node = entry->mNode; + + if (node->mType == nsXULPrototypeNode::eType_Element) { + nsXULPrototypeElement* element = + NS_REINTERPRET_CAST(nsXULPrototypeElement*, node); + + if (element->mNodeInfo->Equals(kTemplateAtom, + kNameSpaceID_XUL)) { + return PR_TRUE; + } + } + + entry = entry->mNext; + } + } + return PR_FALSE; +} + + //---------------------------------------------------------------------- @@ -1197,16 +1224,50 @@ XULContentSinkImpl::AddAttributes(const nsIParserNode& aNode, nsXULPrototypeElem nsresult rv; PRInt32 count = aNode.GetAttributeCount(); + PRBool generateIDAttr = PR_FALSE; + if (mContextStack.IsInsideXULTemplate()) { + // Check for an 'id' attribute. If we're inside a XUL + // template, then _everything_ needs to have an ID for the + // 'template' attribute hookup. + generateIDAttr = PR_TRUE; + + for (PRInt32 i = 0; i < count; i++) { + if (aNode.GetKeyAt(i).Equals(NS_LITERAL_STRING("id"))) { + generateIDAttr = PR_FALSE; + break; + } + } + } + // Create storage for the attributes + PRInt32 numattrs = count; + if (generateIDAttr) + ++numattrs; + nsXULPrototypeAttribute* attrs = nsnull; - if (count > 0) { - attrs = new nsXULPrototypeAttribute[count]; + if (numattrs > 0) { + attrs = new nsXULPrototypeAttribute[numattrs]; if (! attrs) return NS_ERROR_OUT_OF_MEMORY; } aElement->mAttributes = attrs; - aElement->mNumAttributes = count; + aElement->mNumAttributes = numattrs; + + if (generateIDAttr) { + // Deal with generating an ID attribute for stuff inside a XUL + // template + nsAutoString id; id.AssignWithConversion("$"); + id.AppendInt(PRInt32(aElement), 16); + + mNodeInfoManager->GetNodeInfo(kIdAtom, nsnull, kNameSpaceID_None, + *getter_AddRefs(attrs->mNodeInfo)); + NS_ENSURE_TRUE(attrs->mNodeInfo, NS_ERROR_FAILURE); + + attrs->mValue.SetValue( id ); + + ++attrs; + } // Copy the attributes into the prototype for (PRInt32 i = 0; i < count; i++) { diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 3b0868f6f9e9..17c60632f230 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -3141,7 +3141,7 @@ nsXULDocument::GetElementsByTagNameNS(const nsAReadableString& aNamespaceURI, return NS_OK; } -NS_IMETHODIMP +nsresult nsXULDocument::AddSubtreeToDocument(nsIContent* aElement) { // Do a bunch of work that's necessary when an element gets added @@ -3194,13 +3194,10 @@ nsXULDocument::AddSubtreeToDocument(nsIContent* aElement) if (NS_FAILED(rv)) return rv; } - // 5. See if we need to attach a XUL template to this node - CheckTemplateBuilder(aElement); - return NS_OK; } -NS_IMETHODIMP +nsresult nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement) { // Do a bunch of cleanup to remove an element from the XUL @@ -5048,12 +5045,26 @@ nsXULDocument::ResumeWalk() if (NS_FAILED(rv)) return rv; if (indx >= proto->mNumChildren) { - // We've processed all of the prototype's children. If - // we're in the master prototype, do document-level - // hookup. (An overlay will get its document hookup - // done when it's successfully resolved.) - if (element && (mState == eState_Master)) - AddSubtreeToDocument(element); + if (element && ((mState == eState_Master) || (mContextStack.Depth() > 2))) { + // We've processed all of the prototype's children. + // Check the element for a 'datasources' attribute, in + // which case we'll need to create a template builder + // and construct the first 'ply' of elements beneath + // it. + // + // N.B. that we do this -after- all other XUL children + // have been created: this ensures that there'll be a + //