diff --git a/content/xbl/public/nsIXBLBinding.h b/content/xbl/public/nsIXBLBinding.h index f99b6ba3a40..8ee33913efe 100644 --- a/content/xbl/public/nsIXBLBinding.h +++ b/content/xbl/public/nsIXBLBinding.h @@ -55,6 +55,8 @@ public: NS_IMETHOD GetBindingElement(nsIContent** aResult) = 0; NS_IMETHOD SetBindingElement(nsIContent* aElement) = 0; + NS_IMETHOD GetInsertionPoint(nsIContent** aResult) = 0; + NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement) = 0; NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement) = 0; diff --git a/content/xbl/src/nsXBLBinding.cpp b/content/xbl/src/nsXBLBinding.cpp index cdb18d79d25..e917b6a805f 100644 --- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -114,6 +114,8 @@ class nsXBLBinding: public nsIXBLBinding NS_IMETHOD GetBindingElement(nsIContent** aResult); NS_IMETHOD SetBindingElement(nsIContent* aElement); + NS_IMETHOD GetInsertionPoint(nsIContent** aResult); + NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement); NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement); @@ -139,7 +141,6 @@ public: static nsIAtom* kCapturerAtom; static nsIAtom* kExtendsAtom; static nsIAtom* kChildrenAtom; - static nsIAtom* kHasChildrenAtom; static nsIAtom* kHTMLAtom; static nsIAtom* kValueAtom; @@ -171,8 +172,10 @@ protected: nsCOMPtr mBinding; // Strong. As long as we're around, the binding can't go away. nsCOMPtr mContent; // Strong. Our anonymous content stays around with us. nsCOMPtr mNextBinding; // Strong. The derived binding owns the base class bindings. + nsCOMPtr mChildrenElement; // Strong. One of our anonymous content children. nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it. + nsSupportsHashtable* mAttributeTable; // A table for attribute entries. }; @@ -188,7 +191,6 @@ nsIAtom* nsXBLBinding::kTypeAtom = nsnull; nsIAtom* nsXBLBinding::kCapturerAtom = nsnull; nsIAtom* nsXBLBinding::kExtendsAtom = nsnull; nsIAtom* nsXBLBinding::kChildrenAtom = nsnull; -nsIAtom* nsXBLBinding::kHasChildrenAtom = nsnull; nsIAtom* nsXBLBinding::kValueAtom = nsnull; nsIAtom* nsXBLBinding::kHTMLAtom = nsnull; @@ -260,7 +262,6 @@ nsXBLBinding::nsXBLBinding(void) kCapturerAtom = NS_NewAtom("capturer"); kExtendsAtom = NS_NewAtom("extends"); kChildrenAtom = NS_NewAtom("children"); - kHasChildrenAtom = NS_NewAtom("haschildren"); kHTMLAtom = NS_NewAtom("html"); kValueAtom = NS_NewAtom("value"); @@ -287,7 +288,6 @@ nsXBLBinding::~nsXBLBinding(void) NS_RELEASE(kCapturerAtom); NS_RELEASE(kExtendsAtom); NS_RELEASE(kChildrenAtom); - NS_RELEASE(kHasChildrenAtom); NS_RELEASE(kHTMLAtom); NS_RELEASE(kValueAtom); @@ -370,6 +370,14 @@ nsXBLBinding::SetBindingElement(nsIContent* aElement) return NS_OK; } +NS_IMETHODIMP +nsXBLBinding::GetInsertionPoint(nsIContent** aResult) +{ + *aResult = mChildrenElement; + NS_IF_ADDREF(*aResult); + return NS_OK; +} + NS_IMETHODIMP nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) { @@ -397,40 +405,37 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) // in the excludes list. nsAutoString excludes; content->GetAttribute(kNameSpaceID_None, kExcludesAtom, excludes); - if (excludes != "") { - // Walk the children and ensure that all of them - // are in the excludes array. - for (PRInt32 i = 0; i < childCount; i++) { - nsCOMPtr child; - aBoundElement->ChildAt(i, *getter_AddRefs(child)); - nsCOMPtr tag; - child->GetTag(*getter_AddRefs(tag)); - if (!IsInExcludesList(tag, excludes)) { - buildContent = PR_FALSE; - break; + if (excludes != "*") { + if (!excludes.IsEmpty()) { + // Walk the children and ensure that all of them + // are in the excludes array. + for (PRInt32 i = 0; i < childCount; i++) { + nsCOMPtr child; + aBoundElement->ChildAt(i, *getter_AddRefs(child)); + nsCOMPtr tag; + child->GetTag(*getter_AddRefs(tag)); + if (!IsInExcludesList(tag, excludes)) { + buildContent = PR_FALSE; + break; + } } } + else buildContent = PR_FALSE; } - else buildContent = PR_FALSE; } + nsCOMPtr childrenElement; + if (!buildContent) { - nsAutoString hasChildren; - mBinding->GetAttribute(kNameSpaceID_None, kHasChildrenAtom, hasChildren); - if (hasChildren == "") { - // see if we have a element - nsCOMPtr child; - GetNestedChild(kChildrenAtom, content, getter_AddRefs(child)); - if (child) { - buildContent = PR_TRUE; - mBinding->SetAttribute(kNameSpaceID_None, kHasChildrenAtom, "true", PR_FALSE); - } - } - else + // see if we have a element + GetNestedChild(kChildrenAtom, content, getter_AddRefs(childrenElement)); + if (childrenElement) { buildContent = PR_TRUE; + } } - + if (buildContent) { + // Always check the content element for potential attributes. nsCOMPtr node(do_QueryInterface(content)); nsCOMPtr namedMap; @@ -449,15 +454,15 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) nsAutoString value; nsCOMPtr element(do_QueryInterface(mBoundElement)); element->GetAttribute(name, value); - if (value == "") { + if (value.IsEmpty()) { nsAutoString value2; attr->GetValue(value2); - element->SetAttribute(name, value2); + nsCOMPtr atom = getter_AddRefs(NS_NewAtom(name)); + mBoundElement->SetAttribute(kNameSpaceID_None, atom, value2, PR_FALSE); } } } - - + nsCOMPtr domElement = do_QueryInterface(content); nsCOMPtr clonedNode; @@ -465,6 +470,10 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) nsCOMPtr clonedContent = do_QueryInterface(clonedNode); SetAnonymousContent(clonedContent); + + if (childrenElement) { + GetNestedChild(kChildrenAtom, clonedContent, getter_AddRefs(mChildrenElement)); + } } if (mNextBinding) { @@ -701,7 +710,7 @@ nsXBLBinding::GetNestedChild(nsIAtom* aTag, nsIContent* aContent, nsIContent** a nsCOMPtr tag; child->GetTag(*getter_AddRefs(tag)); if (aTag == tag.get()) { - *aResult = child; + *aResult = aContent; // We return the parent of the correct child. NS_ADDREF(*aResult); return; } diff --git a/content/xbl/src/nsXBLService.cpp b/content/xbl/src/nsXBLService.cpp index 85bcb2a6363..38801f40a3b 100644 --- a/content/xbl/src/nsXBLService.cpp +++ b/content/xbl/src/nsXBLService.cpp @@ -312,9 +312,7 @@ nsXBLService::GetContentList(nsIContent* aContent, nsISupportsArray** aResult, n (*aResult)->AppendElement(anonymousChild); } - nsCOMPtr bindingElement; - binding->GetBindingElement(getter_AddRefs(bindingElement)); - + binding->GetInsertionPoint(aParent); return NS_OK; } diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index a3fad1fd049..31985a5bb33 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -4282,6 +4282,31 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresShell* aPresShell, // after the node has been constructed and initialized create any // anonymous content a node needs. +static void LocateAnonymousFrame(nsIPresContext* aPresContext, + nsIFrame* aParentFrame, + nsIContent* aTargetContent, + nsIFrame** aResult) +{ + // Check ourselves. + *aResult = nsnull; + nsCOMPtr content; + aParentFrame->GetContent(getter_AddRefs(content)); + if (content.get() == aTargetContent) { + *aResult = aParentFrame; + return; + } + + // Check our kids. + nsIFrame* currFrame; + aParentFrame->FirstChild(aPresContext, nsnull, &currFrame); + while (currFrame) { + LocateAnonymousFrame(aPresContext, currFrame, aTargetContent, aResult); + if (*aResult) + return; + currFrame->GetNextSibling(&currFrame); + } +} + nsresult nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, nsIPresContext* aPresContext, @@ -4319,6 +4344,16 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, if (!anonymousItems) return NS_OK; + // See if we have to move our explicit content. + nsFrameItems explicitItems; + if (childElement) { + // First, remove all of the kids from the frame list and put them + // in a new frame list. + explicitItems.childList = aChildItems.childList; + explicitItems.lastChild = aChildItems.lastChild; + aChildItems.childList = aChildItems.lastChild = nsnull; + } + // Build the frames for the anonymous content. PRUint32 count = 0; anonymousItems->Count(&count); @@ -4335,6 +4370,38 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, ConstructFrame(aPresShell, aPresContext, aState, content, aNewFrame, aChildItems); } + if (childElement) { + // Now append the explicit frames + // All our explicit content that we built must be reparented. + nsIFrame* frame = nsnull; + nsIFrame* currFrame = aChildItems.childList; + while (currFrame) { + LocateAnonymousFrame(aPresContext, + currFrame, + childElement, + &frame); + if (frame) + break; + currFrame->GetNextSibling(&currFrame); + } + + nsCOMPtr frameManager; + aPresShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager && frame && explicitItems.childList) { + frameManager->AppendFrames(aPresContext, *aPresShell, frame, + nsnull, explicitItems.childList); + } + + /* XXX comes online soon. + if (frame) { + // XXX Eventually generalize to HTML as well. For now, + // leave this on nsIBox. + nsCOMPtr box(do_QueryInterface(aNewFrame)); + box->SetInsertionPoint(frame); + }*/ + } + return NS_OK; } diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index a3fad1fd049..31985a5bb33 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -4282,6 +4282,31 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresShell* aPresShell, // after the node has been constructed and initialized create any // anonymous content a node needs. +static void LocateAnonymousFrame(nsIPresContext* aPresContext, + nsIFrame* aParentFrame, + nsIContent* aTargetContent, + nsIFrame** aResult) +{ + // Check ourselves. + *aResult = nsnull; + nsCOMPtr content; + aParentFrame->GetContent(getter_AddRefs(content)); + if (content.get() == aTargetContent) { + *aResult = aParentFrame; + return; + } + + // Check our kids. + nsIFrame* currFrame; + aParentFrame->FirstChild(aPresContext, nsnull, &currFrame); + while (currFrame) { + LocateAnonymousFrame(aPresContext, currFrame, aTargetContent, aResult); + if (*aResult) + return; + currFrame->GetNextSibling(&currFrame); + } +} + nsresult nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, nsIPresContext* aPresContext, @@ -4319,6 +4344,16 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, if (!anonymousItems) return NS_OK; + // See if we have to move our explicit content. + nsFrameItems explicitItems; + if (childElement) { + // First, remove all of the kids from the frame list and put them + // in a new frame list. + explicitItems.childList = aChildItems.childList; + explicitItems.lastChild = aChildItems.lastChild; + aChildItems.childList = aChildItems.lastChild = nsnull; + } + // Build the frames for the anonymous content. PRUint32 count = 0; anonymousItems->Count(&count); @@ -4335,6 +4370,38 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, ConstructFrame(aPresShell, aPresContext, aState, content, aNewFrame, aChildItems); } + if (childElement) { + // Now append the explicit frames + // All our explicit content that we built must be reparented. + nsIFrame* frame = nsnull; + nsIFrame* currFrame = aChildItems.childList; + while (currFrame) { + LocateAnonymousFrame(aPresContext, + currFrame, + childElement, + &frame); + if (frame) + break; + currFrame->GetNextSibling(&currFrame); + } + + nsCOMPtr frameManager; + aPresShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager && frame && explicitItems.childList) { + frameManager->AppendFrames(aPresContext, *aPresShell, frame, + nsnull, explicitItems.childList); + } + + /* XXX comes online soon. + if (frame) { + // XXX Eventually generalize to HTML as well. For now, + // leave this on nsIBox. + nsCOMPtr box(do_QueryInterface(aNewFrame)); + box->SetInsertionPoint(frame); + }*/ + } + return NS_OK; } diff --git a/layout/xbl/public/nsIXBLBinding.h b/layout/xbl/public/nsIXBLBinding.h index f99b6ba3a40..8ee33913efe 100644 --- a/layout/xbl/public/nsIXBLBinding.h +++ b/layout/xbl/public/nsIXBLBinding.h @@ -55,6 +55,8 @@ public: NS_IMETHOD GetBindingElement(nsIContent** aResult) = 0; NS_IMETHOD SetBindingElement(nsIContent* aElement) = 0; + NS_IMETHOD GetInsertionPoint(nsIContent** aResult) = 0; + NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement) = 0; NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement) = 0; diff --git a/layout/xbl/src/nsXBLBinding.cpp b/layout/xbl/src/nsXBLBinding.cpp index cdb18d79d25..e917b6a805f 100644 --- a/layout/xbl/src/nsXBLBinding.cpp +++ b/layout/xbl/src/nsXBLBinding.cpp @@ -114,6 +114,8 @@ class nsXBLBinding: public nsIXBLBinding NS_IMETHOD GetBindingElement(nsIContent** aResult); NS_IMETHOD SetBindingElement(nsIContent* aElement); + NS_IMETHOD GetInsertionPoint(nsIContent** aResult); + NS_IMETHOD GenerateAnonymousContent(nsIContent* aBoundElement); NS_IMETHOD InstallEventHandlers(nsIContent* aBoundElement); @@ -139,7 +141,6 @@ public: static nsIAtom* kCapturerAtom; static nsIAtom* kExtendsAtom; static nsIAtom* kChildrenAtom; - static nsIAtom* kHasChildrenAtom; static nsIAtom* kHTMLAtom; static nsIAtom* kValueAtom; @@ -171,8 +172,10 @@ protected: nsCOMPtr mBinding; // Strong. As long as we're around, the binding can't go away. nsCOMPtr mContent; // Strong. Our anonymous content stays around with us. nsCOMPtr mNextBinding; // Strong. The derived binding owns the base class bindings. + nsCOMPtr mChildrenElement; // Strong. One of our anonymous content children. nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it. + nsSupportsHashtable* mAttributeTable; // A table for attribute entries. }; @@ -188,7 +191,6 @@ nsIAtom* nsXBLBinding::kTypeAtom = nsnull; nsIAtom* nsXBLBinding::kCapturerAtom = nsnull; nsIAtom* nsXBLBinding::kExtendsAtom = nsnull; nsIAtom* nsXBLBinding::kChildrenAtom = nsnull; -nsIAtom* nsXBLBinding::kHasChildrenAtom = nsnull; nsIAtom* nsXBLBinding::kValueAtom = nsnull; nsIAtom* nsXBLBinding::kHTMLAtom = nsnull; @@ -260,7 +262,6 @@ nsXBLBinding::nsXBLBinding(void) kCapturerAtom = NS_NewAtom("capturer"); kExtendsAtom = NS_NewAtom("extends"); kChildrenAtom = NS_NewAtom("children"); - kHasChildrenAtom = NS_NewAtom("haschildren"); kHTMLAtom = NS_NewAtom("html"); kValueAtom = NS_NewAtom("value"); @@ -287,7 +288,6 @@ nsXBLBinding::~nsXBLBinding(void) NS_RELEASE(kCapturerAtom); NS_RELEASE(kExtendsAtom); NS_RELEASE(kChildrenAtom); - NS_RELEASE(kHasChildrenAtom); NS_RELEASE(kHTMLAtom); NS_RELEASE(kValueAtom); @@ -370,6 +370,14 @@ nsXBLBinding::SetBindingElement(nsIContent* aElement) return NS_OK; } +NS_IMETHODIMP +nsXBLBinding::GetInsertionPoint(nsIContent** aResult) +{ + *aResult = mChildrenElement; + NS_IF_ADDREF(*aResult); + return NS_OK; +} + NS_IMETHODIMP nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) { @@ -397,40 +405,37 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) // in the excludes list. nsAutoString excludes; content->GetAttribute(kNameSpaceID_None, kExcludesAtom, excludes); - if (excludes != "") { - // Walk the children and ensure that all of them - // are in the excludes array. - for (PRInt32 i = 0; i < childCount; i++) { - nsCOMPtr child; - aBoundElement->ChildAt(i, *getter_AddRefs(child)); - nsCOMPtr tag; - child->GetTag(*getter_AddRefs(tag)); - if (!IsInExcludesList(tag, excludes)) { - buildContent = PR_FALSE; - break; + if (excludes != "*") { + if (!excludes.IsEmpty()) { + // Walk the children and ensure that all of them + // are in the excludes array. + for (PRInt32 i = 0; i < childCount; i++) { + nsCOMPtr child; + aBoundElement->ChildAt(i, *getter_AddRefs(child)); + nsCOMPtr tag; + child->GetTag(*getter_AddRefs(tag)); + if (!IsInExcludesList(tag, excludes)) { + buildContent = PR_FALSE; + break; + } } } + else buildContent = PR_FALSE; } - else buildContent = PR_FALSE; } + nsCOMPtr childrenElement; + if (!buildContent) { - nsAutoString hasChildren; - mBinding->GetAttribute(kNameSpaceID_None, kHasChildrenAtom, hasChildren); - if (hasChildren == "") { - // see if we have a element - nsCOMPtr child; - GetNestedChild(kChildrenAtom, content, getter_AddRefs(child)); - if (child) { - buildContent = PR_TRUE; - mBinding->SetAttribute(kNameSpaceID_None, kHasChildrenAtom, "true", PR_FALSE); - } - } - else + // see if we have a element + GetNestedChild(kChildrenAtom, content, getter_AddRefs(childrenElement)); + if (childrenElement) { buildContent = PR_TRUE; + } } - + if (buildContent) { + // Always check the content element for potential attributes. nsCOMPtr node(do_QueryInterface(content)); nsCOMPtr namedMap; @@ -449,15 +454,15 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) nsAutoString value; nsCOMPtr element(do_QueryInterface(mBoundElement)); element->GetAttribute(name, value); - if (value == "") { + if (value.IsEmpty()) { nsAutoString value2; attr->GetValue(value2); - element->SetAttribute(name, value2); + nsCOMPtr atom = getter_AddRefs(NS_NewAtom(name)); + mBoundElement->SetAttribute(kNameSpaceID_None, atom, value2, PR_FALSE); } } } - - + nsCOMPtr domElement = do_QueryInterface(content); nsCOMPtr clonedNode; @@ -465,6 +470,10 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement) nsCOMPtr clonedContent = do_QueryInterface(clonedNode); SetAnonymousContent(clonedContent); + + if (childrenElement) { + GetNestedChild(kChildrenAtom, clonedContent, getter_AddRefs(mChildrenElement)); + } } if (mNextBinding) { @@ -701,7 +710,7 @@ nsXBLBinding::GetNestedChild(nsIAtom* aTag, nsIContent* aContent, nsIContent** a nsCOMPtr tag; child->GetTag(*getter_AddRefs(tag)); if (aTag == tag.get()) { - *aResult = child; + *aResult = aContent; // We return the parent of the correct child. NS_ADDREF(*aResult); return; } diff --git a/layout/xbl/src/nsXBLService.cpp b/layout/xbl/src/nsXBLService.cpp index 85bcb2a6363..38801f40a3b 100644 --- a/layout/xbl/src/nsXBLService.cpp +++ b/layout/xbl/src/nsXBLService.cpp @@ -312,9 +312,7 @@ nsXBLService::GetContentList(nsIContent* aContent, nsISupportsArray** aResult, n (*aResult)->AppendElement(anonymousChild); } - nsCOMPtr bindingElement; - binding->GetBindingElement(getter_AddRefs(bindingElement)); - + binding->GetInsertionPoint(aParent); return NS_OK; }