mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Fix for 55292, r=ben, sr=brendan
This commit is contained in:
parent
32417b285f
commit
45c08e6635
@ -545,57 +545,6 @@ nsDocumentChildNodes::DropReference()
|
||||
// =
|
||||
// ==================================================================
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsAnonymousContentList)
|
||||
|
||||
nsAnonymousContentList::nsAnonymousContentList(nsISupportsArray* aElements)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAnonymousContentList);
|
||||
|
||||
// We don't reference count our Anonymous reference (to avoid circular
|
||||
// references). We'll be told when the Anonymous goes away.
|
||||
mElements = aElements;
|
||||
NS_IF_ADDREF(mElements);
|
||||
}
|
||||
|
||||
nsAnonymousContentList::~nsAnonymousContentList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsAnonymousContentList);
|
||||
NS_IF_RELEASE(mElements);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::GetLength(PRUint32* aLength)
|
||||
{
|
||||
NS_ASSERTION(aLength != nsnull, "null ptr");
|
||||
if (! aLength)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mElements->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
*aLength = cnt;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
||||
{
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mElements->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aIndex >= (PRUint32) cnt)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// Cast is okay because we're in a closed system.
|
||||
*aReturn = (nsIDOMNode*) mElements->ElementAt(aIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// =
|
||||
// ==================================================================
|
||||
|
||||
nsDocument::nsDocument()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
@ -2211,17 +2160,12 @@ NS_IMETHODIMP
|
||||
nsDocument::GetAnonymousNodes(nsIDOMElement* aElement,
|
||||
nsIDOMNodeList** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Use the XBL service to get the anonymous node list.
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
PRBool dummy;
|
||||
nsCOMPtr<nsIContent> dummyElt;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return xblService->GetContentList(content, aResult, getter_AddRefs(dummyElt), &dummy);
|
||||
*aResult = nsnull;
|
||||
if (mBindingManager) {
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return mBindingManager->GetAnonymousNodesFor(content, aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -115,19 +115,6 @@ protected:
|
||||
nsIDocument* mDocument;
|
||||
};
|
||||
|
||||
class nsAnonymousContentList : public nsGenericDOMNodeList
|
||||
{
|
||||
public:
|
||||
nsAnonymousContentList(nsISupportsArray* aElements);
|
||||
virtual ~nsAnonymousContentList();
|
||||
|
||||
// nsIDOMNodeList interface
|
||||
NS_DECL_IDOMNODELIST
|
||||
|
||||
private:
|
||||
nsISupportsArray* mElements;
|
||||
};
|
||||
|
||||
// Base class for our document implementations
|
||||
class nsDocument : public nsIDocument,
|
||||
public nsIDOMDocument,
|
||||
|
@ -33,6 +33,7 @@ EXPORTS = \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLBindingAttachedHandler.h \
|
||||
nsIXBLDocumentInfo.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLPrototypeBinding.h \
|
||||
nsIXBLPrototypeHandler.h \
|
||||
nsIXBLService.h \
|
||||
|
@ -2,6 +2,7 @@ nsIBindingManager.h
|
||||
nsIXBLBinding.h
|
||||
nsIXBLBindingAttachedHandler.h
|
||||
nsIXBLDocumentInfo.h
|
||||
nsIXBLInsertionPoint.h
|
||||
nsIXBLPrototypeBinding.h
|
||||
nsIXBLPrototypeHandler.h
|
||||
nsIXBLService.h
|
||||
|
@ -26,6 +26,7 @@ EXPORTS = \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLBindingAttachedHandler.h \
|
||||
nsIXBLDocumentInfo.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLPrototypeBinding.h \
|
||||
nsIXBLPrototypeHandler.h \
|
||||
nsIXBLService.h \
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult) = 0;
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionParent(nsIContent* aContent, nsIContent** aResult)=0;
|
||||
NS_IMETHOD SetInsertionParent(nsIContent* aContent, nsIContent* aResult)=0;
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult) = 0;
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult) = 0;
|
||||
|
||||
@ -79,8 +82,15 @@ public:
|
||||
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult,
|
||||
// For a given element with an insertion point child, returns a flat list of all the real children.
|
||||
NS_IMETHOD GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
NS_IMETHOD SetContentListFor(nsIContent* aContent, nsISupportsArray* aList)=0;
|
||||
|
||||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList) = 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;
|
||||
|
||||
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsAReadableString& aURL) = 0;
|
||||
|
@ -85,8 +85,10 @@ public:
|
||||
NS_IMETHOD GetDocURI(nsCString& aResult) = 0;
|
||||
NS_IMETHOD GetID(nsCString& aResult) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRBool* aMultipleInsertionPoints) = 0;
|
||||
NS_IMETHOD GetInsertionPointsFor(nsIContent* aParent, nsISupportsArray** aResult)=0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints) = 0;
|
||||
|
||||
NS_IMETHOD IsStyleBinding(PRBool* aResult) = 0;
|
||||
NS_IMETHOD SetIsStyleBinding(PRBool aIsStyle) = 0;
|
||||
@ -102,8 +104,7 @@ public:
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult,
|
||||
nsIContent** aParent, PRBool* aMultipleInsertionPoints)=0;
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult)=0;
|
||||
};
|
||||
|
@ -32,6 +32,7 @@ class nsIDocument;
|
||||
class nsIDOMEventReceiver;
|
||||
class nsIXBLDocumentInfo;
|
||||
class nsIXBLPrototypeHandler;
|
||||
class nsIXBLBinding;
|
||||
|
||||
// {34D700F5-C1A2-4408-A0B1-DD8F891DD1FE}
|
||||
#define NS_IXBLPROTOTYPEBINDING_IID \
|
||||
@ -76,11 +77,13 @@ public:
|
||||
|
||||
NS_IMETHOD HasInsertionPoints(PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD InstantiateInsertionPoints(nsIXBLBinding* aBinding)=0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent* aChild, nsIContent** aResult)=0;
|
||||
nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)=0;
|
||||
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent** aResult, PRBool* aMultipleInsertionPoints)=0;
|
||||
nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints)=0;
|
||||
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag)=0;
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag)=0;
|
||||
|
@ -64,11 +64,6 @@ public:
|
||||
// Indicates whether or not a binding is fully loaded.
|
||||
NS_IMETHOD BindingReady(nsIContent* aBoundElement, const nsCString& aURLStr, PRBool* aIsReady) = 0;
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsIDOMNodeList** aResult, nsIContent** aChildElement,
|
||||
PRBool* aMultipleInsertionPoints) = 0;
|
||||
|
||||
// Retrieves our base class (e.g., tells us what type of frame and content node to build)
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult) = 0;
|
||||
|
||||
|
@ -50,6 +50,7 @@ CPPSRCS = \
|
||||
nsXBLScrollHandler.cpp \
|
||||
nsXBLService.cpp \
|
||||
nsBindingManager.cpp \
|
||||
nsXBLInsertionPoint \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
@ -46,6 +46,7 @@ CPPSRCS= \
|
||||
nsXBLLoadHandler.cpp \
|
||||
nsXBLPrototypeHandler.cpp \
|
||||
nsBindingManager.cpp \
|
||||
nsXBLInsertionPoint.cpp \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS= \
|
||||
@ -68,6 +69,7 @@ CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsXBLPrototypeHandler.obj \
|
||||
.\$(OBJDIR)\nsXBLService.obj \
|
||||
.\$(OBJDIR)\nsBindingManager.obj \
|
||||
.\$(OBJDIR)\nsXBLInsertionPoint.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsIXBLBinding.h"
|
||||
#include "nsIXBLDocumentInfo.h"
|
||||
#include "nsIXBLBindingAttachedHandler.h"
|
||||
#include "nsIXBLInsertionPoint.h"
|
||||
|
||||
#include "nsIStyleSheet.h"
|
||||
#include "nsIHTMLStyleSheet.h"
|
||||
@ -191,6 +192,89 @@ nsresult NS_NewXBLDocumentInfo(nsIDocument* aDocument, nsIXBLDocumentInfo** aRes
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// = nsAnonymousContentList
|
||||
// ==================================================================
|
||||
|
||||
class nsAnonymousContentList : public nsGenericDOMNodeList
|
||||
{
|
||||
public:
|
||||
nsAnonymousContentList(nsISupportsArray* aElements);
|
||||
virtual ~nsAnonymousContentList();
|
||||
|
||||
// nsIDOMNodeList interface
|
||||
NS_DECL_IDOMNODELIST
|
||||
|
||||
private:
|
||||
nsISupportsArray* mElements;
|
||||
};
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsAnonymousContentList);
|
||||
|
||||
nsAnonymousContentList::nsAnonymousContentList(nsISupportsArray* aElements)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAnonymousContentList);
|
||||
|
||||
// We don't reference count our Anonymous reference (to avoid circular
|
||||
// references). We'll be told when the Anonymous goes away.
|
||||
mElements = aElements;
|
||||
NS_IF_ADDREF(mElements);
|
||||
}
|
||||
|
||||
nsAnonymousContentList::~nsAnonymousContentList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsAnonymousContentList);
|
||||
NS_IF_RELEASE(mElements);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::GetLength(PRUint32* aLength)
|
||||
{
|
||||
NS_ASSERTION(aLength != nsnull, "null ptr");
|
||||
if (! aLength)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRUint32 cnt;
|
||||
mElements->Count(&cnt);
|
||||
|
||||
*aLength = 0;
|
||||
nsCOMPtr<nsIXBLInsertionPoint> point;
|
||||
PRUint32 l;
|
||||
for (PRUint32 i = 0; i < cnt; i++) {
|
||||
point = getter_AddRefs((nsIXBLInsertionPoint*)(mElements->ElementAt(i)));
|
||||
point->ChildCount(&l);
|
||||
*aLength += l;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
||||
{
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mElements->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 pointCount = 0;
|
||||
nsCOMPtr<nsIXBLInsertionPoint> point;
|
||||
for (PRUint32 i = 0; i < cnt; i++) {
|
||||
aIndex -= pointCount;
|
||||
|
||||
point = getter_AddRefs((nsIXBLInsertionPoint*)(mElements->ElementAt(i)));
|
||||
point->ChildCount(&pointCount);
|
||||
|
||||
if (aIndex < pointCount) {
|
||||
nsCOMPtr<nsIContent> result;
|
||||
rv = point->ChildAt(aIndex, getter_AddRefs(result));
|
||||
if (result && NS_SUCCEEDED(rv))
|
||||
return result->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)aReturn);
|
||||
else return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -205,6 +289,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult);
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding);
|
||||
|
||||
NS_IMETHOD GetInsertionParent(nsIContent* aContent, nsIContent** aResult);
|
||||
NS_IMETHOD SetInsertionParent(nsIContent* aContent, nsIContent* aResult);
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult);
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult);
|
||||
|
||||
@ -213,8 +300,14 @@ public:
|
||||
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult,
|
||||
NS_IMETHOD GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
NS_IMETHOD SetContentListFor(nsIContent* aContent, nsISupportsArray* aList);
|
||||
|
||||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints);
|
||||
|
||||
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsAReadableString& aURL);
|
||||
@ -258,11 +351,43 @@ protected:
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
// A mapping from nsIContent* to the nsIXBLBinding* that is installed on that element.
|
||||
nsSupportsHashtable* mBindingTable;
|
||||
|
||||
// A mapping from nsIContent* to an nsIDOMNodeList* (nsAnonymousContentList*).
|
||||
// This list contains an accurate reflection of our *explicit* children (once intermingled with
|
||||
// insertion points) in the altered DOM.
|
||||
nsSupportsHashtable* mContentListTable;
|
||||
|
||||
// A mapping from nsIContent* to an nsIDOMNodeList* (nsAnonymousContentList*).
|
||||
// This list contains an accurate reflection of our *anonymous* children (if and only if they are
|
||||
// intermingled with insertion points) in the altered DOM. This table is not used
|
||||
// if no insertion points were defined directly underneath a <content> tag in a
|
||||
// binding. The NodeList from the <content> is used instead as a performance
|
||||
// optimization.
|
||||
nsSupportsHashtable* mAnonymousNodesTable;
|
||||
|
||||
// A mapping from nsIContent* to nsIContent*. The insertion parent is our one true
|
||||
// parent in the transformed DOM. This gives us a more-or-less O(1) way of obtaining
|
||||
// our transformed parent.
|
||||
nsSupportsHashtable* mInsertionParentTable;
|
||||
|
||||
// A mapping from nsIContent* to nsIXPWrappedJS* (an XPConnect wrapper for JS objects).
|
||||
// For XBL bindings that implement XPIDL interfaces, and that get referred to from C++,
|
||||
// this table caches the XPConnect wrapper for the binding. By caching it, I control
|
||||
// its lifetime, and I prevent a re-wrap of the same script object (in the case where
|
||||
// multiple bindings in an XBL inheritance chain both implement an XPIDL interface).
|
||||
nsSupportsHashtable* mWrapperTable;
|
||||
|
||||
// A mapping from nsIDocument* to nsIXBLDocumentInfo*. This table is the cache of
|
||||
// all binding documents that have been loaded by a given bound document.
|
||||
nsSupportsHashtable* mDocumentTable;
|
||||
|
||||
// The currently loading binding docs. If they're in this table, they have not yet
|
||||
// finished loading.
|
||||
nsSupportsHashtable* mLoadingDocTable;
|
||||
|
||||
// A queue of binding attached event handlers that are awaiting execution.
|
||||
nsCOMPtr<nsISupportsArray> mAttachedQueue;
|
||||
};
|
||||
|
||||
@ -279,6 +404,9 @@ nsBindingManager::nsBindingManager(void)
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mBindingTable = nsnull;
|
||||
mContentListTable = nsnull;
|
||||
mAnonymousNodesTable = nsnull;
|
||||
mInsertionParentTable = nsnull;
|
||||
mWrapperTable = nsnull;
|
||||
mDocumentTable = nsnull;
|
||||
mLoadingDocTable = nsnull;
|
||||
@ -289,6 +417,9 @@ nsBindingManager::nsBindingManager(void)
|
||||
nsBindingManager::~nsBindingManager(void)
|
||||
{
|
||||
delete mBindingTable;
|
||||
delete mContentListTable;
|
||||
delete mAnonymousNodesTable;
|
||||
delete mInsertionParentTable;
|
||||
delete mWrapperTable;
|
||||
delete mDocumentTable;
|
||||
delete mLoadingDocTable;
|
||||
@ -333,6 +464,36 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionParent(nsIContent* aContent, nsIContent** aResult)
|
||||
{
|
||||
if (mInsertionParentTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIContent*, mInsertionParentTable->Get(&key));
|
||||
}
|
||||
else {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetInsertionParent(nsIContent* aContent, nsIContent* aParent)
|
||||
{
|
||||
if (!mInsertionParentTable)
|
||||
mInsertionParentTable = new nsSupportsHashtable;
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aParent) {
|
||||
mInsertionParentTable->Put(&key, aParent);
|
||||
}
|
||||
else
|
||||
mInsertionParentTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult)
|
||||
{
|
||||
@ -383,6 +544,11 @@ nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocum
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out insertion parents and content lists.
|
||||
SetInsertionParent(aContent, nsnull);
|
||||
SetContentListFor(aContent, nsnull);
|
||||
SetAnonymousNodesFor(aContent, nsnull);
|
||||
|
||||
for (PRInt32 i = aOldDocument->GetNumberOfShells() - 1; i >= 0; --i) {
|
||||
nsCOMPtr<nsIPresShell> shell = dont_AddRef( aOldDocument->GetShellAt(i) );
|
||||
NS_ASSERTION(shell != nsnull, "Zoiks! nsIPresShell::ShellAt() broke");
|
||||
@ -434,26 +600,105 @@ nsBindingManager::ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAto
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult)
|
||||
nsBindingManager::GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult)
|
||||
{
|
||||
// Locate the primary binding and get its node list of anonymous children.
|
||||
*aResult = nsnull;
|
||||
|
||||
if (mContentListTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIDOMNodeList*, mContentListTable->Get(&key));
|
||||
}
|
||||
|
||||
if (!*aResult) {
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
|
||||
return node->GetChildNodes(aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetContentListFor(nsIContent* aContent, nsISupportsArray* aList)
|
||||
{
|
||||
if (!mContentListTable) {
|
||||
if (!aList)
|
||||
return NS_OK;
|
||||
mContentListTable = new nsSupportsHashtable;
|
||||
}
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aList) {
|
||||
nsAnonymousContentList* contentList = new nsAnonymousContentList(aList);
|
||||
mContentListTable->Put(&key, (nsIDOMNodeList*)contentList);
|
||||
}
|
||||
else
|
||||
mContentListTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult)
|
||||
{
|
||||
// Locate the primary binding and get its node list of anonymous children.
|
||||
*aResult = nsnull;
|
||||
if (mAnonymousNodesTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIDOMNodeList*, mAnonymousNodesTable->Get(&key));
|
||||
}
|
||||
|
||||
if (!*aResult) {
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aContent, getter_AddRefs(binding));
|
||||
if (binding)
|
||||
return binding->GetAnonymousNodes(aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList)
|
||||
{
|
||||
if (!mAnonymousNodesTable) {
|
||||
if (!aList)
|
||||
return NS_OK;
|
||||
mAnonymousNodesTable = new nsSupportsHashtable;
|
||||
}
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aList) {
|
||||
nsAnonymousContentList* contentList = new nsAnonymousContentList(aList);
|
||||
mAnonymousNodesTable->Put(&key, (nsIDOMNodeList*)contentList);
|
||||
}
|
||||
else
|
||||
mAnonymousNodesTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aParent, getter_AddRefs(binding));
|
||||
|
||||
if (binding)
|
||||
return binding->GetInsertionPoint(aChild, aResult);
|
||||
return binding->GetInsertionPoint(aChild, aResult, aIndex);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult,
|
||||
nsBindingManager::GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aParent, getter_AddRefs(binding));
|
||||
|
||||
if (binding)
|
||||
return binding->GetSingleInsertionPoint( aResult, aMultipleInsertionPoints);
|
||||
return binding->GetSingleInsertionPoint(aResult, aIndex, aMultipleInsertionPoints);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsXBLService.h"
|
||||
#include "nsIXBLInsertionPoint.h"
|
||||
|
||||
// Event listeners
|
||||
#include "nsIEventListenerManager.h"
|
||||
@ -232,6 +233,7 @@ NS_IMPL_ISUPPORTS1(nsXBLBinding, nsIXBLBinding)
|
||||
// Constructors/Destructors
|
||||
nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding* aBinding)
|
||||
: mFirstHandler(nsnull),
|
||||
mInsertionPointTable(nsnull),
|
||||
mIsStyleBinding(PR_TRUE),
|
||||
mMarkedForDeath(PR_FALSE)
|
||||
{
|
||||
@ -277,6 +279,8 @@ nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding* aBinding)
|
||||
|
||||
nsXBLBinding::~nsXBLBinding(void)
|
||||
{
|
||||
delete mInsertionPointTable;
|
||||
|
||||
gRefCnt--;
|
||||
// printf("REF COUNT DOWN: %d %s\n", gRefCnt, (const char*)mID);
|
||||
|
||||
@ -437,6 +441,102 @@ nsXBLBinding::HasStyleSheets(PRBool* aResolveStyle)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct ContentListData {
|
||||
nsXBLBinding* mBinding;
|
||||
nsIBindingManager* mBindingManager;
|
||||
|
||||
ContentListData(nsXBLBinding* aBinding, nsIBindingManager* aManager)
|
||||
:mBinding(aBinding), mBindingManager(aManager)
|
||||
{};
|
||||
};
|
||||
|
||||
PRBool PR_CALLBACK BuildContentLists(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
{
|
||||
ContentListData* data = (ContentListData*)aClosure;
|
||||
nsIBindingManager* bm = data->mBindingManager;
|
||||
nsXBLBinding* binding = data->mBinding;
|
||||
|
||||
nsCOMPtr<nsIContent> boundElement;
|
||||
binding->GetBoundElement(getter_AddRefs(boundElement));
|
||||
|
||||
nsISupportsArray* arr = (nsISupportsArray*)aData;
|
||||
PRUint32 count;
|
||||
arr->Count(&count);
|
||||
|
||||
if (count == 0)
|
||||
return NS_OK;
|
||||
|
||||
// XXX Could this array just be altered in place and passed directly to
|
||||
// SetContentListFor? We'd save space if we could pull this off.
|
||||
nsCOMPtr<nsISupportsArray> contentList;
|
||||
NS_NewISupportsArray(getter_AddRefs(contentList));
|
||||
|
||||
// Figure out the relevant content node.
|
||||
PRUint32 j = 0;
|
||||
nsCOMPtr<nsIXBLInsertionPoint> currPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
PRUint32 currIndex;
|
||||
currPoint->GetInsertionParent(getter_AddRefs(parent));
|
||||
currPoint->GetInsertionIndex(&currIndex);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
||||
if (parent == boundElement) {
|
||||
// We are altering anonymous nodes to accommodate insertion points.
|
||||
binding->GetAnonymousNodes(getter_AddRefs(nodeList));
|
||||
}
|
||||
else {
|
||||
// We are altering the explicit content list of a node to accommodate insertion points.
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(parent));
|
||||
node->GetChildNodes(getter_AddRefs(nodeList));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXBLInsertionPoint> pseudoPoint;
|
||||
PRUint32 childCount;
|
||||
nodeList->GetLength(&childCount);
|
||||
for (PRUint32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nodeList->Item(i, getter_AddRefs(node));
|
||||
nsCOMPtr<nsIContent> child(do_QueryInterface(node));
|
||||
if (i == currIndex) {
|
||||
// Add the currPoint to the supports array.
|
||||
contentList->AppendElement(currPoint);
|
||||
|
||||
// Get the next real insertion point and update our currIndex.
|
||||
j++;
|
||||
if (j < count) {
|
||||
currPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
currPoint->GetInsertionIndex(&currIndex);
|
||||
}
|
||||
|
||||
// Null out our current pseudo-point.
|
||||
pseudoPoint = nsnull;
|
||||
}
|
||||
|
||||
if (!pseudoPoint) {
|
||||
NS_NewXBLInsertionPoint(parent, 0, getter_AddRefs(pseudoPoint));
|
||||
contentList->AppendElement(pseudoPoint);
|
||||
}
|
||||
|
||||
pseudoPoint->AddChild(child);
|
||||
}
|
||||
|
||||
// Add in all the remaining insertion points.
|
||||
for ( ; j < count; j++) {
|
||||
currPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
contentList->AppendElement(currPoint);
|
||||
}
|
||||
|
||||
// Now set the content list using the binding manager,
|
||||
// If the bound element is the parent, then we alter the anonymous node list
|
||||
// instead. This allows us to always maintain two distinct lists should
|
||||
// insertion points be nested into an inner binding.
|
||||
if (parent == boundElement)
|
||||
bm->SetAnonymousNodesFor(parent, contentList);
|
||||
else
|
||||
bm->SetContentListFor(parent, contentList);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
|
||||
{
|
||||
@ -499,6 +599,103 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
|
||||
|
||||
clonedContent = do_QueryInterface(clonedNode);
|
||||
SetAnonymousContent(clonedContent);
|
||||
|
||||
mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
|
||||
|
||||
if (hasInsertionPoints) {
|
||||
// Now check and see if we have a single insertion point
|
||||
// or multiple insertion points.
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
bindingManager->GetContentListFor(mBoundElement, getter_AddRefs(children));
|
||||
|
||||
// Enumerate the prototype binding's insertion table to build
|
||||
// our table of instantiated insertion points.
|
||||
mPrototypeBinding->InstantiateInsertionPoints(this);
|
||||
|
||||
// We now have our insertion point table constructed. We
|
||||
// enumerate this table. For each array of insertion points
|
||||
// bundled under the same content node, we generate a content
|
||||
// list. In the case of the bound element, we generate a new
|
||||
// anonymous node list that will be used in place of the binding's
|
||||
// cached anonymous node list.
|
||||
ContentListData data(this, bindingManager);
|
||||
mInsertionPointTable->Enumerate(BuildContentLists, &data);
|
||||
|
||||
// We need to place the children
|
||||
// at their respective insertion points.
|
||||
nsCOMPtr<nsIContent> singlePoint;
|
||||
PRUint32 index = 0;
|
||||
PRBool multiplePoints = PR_FALSE;
|
||||
GetSingleInsertionPoint(getter_AddRefs(singlePoint), &index, &multiplePoints);
|
||||
|
||||
if (children) {
|
||||
if (multiplePoints) {
|
||||
// We must walk the entire content list in order to determine where
|
||||
// each child belongs.
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRUint32 length;
|
||||
children->GetLength(&length);
|
||||
for (PRUint32 i = 0; i < length; i++) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
content = do_QueryInterface(node);
|
||||
|
||||
// Now determine the insertion point in the prototype table.
|
||||
nsCOMPtr<nsIContent> point;
|
||||
PRUint32 index;
|
||||
GetInsertionPoint(content, getter_AddRefs(point), &index);
|
||||
bindingManager->SetInsertionParent(content, point);
|
||||
|
||||
// Find the correct nsIXBLInsertion point in our table.
|
||||
nsCOMPtr<nsIXBLInsertionPoint> insertionPoint;
|
||||
nsCOMPtr<nsISupportsArray> arr;
|
||||
GetInsertionPointsFor(point, getter_AddRefs(arr));
|
||||
PRUint32 arrCount;
|
||||
arr->Count(&arrCount);
|
||||
for (PRUint32 j = 0; j < arrCount; j++) {
|
||||
insertionPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
PRBool matches;
|
||||
insertionPoint->Matches(point, index, &matches);
|
||||
if (matches)
|
||||
break;
|
||||
insertionPoint = nsnull;
|
||||
}
|
||||
|
||||
if (!insertionPoint) {
|
||||
NS_ERROR("Filtered insertion point wasn't properly constructed.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else
|
||||
insertionPoint->AddChild(content);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// All of our children are shunted to this single insertion point.
|
||||
nsCOMPtr<nsISupportsArray> arr;
|
||||
GetInsertionPointsFor(singlePoint, getter_AddRefs(arr));
|
||||
PRUint32 arrCount;
|
||||
arr->Count(&arrCount);
|
||||
nsCOMPtr<nsIXBLInsertionPoint> insertionPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(0));
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRUint32 length;
|
||||
children->GetLength(&length);
|
||||
for (PRUint32 i = 0; i < length; i++) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
content = do_QueryInterface(node);
|
||||
bindingManager->SetInsertionParent(content, singlePoint);
|
||||
insertionPoint->AddChild(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always check the content element for potential attributes.
|
||||
@ -529,9 +726,6 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
|
||||
mContent->UnsetAttribute(namespaceID, name, PR_FALSE);
|
||||
}
|
||||
|
||||
if (mContent)
|
||||
mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1407,25 +1601,42 @@ nsXBLBinding::AllowScripts()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetInsertionPoint(nsIContent* aChild, nsIContent** aResult)
|
||||
nsXBLBinding::GetInsertionPointsFor(nsIContent* aParent, nsISupportsArray** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->GetInsertionPoint(mBoundElement, mContent, aChild, aResult);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetInsertionPoint(aChild, aResult);
|
||||
if (!mInsertionPointTable)
|
||||
mInsertionPointTable = new nsSupportsHashtable(4);
|
||||
|
||||
nsISupportsKey key(aParent);
|
||||
*aResult = NS_STATIC_CAST(nsISupportsArray*, mInsertionPointTable->Get(&key));
|
||||
|
||||
if (!*aResult) {
|
||||
NS_NewISupportsArray(aResult);
|
||||
mInsertionPointTable->Put(&key, *aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetSingleInsertionPoint(nsIContent** aResult, PRBool* aMultipleInsertionPoints)
|
||||
nsXBLBinding::GetInsertionPoint(nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->GetInsertionPoint(mBoundElement, mContent, aChild, aResult, aIndex);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetInsertionPoint(aChild, aResult, aIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetSingleInsertionPoint(nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
*aMultipleInsertionPoints = PR_FALSE;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->GetSingleInsertionPoint(mBoundElement, mContent, aResult, aMultipleInsertionPoints);
|
||||
return mPrototypeBinding->GetSingleInsertionPoint(mBoundElement, mContent, aResult, aIndex, aMultipleInsertionPoints);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetSingleInsertionPoint(aResult, aMultipleInsertionPoints);
|
||||
return mNextBinding->GetSingleInsertionPoint(aResult, aIndex, aMultipleInsertionPoints);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1480,16 +1691,15 @@ nsXBLBinding::ImplementsInterface(REFNSIID aIID, PRBool* aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetAnonymousNodes(nsIDOMNodeList** aResult, nsIContent** aParent, PRBool* aMultipleInsertionPoints)
|
||||
nsXBLBinding::GetAnonymousNodes(nsIDOMNodeList** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (mContent) {
|
||||
GetSingleInsertionPoint(aParent, aMultipleInsertionPoints);
|
||||
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mContent));
|
||||
return elt->GetChildNodes(aResult);
|
||||
}
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetAnonymousNodes(aResult, aParent, aMultipleInsertionPoints);
|
||||
return mNextBinding->GetAnonymousNodes(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -79,8 +79,10 @@ class nsXBLBinding: public nsIXBLBinding
|
||||
NS_IMETHOD GetDocURI(nsCString& aResult);
|
||||
NS_IMETHOD GetID(nsCString& aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRBool* aMultipleInsertionPoints);
|
||||
NS_IMETHOD GetInsertionPointsFor(nsIContent* aParent, nsISupportsArray** aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints);
|
||||
|
||||
NS_IMETHOD IsStyleBinding(PRBool* aResult) { *aResult = mIsStyleBinding; return NS_OK; };
|
||||
NS_IMETHOD SetIsStyleBinding(PRBool aIsStyle) { mIsStyleBinding = aIsStyle; return NS_OK; };
|
||||
@ -96,7 +98,7 @@ class nsXBLBinding: public nsIXBLBinding
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult);
|
||||
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult, nsIContent** aParent, PRBool* aMultipleInsertionPoints);
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult);
|
||||
|
||||
@ -172,6 +174,8 @@ protected:
|
||||
|
||||
nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
|
||||
|
||||
nsSupportsHashtable* mInsertionPointTable; // A hash from nsIContent* -> (a sorted array of nsIXBLInsertionPoint*)
|
||||
|
||||
PRPackedBool mIsStyleBinding;
|
||||
PRPackedBool mMarkedForDeath;
|
||||
};
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsINameSpace.h"
|
||||
#include "nsXBLService.h"
|
||||
#include "nsXBLBinding.h"
|
||||
#include "nsIXBLInsertionPoint.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "xptinfo.h"
|
||||
@ -108,6 +109,59 @@ public:
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXBLAttributeEntry, nsIXBLAttributeEntry)
|
||||
|
||||
// nsIXBLInsertionPointEntry and helpers. This class stores all the necessary
|
||||
// info to figure out the position of an insertion point.
|
||||
|
||||
// {76F238AE-5ACB-49e6-B2DE-FD1940637753}
|
||||
#define NS_IXBLINS_IID \
|
||||
{ 0x76f238ae, 0x5acb, 0x49e6, { 0xb2, 0xde, 0xfd, 0x19, 0x40, 0x63, 0x77, 0x53 } }
|
||||
|
||||
class nsIXBLInsertionPointEntry : public nsISupports {
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IXBLINS_IID; return iid; }
|
||||
|
||||
NS_IMETHOD GetInsertionParent(nsIContent** aResult)=0;
|
||||
|
||||
NS_IMETHOD GetInsertionIndex(PRUint32* aResult)=0;
|
||||
NS_IMETHOD SetInsertionIndex(PRUint32 aIndex)=0;
|
||||
};
|
||||
|
||||
class nsXBLInsertionPointEntry : public nsIXBLInsertionPointEntry {
|
||||
public:
|
||||
NS_IMETHOD GetInsertionParent(nsIContent** aResult)
|
||||
{
|
||||
*aResult = mInsertionParent;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHOD GetInsertionIndex(PRUint32* aResult) { *aResult = mInsertionIndex; return NS_OK; };
|
||||
NS_IMETHOD SetInsertionIndex(PRUint32 aIndex) { mInsertionIndex = aIndex; return NS_OK; };
|
||||
|
||||
nsCOMPtr<nsIContent> mInsertionParent;
|
||||
PRUint32 mInsertionIndex;
|
||||
|
||||
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
|
||||
return aAllocator.Alloc(aSize);
|
||||
}
|
||||
|
||||
static void operator delete(void* aPtr, size_t aSize) {
|
||||
nsFixedSizeAllocator::Free(aPtr, aSize);
|
||||
}
|
||||
|
||||
nsXBLInsertionPointEntry(nsIContent* aParent) {
|
||||
NS_INIT_REFCNT();
|
||||
mInsertionIndex = 0;
|
||||
mInsertionParent = aParent;
|
||||
};
|
||||
|
||||
virtual ~nsXBLInsertionPointEntry() {};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXBLInsertionPointEntry, nsIXBLInsertionPointEntry)
|
||||
|
||||
// =============================================================================
|
||||
|
||||
// Static initialization
|
||||
@ -123,15 +177,24 @@ nsIAtom* nsXBLPrototypeBinding::kValueAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kXBLTextAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementationAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementsAtom = nsnull;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kPool;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kAttrPool;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kInsPool;
|
||||
|
||||
static const size_t kBucketSizes[] = {
|
||||
static const PRInt32 kNumElements = 128;
|
||||
|
||||
static const size_t kAttrBucketSizes[] = {
|
||||
sizeof(nsXBLAttributeEntry)
|
||||
};
|
||||
|
||||
static const PRInt32 kNumBuckets = sizeof(kBucketSizes)/sizeof(size_t);
|
||||
static const PRInt32 kNumElements = 128;
|
||||
static const PRInt32 kInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLAttributeEntry))) * kNumElements;
|
||||
static const PRInt32 kAttrNumBuckets = sizeof(kAttrBucketSizes)/sizeof(size_t);
|
||||
static const PRInt32 kAttrInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLAttributeEntry))) * kNumElements;
|
||||
|
||||
static const size_t kInsBucketSizes[] = {
|
||||
sizeof(nsXBLInsertionPointEntry)
|
||||
};
|
||||
|
||||
static const PRInt32 kInsNumBuckets = sizeof(kInsBucketSizes)/sizeof(size_t);
|
||||
static const PRInt32 kInsInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLInsertionPointEntry))) * kNumElements;
|
||||
|
||||
// Implementation /////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -156,7 +219,8 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
// printf("REF COUNT UP: %d %s\n", gRefCnt, (const char*)mID);
|
||||
|
||||
if (gRefCnt == 1) {
|
||||
kPool.Init("XBL Attribute Entries", kBucketSizes, kNumBuckets, kInitialSize);
|
||||
kAttrPool.Init("XBL Attribute Entries", kAttrBucketSizes, kAttrNumBuckets, kAttrInitialSize);
|
||||
kInsPool.Init("XBL Insertion Point Entries", kInsBucketSizes, kInsNumBuckets, kInsInitialSize);
|
||||
|
||||
kInheritStyleAtom = NS_NewAtom("inheritstyle");
|
||||
kHandlersAtom = NS_NewAtom("handlers");
|
||||
@ -466,31 +530,107 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct InsertionData {
|
||||
nsIXBLBinding* mBinding;
|
||||
nsXBLPrototypeBinding* mPrototype;
|
||||
|
||||
InsertionData(nsIXBLBinding* aBinding,
|
||||
nsXBLPrototypeBinding* aPrototype)
|
||||
:mBinding(aBinding), mPrototype(aPrototype) {};
|
||||
};
|
||||
|
||||
PRBool PR_CALLBACK InstantiateInsertionPoint(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
{
|
||||
nsIXBLInsertionPointEntry* entry = (nsIXBLInsertionPointEntry*)aData;
|
||||
InsertionData* data = (InsertionData*)aClosure;
|
||||
nsIXBLBinding* binding = data->mBinding;
|
||||
nsXBLPrototypeBinding* proto = data->mPrototype;
|
||||
|
||||
// Get the insertion parent.
|
||||
nsCOMPtr<nsIContent> content;
|
||||
entry->GetInsertionParent(getter_AddRefs(content));
|
||||
PRUint32 index;
|
||||
entry->GetInsertionIndex(&index);
|
||||
|
||||
// Locate the real content.
|
||||
nsCOMPtr<nsIContent> realContent;
|
||||
nsCOMPtr<nsIContent> instanceRoot;
|
||||
binding->GetAnonymousContent(getter_AddRefs(instanceRoot));
|
||||
nsCOMPtr<nsIContent> templRoot;
|
||||
proto->GetImmediateChild(nsXBLPrototypeBinding::kContentAtom, getter_AddRefs(templRoot));
|
||||
proto->LocateInstance(templRoot, instanceRoot, content, getter_AddRefs(realContent));
|
||||
if (!realContent)
|
||||
binding->GetBoundElement(getter_AddRefs(realContent));
|
||||
|
||||
// Now that we have the real content, look it up in our table.
|
||||
nsCOMPtr<nsISupportsArray> points;
|
||||
binding->GetInsertionPointsFor(realContent, getter_AddRefs(points));
|
||||
nsCOMPtr<nsIXBLInsertionPoint> insertionPoint;
|
||||
PRUint32 count;
|
||||
points->Count(&count);
|
||||
PRUint32 i = 0, currIndex = 0;
|
||||
for ( ; i < count; i++) {
|
||||
nsCOMPtr<nsIXBLInsertionPoint> currPoint = getter_AddRefs((nsIXBLInsertionPoint*)points->ElementAt(i));
|
||||
currPoint->GetInsertionIndex(&currIndex);
|
||||
if (currIndex == index) {
|
||||
// This is a match. Break out of the loop and set our variable.
|
||||
insertionPoint = currPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
if (currIndex > index)
|
||||
// There was no match. Break.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!insertionPoint) {
|
||||
// We need to make a new insertion point.
|
||||
NS_NewXBLInsertionPoint(realContent, index, getter_AddRefs(insertionPoint));
|
||||
points->InsertElementAt(insertionPoint, i);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::InstantiateInsertionPoints(nsIXBLBinding* aBinding)
|
||||
{
|
||||
InsertionData data(aBinding, this);
|
||||
if (mInsertionPointTable)
|
||||
mInsertionPointTable->Enumerate(InstantiateInsertionPoint, &data);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent* aChild, nsIContent** aResult)
|
||||
nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
if (mInsertionPointTable) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aChild->GetTag(*getter_AddRefs(tag));
|
||||
nsISupportsKey key(tag);
|
||||
nsCOMPtr<nsIContent> content = getter_AddRefs(NS_STATIC_CAST(nsIContent*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
if (!content) {
|
||||
nsCOMPtr<nsIXBLInsertionPointEntry> entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
if (!entry) {
|
||||
nsISupportsKey key2(kChildrenAtom);
|
||||
content = getter_AddRefs(NS_STATIC_CAST(nsIContent*, mInsertionPointTable->Get(&key2)));
|
||||
entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*, mInsertionPointTable->Get(&key2)));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> realContent;
|
||||
if (content) {
|
||||
if (entry) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
entry->GetInsertionParent(getter_AddRefs(content));
|
||||
entry->GetInsertionIndex(aIndex);
|
||||
nsCOMPtr<nsIContent> templContent;
|
||||
GetImmediateChild(kContentAtom, getter_AddRefs(templContent));
|
||||
LocateInstance(templContent, aCopyRoot, content, getter_AddRefs(realContent));
|
||||
}
|
||||
|
||||
if (realContent)
|
||||
*aResult = realContent;
|
||||
else
|
||||
*aResult = aBoundElement;
|
||||
|
||||
NS_IF_ADDREF(*aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
@ -499,15 +639,19 @@ nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement, nsIContent*
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement,
|
||||
nsIContent* aCopyRoot,
|
||||
nsIContent** aResult, PRBool* aMultipleInsertionPoints)
|
||||
nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
if (mInsertionPointTable) {
|
||||
if(mInsertionPointTable->Count() == 1) {
|
||||
nsISupportsKey key(kChildrenAtom);
|
||||
nsCOMPtr<nsIContent> content = getter_AddRefs(NS_STATIC_CAST(nsIContent*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
nsCOMPtr<nsIXBLInsertionPointEntry> entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
nsCOMPtr<nsIContent> realContent;
|
||||
if (content) {
|
||||
if (entry) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
entry->GetInsertionParent(getter_AddRefs(content));
|
||||
entry->GetInsertionIndex(aIndex);
|
||||
nsCOMPtr<nsIContent> templContent;
|
||||
GetImmediateChild(kContentAtom, getter_AddRefs(templContent));
|
||||
LocateInstance(templContent, aCopyRoot, content, getter_AddRefs(realContent));
|
||||
@ -519,6 +663,7 @@ nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement,
|
||||
// match the filter will just go right underneath the bound element).
|
||||
*aMultipleInsertionPoints = PR_TRUE;
|
||||
*aResult = nsnull;
|
||||
*aIndex = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -527,6 +672,7 @@ nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement,
|
||||
*aResult = realContent;
|
||||
else
|
||||
*aResult = aBoundElement;
|
||||
|
||||
NS_IF_ADDREF(*aResult);
|
||||
}
|
||||
else
|
||||
@ -774,7 +920,7 @@ nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
}
|
||||
|
||||
// Create an XBL attribute entry.
|
||||
nsXBLAttributeEntry* xblAttr = new (kPool) nsXBLAttributeEntry(atom, attribute, aElement);
|
||||
nsXBLAttributeEntry* xblAttr = new (kAttrPool) nsXBLAttributeEntry(atom, attribute, aElement);
|
||||
|
||||
// Now we should see if some element within our anonymous
|
||||
// content is already observing this attribute.
|
||||
@ -826,7 +972,7 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
if (!childrenElements)
|
||||
return;
|
||||
|
||||
mInsertionPointTable = new nsSupportsHashtable;
|
||||
mInsertionPointTable = new nsSupportsHashtable(4);
|
||||
|
||||
PRUint32 count;
|
||||
childrenElements->Count(&count);
|
||||
@ -838,11 +984,15 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
if (child) {
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
child->GetParent(*getter_AddRefs(parent));
|
||||
|
||||
// Create an XBL insertion point entry.
|
||||
nsXBLInsertionPointEntry* xblIns = new (kInsPool) nsXBLInsertionPointEntry(parent);
|
||||
|
||||
nsAutoString includes;
|
||||
child->GetAttribute(kNameSpaceID_None, kIncludesAtom, includes);
|
||||
if (includes.IsEmpty()) {
|
||||
nsISupportsKey key(kChildrenAtom);
|
||||
mInsertionPointTable->Put(&key, parent);
|
||||
mInsertionPointTable->Put(&key, xblIns);
|
||||
}
|
||||
else {
|
||||
// The user specified at least one attribute.
|
||||
@ -860,26 +1010,28 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
atom = getter_AddRefs(NS_NewAtom(tok.GetUnicode()));
|
||||
|
||||
nsISupportsKey key(atom);
|
||||
mInsertionPointTable->Put(&key, parent);
|
||||
mInsertionPointTable->Put(&key, xblIns);
|
||||
|
||||
token = nsCRT::strtok( newStr, ", ", &newStr );
|
||||
}
|
||||
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove the <children> elements.
|
||||
for (i = 0; i < count; i++) {
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
childrenElements->GetElementAt(i, getter_AddRefs(supp));
|
||||
nsCOMPtr<nsIContent> child(do_QueryInterface(supp));
|
||||
if (child) {
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
child->GetParent(*getter_AddRefs(parent));
|
||||
// Compute the index of the <children> element. This index is
|
||||
// equal to the index of the <children> in the template minus the #
|
||||
// of previous insertion point siblings removed. Because our childrenElements
|
||||
// array was built in a DFS that went from left-to-right through siblings,
|
||||
// if we dynamically obtain our index each time, then the removals of previous
|
||||
// siblings will cause the index to adjust (and we won't have to take that into
|
||||
// account explicitly).
|
||||
PRInt32 index;
|
||||
parent->IndexOf(child, index);
|
||||
xblIns->SetInsertionIndex((PRUint32)index);
|
||||
|
||||
// Now remove the <children> element from the template. This ensures that the
|
||||
// binding instantiation will not contain a clone of the <children> element when
|
||||
// it clones the binding template.
|
||||
parent->RemoveChildAt(index, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -75,11 +75,13 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding
|
||||
|
||||
NS_IMETHOD HasInsertionPoints(PRBool* aResult) { *aResult = (mInsertionPointTable != nsnull); return NS_OK; };
|
||||
|
||||
NS_IMETHOD InstantiateInsertionPoints(nsIXBLBinding* aBinding);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent* aChild, nsIContent** aResult);
|
||||
nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent** aResult, PRBool* aMultiple);
|
||||
nsIContent** aResult, PRUint32* aIndex, PRBool* aMultiple);
|
||||
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag);
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag);
|
||||
@ -107,7 +109,8 @@ public:
|
||||
static nsIAtom* kImplementationAtom;
|
||||
static nsIAtom* kImplementsAtom;
|
||||
|
||||
static nsFixedSizeAllocator kPool;
|
||||
static nsFixedSizeAllocator kAttrPool;
|
||||
static nsFixedSizeAllocator kInsPool;
|
||||
|
||||
// Internal member functions
|
||||
public:
|
||||
|
@ -710,31 +710,6 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsAReadableString& aURL,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::GetContentList(nsIContent* aContent, nsIDOMNodeList** aResult, nsIContent** aParent,
|
||||
PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
// Locate the primary binding and get the node list from its mContent parent.
|
||||
*aResult = nsnull;
|
||||
*aParent = nsnull;
|
||||
*aMultipleInsertionPoints = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
aContent->GetDocument(*getter_AddRefs(document));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
NS_ASSERTION(document, "no document");
|
||||
if (!document) return NS_ERROR_FAILURE;
|
||||
document->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
bindingManager->GetBinding(aContent, getter_AddRefs(binding));
|
||||
|
||||
binding->GetAnonymousNodes(getter_AddRefs(aResult), aParent, aMultipleInsertionPoints);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::FlushStyleBindings(nsIContent* aContent)
|
||||
{
|
||||
|
@ -65,11 +65,6 @@ class nsXBLService : public nsIXBLService, public nsIObserver, public nsSupports
|
||||
// This function clears out the bindings on a given content node.
|
||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsIDOMNodeList** aResult, nsIContent** aChildElement,
|
||||
PRBool* aMultipleInsertionPoints);
|
||||
|
||||
// Gets the object's base class type.
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult);
|
||||
|
||||
|
@ -2899,17 +2899,12 @@ NS_IMETHODIMP
|
||||
nsXULDocument::GetAnonymousNodes(nsIDOMElement* aElement,
|
||||
nsIDOMNodeList** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Use the XBL service to get the anonymous node list.
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
PRBool dummy;
|
||||
nsCOMPtr<nsIContent> dummyElt;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return xblService->GetContentList(content, aResult, getter_AddRefs(dummyElt), &dummy);
|
||||
*aResult = nsnull;
|
||||
if (mBindingManager) {
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return mBindingManager->GetAnonymousNodesFor(content, aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -786,6 +786,56 @@ nsMathMLmtableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame)
|
||||
}
|
||||
#endif // MOZ_MATHML
|
||||
|
||||
// Helper class for iterating children during frame construction.
|
||||
// This class should always be used in lieu of the straight content
|
||||
// node APIs, since it handles XBL-generated anonymous content as well.
|
||||
struct ChildIterator
|
||||
{
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsCOMPtr<nsIBindingManager> mBindingManager;
|
||||
PRUint32 mIndex;
|
||||
PRUint32 mLength;
|
||||
nsCOMPtr<nsIDOMNodeList> mNodes;
|
||||
|
||||
ChildIterator(nsIContent* aContent)
|
||||
:mContent(aContent), mIndex(0), mLength(0), mNodes(nsnull)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aContent->GetDocument(*getter_AddRefs(doc));
|
||||
doc->GetBindingManager(getter_AddRefs(mBindingManager));
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
mBindingManager->GetAnonymousNodesFor(mContent, getter_AddRefs(mNodes));
|
||||
if (mNodes) {
|
||||
mNodes->GetLength(&mLength);
|
||||
if (mLength == 0)
|
||||
mNodes = 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 (!mNodes) {
|
||||
mBindingManager->GetContentListFor(mContent, getter_AddRefs(mNodes));
|
||||
if (mNodes)
|
||||
mNodes->GetLength(&mLength);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool HasMoreChildren() {
|
||||
return mIndex < mLength;
|
||||
}
|
||||
|
||||
void NextChild(nsIContent** aChild) {
|
||||
if (mNodes) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
mNodes->Item(mIndex, getter_AddRefs(node));
|
||||
node->QueryInterface(NS_GET_IID(nsIContent), (void**)aChild);
|
||||
}
|
||||
mIndex++;
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// return the child list that aFrame belongs on. does not ADDREF
|
||||
@ -818,6 +868,7 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(void)
|
||||
mGfxScrollFrame(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
mVerifyFastFindFrame = PR_FALSE;
|
||||
// Get the pref for verifying the new fast find frame with hint code.
|
||||
@ -2864,12 +2915,6 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShe
|
||||
PR_TRUE, childItems, PR_TRUE, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// if there are any tree anonymous children create frames for them
|
||||
nsCOMPtr<nsIAtom> tagName;
|
||||
aContent->GetTag(*getter_AddRefs(tagName));
|
||||
CreateAnonymousTableCellFrames(aPresShell, aPresContext, tagName, aState, aContent,
|
||||
aNewCellInnerFrame, aNewCellOuterFrame, childItems);
|
||||
|
||||
aNewCellInnerFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
|
||||
if (aState.mFloatedItems.childList) {
|
||||
aNewCellInnerFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::floaterList,
|
||||
@ -3019,13 +3064,11 @@ nsCSSFrameConstructor::TableProcessChildren(nsIPresShell* aPresShell,
|
||||
nsCOMPtr<nsIStyleContext> parentStyleContext;
|
||||
aParentFrame->GetStyleContext(getter_AddRefs(parentStyleContext));
|
||||
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
|
||||
for (PRInt32 childX = 0; childX < count; childX++) { // iterate the child content
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
rv = aContent->ChildAt(childX, *getter_AddRefs(childContent));
|
||||
if (childContent.get() && NS_SUCCEEDED(rv)) {
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
if (childContent.get()) {
|
||||
rv = TableProcessChild(aPresShell, aPresContext, aState, *childContent.get(), aParentFrame,
|
||||
parentFrameType.get(), parentStyleContext.get(),
|
||||
aTableCreator, aChildItems, aCaption);
|
||||
@ -4126,7 +4169,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell,
|
||||
|
||||
InitializeSelectFrame(aPresShell, aPresContext, aState, listFrame, scrolledFrame, aContent, comboboxFrame,
|
||||
listStyle, PR_FALSE, PR_FALSE, PR_TRUE);
|
||||
|
||||
newFrame = listFrame;
|
||||
// XXX Temporary for Bug 19416
|
||||
{
|
||||
@ -5041,160 +5083,8 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell,
|
||||
nsIFrame* aNewFrame,
|
||||
nsFrameItems& aChildItems)
|
||||
{
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
aNewFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
||||
const nsStyleUserInterface* ui= (const nsStyleUserInterface*)
|
||||
styleContext->GetStyleData(eStyleStruct_UserInterface);
|
||||
|
||||
if (!ui->mBehavior.IsEmpty()) {
|
||||
// Get the XBL loader.
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
nsCOMPtr<nsIDOMNodeList> anonymousItems;
|
||||
nsCOMPtr<nsIContent> childElement;
|
||||
PRBool multiple;
|
||||
xblService->GetContentList(aParent, getter_AddRefs(anonymousItems), getter_AddRefs(childElement), &multiple);
|
||||
|
||||
if (anonymousItems)
|
||||
{
|
||||
// See if we have to move our explicit content.
|
||||
nsFrameItems explicitItems;
|
||||
if (childElement || multiple) {
|
||||
// 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->GetLength(&count);
|
||||
|
||||
for (PRUint32 i=0; i < count; i++)
|
||||
{
|
||||
// get our child's content and set its parent to our content
|
||||
nsCOMPtr<nsIDOMNode> elt;
|
||||
if (NS_FAILED(anonymousItems->Item(i, getter_AddRefs(elt))))
|
||||
continue;
|
||||
|
||||
// create the frame and attach it to our frame
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
|
||||
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<nsIFrameManager> frameManager;
|
||||
aPresShell->GetFrameManager(getter_AddRefs(frameManager));
|
||||
|
||||
if (frameManager && frame && explicitItems.childList) {
|
||||
frameManager->AppendFrames(aPresContext, *aPresShell, frame,
|
||||
nsnull, explicitItems.childList);
|
||||
|
||||
nsIFrame* insertionPoint = nsnull;
|
||||
frameManager->GetInsertionPoint(aPresShell, frame, explicitItems.childList, &insertionPoint);
|
||||
if (!insertionPoint) {
|
||||
nsCOMPtr<nsIStyleContext> styleContextForFrame;
|
||||
frame->GetStyleContext(getter_AddRefs(styleContextForFrame));
|
||||
nsIFrame* walkit = explicitItems.childList;
|
||||
while (walkit) {
|
||||
nsIFrame* realFrame = GetRealFrame(walkit);
|
||||
realFrame->SetParent(frame);
|
||||
aPresContext->ReParentStyleContext(realFrame, styleContextForFrame);
|
||||
walkit->GetNextSibling(&walkit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (multiple) {
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
aParent->GetDocument(*getter_AddRefs(document));
|
||||
document->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
nsCOMPtr<nsIContent> currContent;
|
||||
nsCOMPtr<nsIContent> insertionElement;
|
||||
nsIFrame* currFrame = explicitItems.childList;
|
||||
explicitItems.childList = explicitItems.lastChild = nsnull;
|
||||
nsCOMPtr<nsIFrameManager> frameManager;
|
||||
aPresShell->GetFrameManager(getter_AddRefs(frameManager));
|
||||
|
||||
while (currFrame) {
|
||||
nsIFrame* nextFrame;
|
||||
currFrame->GetNextSibling(&nextFrame);
|
||||
currFrame->SetNextSibling(nsnull);
|
||||
|
||||
currFrame->GetContent(getter_AddRefs(currContent));
|
||||
bindingManager->GetInsertionPoint(aParent, currContent, getter_AddRefs(insertionElement));
|
||||
|
||||
nsIFrame* frame = nsnull;
|
||||
if (insertionElement) {
|
||||
nsIFrame* childFrame = aChildItems.childList;
|
||||
while (childFrame) {
|
||||
LocateAnonymousFrame(aPresContext,
|
||||
childFrame,
|
||||
insertionElement,
|
||||
&frame);
|
||||
if (frame)
|
||||
break;
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
}
|
||||
|
||||
if (!frame) {
|
||||
if (!explicitItems.childList)
|
||||
explicitItems.childList = explicitItems.lastChild = currFrame;
|
||||
else {
|
||||
explicitItems.lastChild->SetNextSibling(currFrame);
|
||||
explicitItems.lastChild = currFrame;
|
||||
}
|
||||
}
|
||||
|
||||
if (frameManager && frame) {
|
||||
frameManager->AppendFrames(aPresContext, *aPresShell, frame,
|
||||
nsnull, currFrame);
|
||||
|
||||
nsIFrame* insertionPoint = nsnull;
|
||||
frameManager->GetInsertionPoint(aPresShell, frame, explicitItems.childList, &insertionPoint);
|
||||
if (!insertionPoint) {
|
||||
frame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
nsIFrame* realFrame = GetRealFrame(currFrame);
|
||||
realFrame->SetParent(frame);
|
||||
aPresContext->ReParentStyleContext(realFrame, styleContext);
|
||||
}
|
||||
}
|
||||
|
||||
currFrame = nextFrame;
|
||||
}
|
||||
if (explicitItems.lastChild) {
|
||||
explicitItems.lastChild->SetNextSibling(aChildItems.childList);
|
||||
aChildItems.childList = explicitItems.childList;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// If we have no anonymous content from XBL see if we might have
|
||||
// some by looking at the tag rather than doing a QueryInterface on
|
||||
// See if we might have anonymous content
|
||||
// by looking at the tag rather than doing a QueryInterface on
|
||||
// the frame. Only these tags' frames can have anonymous content
|
||||
// through nsIAnonymousContentCreator. We do this check for
|
||||
// performance reasons. If we did a QueryInterface on every tag it
|
||||
@ -5278,61 +5168,6 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// after the node has been constructed and initialized create any
|
||||
// anonymous content a node needs.
|
||||
nsresult
|
||||
nsCSSFrameConstructor::CreateAnonymousTableCellFrames(nsIPresShell* aPresShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIAtom* aTag,
|
||||
nsFrameConstructorState& aState,
|
||||
nsIContent* aParent,
|
||||
nsIFrame* aNewFrame,
|
||||
nsIFrame* aNewCellFrame,
|
||||
nsFrameItems& aChildItems)
|
||||
{
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
aNewCellFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
||||
const nsStyleUserInterface* ui= (const nsStyleUserInterface*)
|
||||
styleContext->GetStyleData(eStyleStruct_UserInterface);
|
||||
|
||||
if (!ui->mBehavior.IsEmpty()) {
|
||||
// Get the XBL loader.
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
nsCOMPtr<nsIContent> childElement;
|
||||
nsCOMPtr<nsIDOMNodeList> anonymousItems;
|
||||
PRBool multiple;
|
||||
xblService->GetContentList(aParent, getter_AddRefs(anonymousItems), getter_AddRefs(childElement), &multiple);
|
||||
|
||||
if (!anonymousItems)
|
||||
return NS_OK;
|
||||
|
||||
// Build the frames for the anonymous content.
|
||||
PRUint32 count = 0;
|
||||
anonymousItems->GetLength(&count);
|
||||
|
||||
for (PRUint32 i=0; i < count; i++)
|
||||
{
|
||||
// get our child's content and set its parent to our content
|
||||
nsCOMPtr<nsIDOMNode> elt;
|
||||
if (NS_FAILED(anonymousItems->Item(i, getter_AddRefs(elt))))
|
||||
continue;
|
||||
|
||||
// create the frame and attach it to our frame
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
|
||||
ConstructFrame(aPresShell, aPresContext, aState, content, aNewFrame, aChildItems);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_XUL
|
||||
nsresult
|
||||
nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
|
||||
@ -7175,29 +7010,19 @@ nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
|
||||
rv = ResolveStyleContext(aPresContext, aParentFrame, aContent, tag, getter_AddRefs(styleContext));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Pre-check for display "none" - if we find that, don't create
|
||||
// any frame at all
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
styleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
|
||||
aState.mFrameManager->SetUndisplayedContent(aContent, styleContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRInt32 nameSpaceID;
|
||||
aContent->GetNameSpaceID(nameSpaceID);
|
||||
rv = ConstructFrameInternal(aPresShell,
|
||||
aPresContext,
|
||||
aState,
|
||||
aContent,
|
||||
aParentFrame,
|
||||
tag,
|
||||
nameSpaceID,
|
||||
styleContext,
|
||||
aFrameItems,
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
PRInt32 nameSpaceID;
|
||||
aContent->GetNameSpaceID(nameSpaceID);
|
||||
rv = ConstructFrameInternal(aPresShell,
|
||||
aPresContext,
|
||||
aState,
|
||||
aContent,
|
||||
aParentFrame,
|
||||
tag,
|
||||
nameSpaceID,
|
||||
styleContext,
|
||||
aFrameItems,
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -7216,13 +7041,8 @@ nsCSSFrameConstructor::ConstructFrameInternal( nsIPresShell* aPresShe
|
||||
nsFrameItems& aFrameItems,
|
||||
PRBool aXBLBaseTag)
|
||||
{
|
||||
#ifdef DEBUG_hyatt
|
||||
if (aTag == nsXULAtoms::menulist) {
|
||||
printf("moo!");
|
||||
}
|
||||
#endif /* DEBUG_hyatt */
|
||||
// The following code allows the user to specify the base tag
|
||||
// of a XUL object using XBL. XUL objects (like boxes, menus, etc.)
|
||||
// of an element using XBL. XUL and HTML objects (like boxes, menus, etc.)
|
||||
// can then be extended arbitrarily.
|
||||
nsCOMPtr<nsIStyleContext> styleContext(do_QueryInterface(aStyleContext));
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
@ -7278,6 +7098,15 @@ nsCSSFrameConstructor::ConstructFrameInternal( nsIPresShell* aPresShe
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-check for display "none" - if we find that, don't create
|
||||
// any frame at all
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
styleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
|
||||
aState.mFrameManager->SetUndisplayedContent(aContent, styleContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame* lastChild = aFrameItems.lastChild;
|
||||
|
||||
@ -11286,11 +11115,11 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresShell* aPresShell,
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
|
||||
aFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
||||
if (aCanHaveGeneratedContent) {
|
||||
// Probe for generated content before
|
||||
nsIFrame* generatedFrame;
|
||||
aFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
if (CreateGeneratedContentFrame(aPresShell, aPresContext, aState, aFrame, aContent,
|
||||
styleContext, nsCSSAtoms::beforePseudo,
|
||||
aParentIsBlock, &generatedFrame)) {
|
||||
@ -11310,19 +11139,15 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresShell* aPresShell,
|
||||
nsPseudoFrames priorPseudoFrames;
|
||||
aState.mPseudoFrames.Reset(&priorPseudoFrames);
|
||||
|
||||
// Iterate the child content objects and construct frames
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) {
|
||||
// Construct a child frame
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
// process the current pseudo frame state
|
||||
if (!aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aFrameItems);
|
||||
@ -12471,17 +12296,14 @@ nsCSSFrameConstructor::ProcessBlockChildren(nsIPresShell* aPresShell,
|
||||
}
|
||||
|
||||
// Iterate the child content objects and construct frames
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) {
|
||||
// Construct a child frame
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
// Construct a child frame
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
// process pseudo frames if necessary
|
||||
@ -12763,36 +12585,34 @@ nsCSSFrameConstructor::ProcessInlineChildren(nsIPresShell* aPresShell,
|
||||
|
||||
// Iterate the child content objects and construct frames
|
||||
PRBool allKidsInline = PR_TRUE;
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) {
|
||||
// Construct a child frame
|
||||
nsIFrame* oldLastChild = aFrameItems.lastChild;
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
// Construct a child frame
|
||||
nsIFrame* oldLastChild = aFrameItems.lastChild;
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Examine newly added children (we may have added more than one
|
||||
// child if the child was another inline frame that ends up
|
||||
// being carved in 3 pieces) to maintain the allKidsInline flag.
|
||||
if (allKidsInline) {
|
||||
nsIFrame* kid;
|
||||
if (oldLastChild) {
|
||||
oldLastChild->GetNextSibling(&kid);
|
||||
}
|
||||
else {
|
||||
kid = aFrameItems.childList;
|
||||
}
|
||||
while (kid) {
|
||||
if (!IsInlineFrame(kid)) {
|
||||
allKidsInline = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
kid->GetNextSibling(&kid);
|
||||
// Examine newly added children (we may have added more than one
|
||||
// child if the child was another inline frame that ends up
|
||||
// being carved in 3 pieces) to maintain the allKidsInline flag.
|
||||
if (allKidsInline) {
|
||||
nsIFrame* kid;
|
||||
if (oldLastChild) {
|
||||
oldLastChild->GetNextSibling(&kid);
|
||||
}
|
||||
else {
|
||||
kid = aFrameItems.childList;
|
||||
}
|
||||
while (kid) {
|
||||
if (!IsInlineFrame(kid)) {
|
||||
allKidsInline = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
kid->GetNextSibling(&kid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ struct nsStyleDisplay;
|
||||
class nsIPresShell;
|
||||
class nsVoidArray;
|
||||
class nsIFrameManager;
|
||||
|
||||
class nsFrameConstructorState;
|
||||
class nsIDOMHTMLSelectElement;
|
||||
class nsIXBLService;
|
||||
|
||||
class nsCSSFrameConstructor : public nsIStyleFrameConstruction {
|
||||
public:
|
||||
@ -524,15 +524,6 @@ protected:
|
||||
nsIFrame* aNewFrame,
|
||||
nsFrameItems& aChildItems);
|
||||
|
||||
nsresult CreateAnonymousTableCellFrames(nsIPresShell* aPresShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIAtom* aTag,
|
||||
nsFrameConstructorState& aState,
|
||||
nsIContent* aParent,
|
||||
nsIFrame* aNewCellBodyFrame,
|
||||
nsIFrame* aNewCellFrame,
|
||||
nsFrameItems& aChildItems);
|
||||
|
||||
//MathML Mod - RBS
|
||||
#ifdef MOZ_MATHML
|
||||
nsresult ConstructMathMLFrame(nsIPresShell* aPresShell,
|
||||
@ -954,12 +945,12 @@ protected:
|
||||
PRBool mGotGfxPrefs;
|
||||
PRBool mHasGfxScrollbars;
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRBool mVerifyFastFindFrame; // if true, run both the old and new find frame code
|
||||
// to validate that both ways get the same answer
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
|
||||
};
|
||||
|
||||
#endif /* nsCSSFrameConstructor_h___ */
|
||||
|
@ -2396,7 +2396,8 @@ FrameManager::GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aParent, nsIFram
|
||||
return NS_OK; // It is anonymous. Don't use the insertion point, since that's only
|
||||
// for the explicit kids.
|
||||
|
||||
bindingManager->GetInsertionPoint(content, currContent, getter_AddRefs(insertionElement));
|
||||
PRUint32 index;
|
||||
bindingManager->GetInsertionPoint(content, currContent, getter_AddRefs(insertionElement), &index);
|
||||
if (insertionElement) {
|
||||
aShell->GetPrimaryFrameFor(insertionElement, &frame);
|
||||
if (frame) {
|
||||
@ -2414,7 +2415,8 @@ FrameManager::GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aParent, nsIFram
|
||||
}
|
||||
else {
|
||||
PRBool dummy;
|
||||
bindingManager->GetSingleInsertionPoint(content, getter_AddRefs(insertionElement), &dummy);
|
||||
PRUint32 index;
|
||||
bindingManager->GetSingleInsertionPoint(content, getter_AddRefs(insertionElement), &index, &dummy);
|
||||
if (insertionElement) {
|
||||
aShell->GetPrimaryFrameFor(insertionElement, &frame);
|
||||
if (frame) {
|
||||
|
@ -545,57 +545,6 @@ nsDocumentChildNodes::DropReference()
|
||||
// =
|
||||
// ==================================================================
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsAnonymousContentList)
|
||||
|
||||
nsAnonymousContentList::nsAnonymousContentList(nsISupportsArray* aElements)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAnonymousContentList);
|
||||
|
||||
// We don't reference count our Anonymous reference (to avoid circular
|
||||
// references). We'll be told when the Anonymous goes away.
|
||||
mElements = aElements;
|
||||
NS_IF_ADDREF(mElements);
|
||||
}
|
||||
|
||||
nsAnonymousContentList::~nsAnonymousContentList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsAnonymousContentList);
|
||||
NS_IF_RELEASE(mElements);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::GetLength(PRUint32* aLength)
|
||||
{
|
||||
NS_ASSERTION(aLength != nsnull, "null ptr");
|
||||
if (! aLength)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mElements->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
*aLength = cnt;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
||||
{
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mElements->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aIndex >= (PRUint32) cnt)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// Cast is okay because we're in a closed system.
|
||||
*aReturn = (nsIDOMNode*) mElements->ElementAt(aIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// =
|
||||
// ==================================================================
|
||||
|
||||
nsDocument::nsDocument()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
@ -2211,17 +2160,12 @@ NS_IMETHODIMP
|
||||
nsDocument::GetAnonymousNodes(nsIDOMElement* aElement,
|
||||
nsIDOMNodeList** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Use the XBL service to get the anonymous node list.
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
PRBool dummy;
|
||||
nsCOMPtr<nsIContent> dummyElt;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return xblService->GetContentList(content, aResult, getter_AddRefs(dummyElt), &dummy);
|
||||
*aResult = nsnull;
|
||||
if (mBindingManager) {
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return mBindingManager->GetAnonymousNodesFor(content, aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -115,19 +115,6 @@ protected:
|
||||
nsIDocument* mDocument;
|
||||
};
|
||||
|
||||
class nsAnonymousContentList : public nsGenericDOMNodeList
|
||||
{
|
||||
public:
|
||||
nsAnonymousContentList(nsISupportsArray* aElements);
|
||||
virtual ~nsAnonymousContentList();
|
||||
|
||||
// nsIDOMNodeList interface
|
||||
NS_DECL_IDOMNODELIST
|
||||
|
||||
private:
|
||||
nsISupportsArray* mElements;
|
||||
};
|
||||
|
||||
// Base class for our document implementations
|
||||
class nsDocument : public nsIDocument,
|
||||
public nsIDOMDocument,
|
||||
|
@ -2396,7 +2396,8 @@ FrameManager::GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aParent, nsIFram
|
||||
return NS_OK; // It is anonymous. Don't use the insertion point, since that's only
|
||||
// for the explicit kids.
|
||||
|
||||
bindingManager->GetInsertionPoint(content, currContent, getter_AddRefs(insertionElement));
|
||||
PRUint32 index;
|
||||
bindingManager->GetInsertionPoint(content, currContent, getter_AddRefs(insertionElement), &index);
|
||||
if (insertionElement) {
|
||||
aShell->GetPrimaryFrameFor(insertionElement, &frame);
|
||||
if (frame) {
|
||||
@ -2414,7 +2415,8 @@ FrameManager::GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aParent, nsIFram
|
||||
}
|
||||
else {
|
||||
PRBool dummy;
|
||||
bindingManager->GetSingleInsertionPoint(content, getter_AddRefs(insertionElement), &dummy);
|
||||
PRUint32 index;
|
||||
bindingManager->GetSingleInsertionPoint(content, getter_AddRefs(insertionElement), &index, &dummy);
|
||||
if (insertionElement) {
|
||||
aShell->GetPrimaryFrameFor(insertionElement, &frame);
|
||||
if (frame) {
|
||||
|
@ -786,6 +786,56 @@ nsMathMLmtableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame)
|
||||
}
|
||||
#endif // MOZ_MATHML
|
||||
|
||||
// Helper class for iterating children during frame construction.
|
||||
// This class should always be used in lieu of the straight content
|
||||
// node APIs, since it handles XBL-generated anonymous content as well.
|
||||
struct ChildIterator
|
||||
{
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsCOMPtr<nsIBindingManager> mBindingManager;
|
||||
PRUint32 mIndex;
|
||||
PRUint32 mLength;
|
||||
nsCOMPtr<nsIDOMNodeList> mNodes;
|
||||
|
||||
ChildIterator(nsIContent* aContent)
|
||||
:mContent(aContent), mIndex(0), mLength(0), mNodes(nsnull)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aContent->GetDocument(*getter_AddRefs(doc));
|
||||
doc->GetBindingManager(getter_AddRefs(mBindingManager));
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
mBindingManager->GetAnonymousNodesFor(mContent, getter_AddRefs(mNodes));
|
||||
if (mNodes) {
|
||||
mNodes->GetLength(&mLength);
|
||||
if (mLength == 0)
|
||||
mNodes = 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 (!mNodes) {
|
||||
mBindingManager->GetContentListFor(mContent, getter_AddRefs(mNodes));
|
||||
if (mNodes)
|
||||
mNodes->GetLength(&mLength);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool HasMoreChildren() {
|
||||
return mIndex < mLength;
|
||||
}
|
||||
|
||||
void NextChild(nsIContent** aChild) {
|
||||
if (mNodes) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
mNodes->Item(mIndex, getter_AddRefs(node));
|
||||
node->QueryInterface(NS_GET_IID(nsIContent), (void**)aChild);
|
||||
}
|
||||
mIndex++;
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// return the child list that aFrame belongs on. does not ADDREF
|
||||
@ -818,6 +868,7 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(void)
|
||||
mGfxScrollFrame(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
mVerifyFastFindFrame = PR_FALSE;
|
||||
// Get the pref for verifying the new fast find frame with hint code.
|
||||
@ -2864,12 +2915,6 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShe
|
||||
PR_TRUE, childItems, PR_TRUE, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// if there are any tree anonymous children create frames for them
|
||||
nsCOMPtr<nsIAtom> tagName;
|
||||
aContent->GetTag(*getter_AddRefs(tagName));
|
||||
CreateAnonymousTableCellFrames(aPresShell, aPresContext, tagName, aState, aContent,
|
||||
aNewCellInnerFrame, aNewCellOuterFrame, childItems);
|
||||
|
||||
aNewCellInnerFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
|
||||
if (aState.mFloatedItems.childList) {
|
||||
aNewCellInnerFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::floaterList,
|
||||
@ -3019,13 +3064,11 @@ nsCSSFrameConstructor::TableProcessChildren(nsIPresShell* aPresShell,
|
||||
nsCOMPtr<nsIStyleContext> parentStyleContext;
|
||||
aParentFrame->GetStyleContext(getter_AddRefs(parentStyleContext));
|
||||
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
|
||||
for (PRInt32 childX = 0; childX < count; childX++) { // iterate the child content
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
rv = aContent->ChildAt(childX, *getter_AddRefs(childContent));
|
||||
if (childContent.get() && NS_SUCCEEDED(rv)) {
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
if (childContent.get()) {
|
||||
rv = TableProcessChild(aPresShell, aPresContext, aState, *childContent.get(), aParentFrame,
|
||||
parentFrameType.get(), parentStyleContext.get(),
|
||||
aTableCreator, aChildItems, aCaption);
|
||||
@ -4126,7 +4169,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell,
|
||||
|
||||
InitializeSelectFrame(aPresShell, aPresContext, aState, listFrame, scrolledFrame, aContent, comboboxFrame,
|
||||
listStyle, PR_FALSE, PR_FALSE, PR_TRUE);
|
||||
|
||||
newFrame = listFrame;
|
||||
// XXX Temporary for Bug 19416
|
||||
{
|
||||
@ -5041,160 +5083,8 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell,
|
||||
nsIFrame* aNewFrame,
|
||||
nsFrameItems& aChildItems)
|
||||
{
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
aNewFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
||||
const nsStyleUserInterface* ui= (const nsStyleUserInterface*)
|
||||
styleContext->GetStyleData(eStyleStruct_UserInterface);
|
||||
|
||||
if (!ui->mBehavior.IsEmpty()) {
|
||||
// Get the XBL loader.
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
nsCOMPtr<nsIDOMNodeList> anonymousItems;
|
||||
nsCOMPtr<nsIContent> childElement;
|
||||
PRBool multiple;
|
||||
xblService->GetContentList(aParent, getter_AddRefs(anonymousItems), getter_AddRefs(childElement), &multiple);
|
||||
|
||||
if (anonymousItems)
|
||||
{
|
||||
// See if we have to move our explicit content.
|
||||
nsFrameItems explicitItems;
|
||||
if (childElement || multiple) {
|
||||
// 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->GetLength(&count);
|
||||
|
||||
for (PRUint32 i=0; i < count; i++)
|
||||
{
|
||||
// get our child's content and set its parent to our content
|
||||
nsCOMPtr<nsIDOMNode> elt;
|
||||
if (NS_FAILED(anonymousItems->Item(i, getter_AddRefs(elt))))
|
||||
continue;
|
||||
|
||||
// create the frame and attach it to our frame
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
|
||||
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<nsIFrameManager> frameManager;
|
||||
aPresShell->GetFrameManager(getter_AddRefs(frameManager));
|
||||
|
||||
if (frameManager && frame && explicitItems.childList) {
|
||||
frameManager->AppendFrames(aPresContext, *aPresShell, frame,
|
||||
nsnull, explicitItems.childList);
|
||||
|
||||
nsIFrame* insertionPoint = nsnull;
|
||||
frameManager->GetInsertionPoint(aPresShell, frame, explicitItems.childList, &insertionPoint);
|
||||
if (!insertionPoint) {
|
||||
nsCOMPtr<nsIStyleContext> styleContextForFrame;
|
||||
frame->GetStyleContext(getter_AddRefs(styleContextForFrame));
|
||||
nsIFrame* walkit = explicitItems.childList;
|
||||
while (walkit) {
|
||||
nsIFrame* realFrame = GetRealFrame(walkit);
|
||||
realFrame->SetParent(frame);
|
||||
aPresContext->ReParentStyleContext(realFrame, styleContextForFrame);
|
||||
walkit->GetNextSibling(&walkit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (multiple) {
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
aParent->GetDocument(*getter_AddRefs(document));
|
||||
document->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
nsCOMPtr<nsIContent> currContent;
|
||||
nsCOMPtr<nsIContent> insertionElement;
|
||||
nsIFrame* currFrame = explicitItems.childList;
|
||||
explicitItems.childList = explicitItems.lastChild = nsnull;
|
||||
nsCOMPtr<nsIFrameManager> frameManager;
|
||||
aPresShell->GetFrameManager(getter_AddRefs(frameManager));
|
||||
|
||||
while (currFrame) {
|
||||
nsIFrame* nextFrame;
|
||||
currFrame->GetNextSibling(&nextFrame);
|
||||
currFrame->SetNextSibling(nsnull);
|
||||
|
||||
currFrame->GetContent(getter_AddRefs(currContent));
|
||||
bindingManager->GetInsertionPoint(aParent, currContent, getter_AddRefs(insertionElement));
|
||||
|
||||
nsIFrame* frame = nsnull;
|
||||
if (insertionElement) {
|
||||
nsIFrame* childFrame = aChildItems.childList;
|
||||
while (childFrame) {
|
||||
LocateAnonymousFrame(aPresContext,
|
||||
childFrame,
|
||||
insertionElement,
|
||||
&frame);
|
||||
if (frame)
|
||||
break;
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
}
|
||||
|
||||
if (!frame) {
|
||||
if (!explicitItems.childList)
|
||||
explicitItems.childList = explicitItems.lastChild = currFrame;
|
||||
else {
|
||||
explicitItems.lastChild->SetNextSibling(currFrame);
|
||||
explicitItems.lastChild = currFrame;
|
||||
}
|
||||
}
|
||||
|
||||
if (frameManager && frame) {
|
||||
frameManager->AppendFrames(aPresContext, *aPresShell, frame,
|
||||
nsnull, currFrame);
|
||||
|
||||
nsIFrame* insertionPoint = nsnull;
|
||||
frameManager->GetInsertionPoint(aPresShell, frame, explicitItems.childList, &insertionPoint);
|
||||
if (!insertionPoint) {
|
||||
frame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
nsIFrame* realFrame = GetRealFrame(currFrame);
|
||||
realFrame->SetParent(frame);
|
||||
aPresContext->ReParentStyleContext(realFrame, styleContext);
|
||||
}
|
||||
}
|
||||
|
||||
currFrame = nextFrame;
|
||||
}
|
||||
if (explicitItems.lastChild) {
|
||||
explicitItems.lastChild->SetNextSibling(aChildItems.childList);
|
||||
aChildItems.childList = explicitItems.childList;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// If we have no anonymous content from XBL see if we might have
|
||||
// some by looking at the tag rather than doing a QueryInterface on
|
||||
// See if we might have anonymous content
|
||||
// by looking at the tag rather than doing a QueryInterface on
|
||||
// the frame. Only these tags' frames can have anonymous content
|
||||
// through nsIAnonymousContentCreator. We do this check for
|
||||
// performance reasons. If we did a QueryInterface on every tag it
|
||||
@ -5278,61 +5168,6 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// after the node has been constructed and initialized create any
|
||||
// anonymous content a node needs.
|
||||
nsresult
|
||||
nsCSSFrameConstructor::CreateAnonymousTableCellFrames(nsIPresShell* aPresShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIAtom* aTag,
|
||||
nsFrameConstructorState& aState,
|
||||
nsIContent* aParent,
|
||||
nsIFrame* aNewFrame,
|
||||
nsIFrame* aNewCellFrame,
|
||||
nsFrameItems& aChildItems)
|
||||
{
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
aNewCellFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
||||
const nsStyleUserInterface* ui= (const nsStyleUserInterface*)
|
||||
styleContext->GetStyleData(eStyleStruct_UserInterface);
|
||||
|
||||
if (!ui->mBehavior.IsEmpty()) {
|
||||
// Get the XBL loader.
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
nsCOMPtr<nsIContent> childElement;
|
||||
nsCOMPtr<nsIDOMNodeList> anonymousItems;
|
||||
PRBool multiple;
|
||||
xblService->GetContentList(aParent, getter_AddRefs(anonymousItems), getter_AddRefs(childElement), &multiple);
|
||||
|
||||
if (!anonymousItems)
|
||||
return NS_OK;
|
||||
|
||||
// Build the frames for the anonymous content.
|
||||
PRUint32 count = 0;
|
||||
anonymousItems->GetLength(&count);
|
||||
|
||||
for (PRUint32 i=0; i < count; i++)
|
||||
{
|
||||
// get our child's content and set its parent to our content
|
||||
nsCOMPtr<nsIDOMNode> elt;
|
||||
if (NS_FAILED(anonymousItems->Item(i, getter_AddRefs(elt))))
|
||||
continue;
|
||||
|
||||
// create the frame and attach it to our frame
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
|
||||
ConstructFrame(aPresShell, aPresContext, aState, content, aNewFrame, aChildItems);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_XUL
|
||||
nsresult
|
||||
nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
|
||||
@ -7175,29 +7010,19 @@ nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
|
||||
rv = ResolveStyleContext(aPresContext, aParentFrame, aContent, tag, getter_AddRefs(styleContext));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Pre-check for display "none" - if we find that, don't create
|
||||
// any frame at all
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
styleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
|
||||
aState.mFrameManager->SetUndisplayedContent(aContent, styleContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRInt32 nameSpaceID;
|
||||
aContent->GetNameSpaceID(nameSpaceID);
|
||||
rv = ConstructFrameInternal(aPresShell,
|
||||
aPresContext,
|
||||
aState,
|
||||
aContent,
|
||||
aParentFrame,
|
||||
tag,
|
||||
nameSpaceID,
|
||||
styleContext,
|
||||
aFrameItems,
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
PRInt32 nameSpaceID;
|
||||
aContent->GetNameSpaceID(nameSpaceID);
|
||||
rv = ConstructFrameInternal(aPresShell,
|
||||
aPresContext,
|
||||
aState,
|
||||
aContent,
|
||||
aParentFrame,
|
||||
tag,
|
||||
nameSpaceID,
|
||||
styleContext,
|
||||
aFrameItems,
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -7216,13 +7041,8 @@ nsCSSFrameConstructor::ConstructFrameInternal( nsIPresShell* aPresShe
|
||||
nsFrameItems& aFrameItems,
|
||||
PRBool aXBLBaseTag)
|
||||
{
|
||||
#ifdef DEBUG_hyatt
|
||||
if (aTag == nsXULAtoms::menulist) {
|
||||
printf("moo!");
|
||||
}
|
||||
#endif /* DEBUG_hyatt */
|
||||
// The following code allows the user to specify the base tag
|
||||
// of a XUL object using XBL. XUL objects (like boxes, menus, etc.)
|
||||
// of an element using XBL. XUL and HTML objects (like boxes, menus, etc.)
|
||||
// can then be extended arbitrarily.
|
||||
nsCOMPtr<nsIStyleContext> styleContext(do_QueryInterface(aStyleContext));
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
@ -7278,6 +7098,15 @@ nsCSSFrameConstructor::ConstructFrameInternal( nsIPresShell* aPresShe
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-check for display "none" - if we find that, don't create
|
||||
// any frame at all
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
styleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
|
||||
aState.mFrameManager->SetUndisplayedContent(aContent, styleContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame* lastChild = aFrameItems.lastChild;
|
||||
|
||||
@ -11286,11 +11115,11 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresShell* aPresShell,
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
|
||||
aFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
||||
if (aCanHaveGeneratedContent) {
|
||||
// Probe for generated content before
|
||||
nsIFrame* generatedFrame;
|
||||
aFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
if (CreateGeneratedContentFrame(aPresShell, aPresContext, aState, aFrame, aContent,
|
||||
styleContext, nsCSSAtoms::beforePseudo,
|
||||
aParentIsBlock, &generatedFrame)) {
|
||||
@ -11310,19 +11139,15 @@ nsCSSFrameConstructor::ProcessChildren(nsIPresShell* aPresShell,
|
||||
nsPseudoFrames priorPseudoFrames;
|
||||
aState.mPseudoFrames.Reset(&priorPseudoFrames);
|
||||
|
||||
// Iterate the child content objects and construct frames
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) {
|
||||
// Construct a child frame
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
// process the current pseudo frame state
|
||||
if (!aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aFrameItems);
|
||||
@ -12471,17 +12296,14 @@ nsCSSFrameConstructor::ProcessBlockChildren(nsIPresShell* aPresShell,
|
||||
}
|
||||
|
||||
// Iterate the child content objects and construct frames
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) {
|
||||
// Construct a child frame
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
// Construct a child frame
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
// process pseudo frames if necessary
|
||||
@ -12763,36 +12585,34 @@ nsCSSFrameConstructor::ProcessInlineChildren(nsIPresShell* aPresShell,
|
||||
|
||||
// Iterate the child content objects and construct frames
|
||||
PRBool allKidsInline = PR_TRUE;
|
||||
PRInt32 count;
|
||||
aContent->ChildCount(count);
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
ChildIterator iterator(aContent);
|
||||
while (iterator.HasMoreChildren()) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
if (NS_SUCCEEDED(aContent->ChildAt(i, *getter_AddRefs(childContent)))) {
|
||||
// Construct a child frame
|
||||
nsIFrame* oldLastChild = aFrameItems.lastChild;
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
iterator.NextChild(getter_AddRefs(childContent));
|
||||
// Construct a child frame
|
||||
nsIFrame* oldLastChild = aFrameItems.lastChild;
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, childContent, aFrame, aFrameItems);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Examine newly added children (we may have added more than one
|
||||
// child if the child was another inline frame that ends up
|
||||
// being carved in 3 pieces) to maintain the allKidsInline flag.
|
||||
if (allKidsInline) {
|
||||
nsIFrame* kid;
|
||||
if (oldLastChild) {
|
||||
oldLastChild->GetNextSibling(&kid);
|
||||
}
|
||||
else {
|
||||
kid = aFrameItems.childList;
|
||||
}
|
||||
while (kid) {
|
||||
if (!IsInlineFrame(kid)) {
|
||||
allKidsInline = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
kid->GetNextSibling(&kid);
|
||||
// Examine newly added children (we may have added more than one
|
||||
// child if the child was another inline frame that ends up
|
||||
// being carved in 3 pieces) to maintain the allKidsInline flag.
|
||||
if (allKidsInline) {
|
||||
nsIFrame* kid;
|
||||
if (oldLastChild) {
|
||||
oldLastChild->GetNextSibling(&kid);
|
||||
}
|
||||
else {
|
||||
kid = aFrameItems.childList;
|
||||
}
|
||||
while (kid) {
|
||||
if (!IsInlineFrame(kid)) {
|
||||
allKidsInline = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
kid->GetNextSibling(&kid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ struct nsStyleDisplay;
|
||||
class nsIPresShell;
|
||||
class nsVoidArray;
|
||||
class nsIFrameManager;
|
||||
|
||||
class nsFrameConstructorState;
|
||||
class nsIDOMHTMLSelectElement;
|
||||
class nsIXBLService;
|
||||
|
||||
class nsCSSFrameConstructor : public nsIStyleFrameConstruction {
|
||||
public:
|
||||
@ -524,15 +524,6 @@ protected:
|
||||
nsIFrame* aNewFrame,
|
||||
nsFrameItems& aChildItems);
|
||||
|
||||
nsresult CreateAnonymousTableCellFrames(nsIPresShell* aPresShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIAtom* aTag,
|
||||
nsFrameConstructorState& aState,
|
||||
nsIContent* aParent,
|
||||
nsIFrame* aNewCellBodyFrame,
|
||||
nsIFrame* aNewCellFrame,
|
||||
nsFrameItems& aChildItems);
|
||||
|
||||
//MathML Mod - RBS
|
||||
#ifdef MOZ_MATHML
|
||||
nsresult ConstructMathMLFrame(nsIPresShell* aPresShell,
|
||||
@ -954,12 +945,12 @@ protected:
|
||||
PRBool mGotGfxPrefs;
|
||||
PRBool mHasGfxScrollbars;
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRBool mVerifyFastFindFrame; // if true, run both the old and new find frame code
|
||||
// to validate that both ways get the same answer
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
|
||||
};
|
||||
|
||||
#endif /* nsCSSFrameConstructor_h___ */
|
||||
|
@ -33,6 +33,7 @@ EXPORTS = \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLBindingAttachedHandler.h \
|
||||
nsIXBLDocumentInfo.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLPrototypeBinding.h \
|
||||
nsIXBLPrototypeHandler.h \
|
||||
nsIXBLService.h \
|
||||
|
@ -2,6 +2,7 @@ nsIBindingManager.h
|
||||
nsIXBLBinding.h
|
||||
nsIXBLBindingAttachedHandler.h
|
||||
nsIXBLDocumentInfo.h
|
||||
nsIXBLInsertionPoint.h
|
||||
nsIXBLPrototypeBinding.h
|
||||
nsIXBLPrototypeHandler.h
|
||||
nsIXBLService.h
|
||||
|
@ -26,6 +26,7 @@ EXPORTS = \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLBindingAttachedHandler.h \
|
||||
nsIXBLDocumentInfo.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLPrototypeBinding.h \
|
||||
nsIXBLPrototypeHandler.h \
|
||||
nsIXBLService.h \
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult) = 0;
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionParent(nsIContent* aContent, nsIContent** aResult)=0;
|
||||
NS_IMETHOD SetInsertionParent(nsIContent* aContent, nsIContent* aResult)=0;
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult) = 0;
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult) = 0;
|
||||
|
||||
@ -79,8 +82,15 @@ public:
|
||||
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult,
|
||||
// For a given element with an insertion point child, returns a flat list of all the real children.
|
||||
NS_IMETHOD GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
NS_IMETHOD SetContentListFor(nsIContent* aContent, nsISupportsArray* aList)=0;
|
||||
|
||||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList) = 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;
|
||||
|
||||
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsAReadableString& aURL) = 0;
|
||||
|
@ -85,8 +85,10 @@ public:
|
||||
NS_IMETHOD GetDocURI(nsCString& aResult) = 0;
|
||||
NS_IMETHOD GetID(nsCString& aResult) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRBool* aMultipleInsertionPoints) = 0;
|
||||
NS_IMETHOD GetInsertionPointsFor(nsIContent* aParent, nsISupportsArray** aResult)=0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints) = 0;
|
||||
|
||||
NS_IMETHOD IsStyleBinding(PRBool* aResult) = 0;
|
||||
NS_IMETHOD SetIsStyleBinding(PRBool aIsStyle) = 0;
|
||||
@ -102,8 +104,7 @@ public:
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult,
|
||||
nsIContent** aParent, PRBool* aMultipleInsertionPoints)=0;
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult)=0;
|
||||
};
|
||||
|
@ -32,6 +32,7 @@ class nsIDocument;
|
||||
class nsIDOMEventReceiver;
|
||||
class nsIXBLDocumentInfo;
|
||||
class nsIXBLPrototypeHandler;
|
||||
class nsIXBLBinding;
|
||||
|
||||
// {34D700F5-C1A2-4408-A0B1-DD8F891DD1FE}
|
||||
#define NS_IXBLPROTOTYPEBINDING_IID \
|
||||
@ -76,11 +77,13 @@ public:
|
||||
|
||||
NS_IMETHOD HasInsertionPoints(PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD InstantiateInsertionPoints(nsIXBLBinding* aBinding)=0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent* aChild, nsIContent** aResult)=0;
|
||||
nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)=0;
|
||||
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent** aResult, PRBool* aMultipleInsertionPoints)=0;
|
||||
nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints)=0;
|
||||
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag)=0;
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag)=0;
|
||||
|
@ -64,11 +64,6 @@ public:
|
||||
// Indicates whether or not a binding is fully loaded.
|
||||
NS_IMETHOD BindingReady(nsIContent* aBoundElement, const nsCString& aURLStr, PRBool* aIsReady) = 0;
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsIDOMNodeList** aResult, nsIContent** aChildElement,
|
||||
PRBool* aMultipleInsertionPoints) = 0;
|
||||
|
||||
// Retrieves our base class (e.g., tells us what type of frame and content node to build)
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult) = 0;
|
||||
|
||||
|
@ -50,6 +50,7 @@ CPPSRCS = \
|
||||
nsXBLScrollHandler.cpp \
|
||||
nsXBLService.cpp \
|
||||
nsBindingManager.cpp \
|
||||
nsXBLInsertionPoint \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
@ -46,6 +46,7 @@ CPPSRCS= \
|
||||
nsXBLLoadHandler.cpp \
|
||||
nsXBLPrototypeHandler.cpp \
|
||||
nsBindingManager.cpp \
|
||||
nsXBLInsertionPoint.cpp \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS= \
|
||||
@ -68,6 +69,7 @@ CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsXBLPrototypeHandler.obj \
|
||||
.\$(OBJDIR)\nsXBLService.obj \
|
||||
.\$(OBJDIR)\nsBindingManager.obj \
|
||||
.\$(OBJDIR)\nsXBLInsertionPoint.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsIXBLBinding.h"
|
||||
#include "nsIXBLDocumentInfo.h"
|
||||
#include "nsIXBLBindingAttachedHandler.h"
|
||||
#include "nsIXBLInsertionPoint.h"
|
||||
|
||||
#include "nsIStyleSheet.h"
|
||||
#include "nsIHTMLStyleSheet.h"
|
||||
@ -191,6 +192,89 @@ nsresult NS_NewXBLDocumentInfo(nsIDocument* aDocument, nsIXBLDocumentInfo** aRes
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// = nsAnonymousContentList
|
||||
// ==================================================================
|
||||
|
||||
class nsAnonymousContentList : public nsGenericDOMNodeList
|
||||
{
|
||||
public:
|
||||
nsAnonymousContentList(nsISupportsArray* aElements);
|
||||
virtual ~nsAnonymousContentList();
|
||||
|
||||
// nsIDOMNodeList interface
|
||||
NS_DECL_IDOMNODELIST
|
||||
|
||||
private:
|
||||
nsISupportsArray* mElements;
|
||||
};
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsAnonymousContentList);
|
||||
|
||||
nsAnonymousContentList::nsAnonymousContentList(nsISupportsArray* aElements)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAnonymousContentList);
|
||||
|
||||
// We don't reference count our Anonymous reference (to avoid circular
|
||||
// references). We'll be told when the Anonymous goes away.
|
||||
mElements = aElements;
|
||||
NS_IF_ADDREF(mElements);
|
||||
}
|
||||
|
||||
nsAnonymousContentList::~nsAnonymousContentList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsAnonymousContentList);
|
||||
NS_IF_RELEASE(mElements);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::GetLength(PRUint32* aLength)
|
||||
{
|
||||
NS_ASSERTION(aLength != nsnull, "null ptr");
|
||||
if (! aLength)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRUint32 cnt;
|
||||
mElements->Count(&cnt);
|
||||
|
||||
*aLength = 0;
|
||||
nsCOMPtr<nsIXBLInsertionPoint> point;
|
||||
PRUint32 l;
|
||||
for (PRUint32 i = 0; i < cnt; i++) {
|
||||
point = getter_AddRefs((nsIXBLInsertionPoint*)(mElements->ElementAt(i)));
|
||||
point->ChildCount(&l);
|
||||
*aLength += l;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnonymousContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
||||
{
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mElements->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 pointCount = 0;
|
||||
nsCOMPtr<nsIXBLInsertionPoint> point;
|
||||
for (PRUint32 i = 0; i < cnt; i++) {
|
||||
aIndex -= pointCount;
|
||||
|
||||
point = getter_AddRefs((nsIXBLInsertionPoint*)(mElements->ElementAt(i)));
|
||||
point->ChildCount(&pointCount);
|
||||
|
||||
if (aIndex < pointCount) {
|
||||
nsCOMPtr<nsIContent> result;
|
||||
rv = point->ChildAt(aIndex, getter_AddRefs(result));
|
||||
if (result && NS_SUCCEEDED(rv))
|
||||
return result->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)aReturn);
|
||||
else return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -205,6 +289,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult);
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding);
|
||||
|
||||
NS_IMETHOD GetInsertionParent(nsIContent* aContent, nsIContent** aResult);
|
||||
NS_IMETHOD SetInsertionParent(nsIContent* aContent, nsIContent* aResult);
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult);
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult);
|
||||
|
||||
@ -213,8 +300,14 @@ public:
|
||||
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult,
|
||||
NS_IMETHOD GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
NS_IMETHOD SetContentListFor(nsIContent* aContent, nsISupportsArray* aList);
|
||||
|
||||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints);
|
||||
|
||||
NS_IMETHOD AddLayeredBinding(nsIContent* aContent, const nsAReadableString& aURL);
|
||||
@ -258,11 +351,43 @@ protected:
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
// A mapping from nsIContent* to the nsIXBLBinding* that is installed on that element.
|
||||
nsSupportsHashtable* mBindingTable;
|
||||
|
||||
// A mapping from nsIContent* to an nsIDOMNodeList* (nsAnonymousContentList*).
|
||||
// This list contains an accurate reflection of our *explicit* children (once intermingled with
|
||||
// insertion points) in the altered DOM.
|
||||
nsSupportsHashtable* mContentListTable;
|
||||
|
||||
// A mapping from nsIContent* to an nsIDOMNodeList* (nsAnonymousContentList*).
|
||||
// This list contains an accurate reflection of our *anonymous* children (if and only if they are
|
||||
// intermingled with insertion points) in the altered DOM. This table is not used
|
||||
// if no insertion points were defined directly underneath a <content> tag in a
|
||||
// binding. The NodeList from the <content> is used instead as a performance
|
||||
// optimization.
|
||||
nsSupportsHashtable* mAnonymousNodesTable;
|
||||
|
||||
// A mapping from nsIContent* to nsIContent*. The insertion parent is our one true
|
||||
// parent in the transformed DOM. This gives us a more-or-less O(1) way of obtaining
|
||||
// our transformed parent.
|
||||
nsSupportsHashtable* mInsertionParentTable;
|
||||
|
||||
// A mapping from nsIContent* to nsIXPWrappedJS* (an XPConnect wrapper for JS objects).
|
||||
// For XBL bindings that implement XPIDL interfaces, and that get referred to from C++,
|
||||
// this table caches the XPConnect wrapper for the binding. By caching it, I control
|
||||
// its lifetime, and I prevent a re-wrap of the same script object (in the case where
|
||||
// multiple bindings in an XBL inheritance chain both implement an XPIDL interface).
|
||||
nsSupportsHashtable* mWrapperTable;
|
||||
|
||||
// A mapping from nsIDocument* to nsIXBLDocumentInfo*. This table is the cache of
|
||||
// all binding documents that have been loaded by a given bound document.
|
||||
nsSupportsHashtable* mDocumentTable;
|
||||
|
||||
// The currently loading binding docs. If they're in this table, they have not yet
|
||||
// finished loading.
|
||||
nsSupportsHashtable* mLoadingDocTable;
|
||||
|
||||
// A queue of binding attached event handlers that are awaiting execution.
|
||||
nsCOMPtr<nsISupportsArray> mAttachedQueue;
|
||||
};
|
||||
|
||||
@ -279,6 +404,9 @@ nsBindingManager::nsBindingManager(void)
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mBindingTable = nsnull;
|
||||
mContentListTable = nsnull;
|
||||
mAnonymousNodesTable = nsnull;
|
||||
mInsertionParentTable = nsnull;
|
||||
mWrapperTable = nsnull;
|
||||
mDocumentTable = nsnull;
|
||||
mLoadingDocTable = nsnull;
|
||||
@ -289,6 +417,9 @@ nsBindingManager::nsBindingManager(void)
|
||||
nsBindingManager::~nsBindingManager(void)
|
||||
{
|
||||
delete mBindingTable;
|
||||
delete mContentListTable;
|
||||
delete mAnonymousNodesTable;
|
||||
delete mInsertionParentTable;
|
||||
delete mWrapperTable;
|
||||
delete mDocumentTable;
|
||||
delete mLoadingDocTable;
|
||||
@ -333,6 +464,36 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionParent(nsIContent* aContent, nsIContent** aResult)
|
||||
{
|
||||
if (mInsertionParentTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIContent*, mInsertionParentTable->Get(&key));
|
||||
}
|
||||
else {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetInsertionParent(nsIContent* aContent, nsIContent* aParent)
|
||||
{
|
||||
if (!mInsertionParentTable)
|
||||
mInsertionParentTable = new nsSupportsHashtable;
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aParent) {
|
||||
mInsertionParentTable->Put(&key, aParent);
|
||||
}
|
||||
else
|
||||
mInsertionParentTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult)
|
||||
{
|
||||
@ -383,6 +544,11 @@ nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocum
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out insertion parents and content lists.
|
||||
SetInsertionParent(aContent, nsnull);
|
||||
SetContentListFor(aContent, nsnull);
|
||||
SetAnonymousNodesFor(aContent, nsnull);
|
||||
|
||||
for (PRInt32 i = aOldDocument->GetNumberOfShells() - 1; i >= 0; --i) {
|
||||
nsCOMPtr<nsIPresShell> shell = dont_AddRef( aOldDocument->GetShellAt(i) );
|
||||
NS_ASSERTION(shell != nsnull, "Zoiks! nsIPresShell::ShellAt() broke");
|
||||
@ -434,26 +600,105 @@ nsBindingManager::ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAto
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult)
|
||||
nsBindingManager::GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult)
|
||||
{
|
||||
// Locate the primary binding and get its node list of anonymous children.
|
||||
*aResult = nsnull;
|
||||
|
||||
if (mContentListTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIDOMNodeList*, mContentListTable->Get(&key));
|
||||
}
|
||||
|
||||
if (!*aResult) {
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
|
||||
return node->GetChildNodes(aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetContentListFor(nsIContent* aContent, nsISupportsArray* aList)
|
||||
{
|
||||
if (!mContentListTable) {
|
||||
if (!aList)
|
||||
return NS_OK;
|
||||
mContentListTable = new nsSupportsHashtable;
|
||||
}
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aList) {
|
||||
nsAnonymousContentList* contentList = new nsAnonymousContentList(aList);
|
||||
mContentListTable->Put(&key, (nsIDOMNodeList*)contentList);
|
||||
}
|
||||
else
|
||||
mContentListTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult)
|
||||
{
|
||||
// Locate the primary binding and get its node list of anonymous children.
|
||||
*aResult = nsnull;
|
||||
if (mAnonymousNodesTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIDOMNodeList*, mAnonymousNodesTable->Get(&key));
|
||||
}
|
||||
|
||||
if (!*aResult) {
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aContent, getter_AddRefs(binding));
|
||||
if (binding)
|
||||
return binding->GetAnonymousNodes(aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList)
|
||||
{
|
||||
if (!mAnonymousNodesTable) {
|
||||
if (!aList)
|
||||
return NS_OK;
|
||||
mAnonymousNodesTable = new nsSupportsHashtable;
|
||||
}
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aList) {
|
||||
nsAnonymousContentList* contentList = new nsAnonymousContentList(aList);
|
||||
mAnonymousNodesTable->Put(&key, (nsIDOMNodeList*)contentList);
|
||||
}
|
||||
else
|
||||
mAnonymousNodesTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aParent, getter_AddRefs(binding));
|
||||
|
||||
if (binding)
|
||||
return binding->GetInsertionPoint(aChild, aResult);
|
||||
return binding->GetInsertionPoint(aChild, aResult, aIndex);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult,
|
||||
nsBindingManager::GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aParent, getter_AddRefs(binding));
|
||||
|
||||
if (binding)
|
||||
return binding->GetSingleInsertionPoint( aResult, aMultipleInsertionPoints);
|
||||
return binding->GetSingleInsertionPoint(aResult, aIndex, aMultipleInsertionPoints);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsXBLService.h"
|
||||
#include "nsIXBLInsertionPoint.h"
|
||||
|
||||
// Event listeners
|
||||
#include "nsIEventListenerManager.h"
|
||||
@ -232,6 +233,7 @@ NS_IMPL_ISUPPORTS1(nsXBLBinding, nsIXBLBinding)
|
||||
// Constructors/Destructors
|
||||
nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding* aBinding)
|
||||
: mFirstHandler(nsnull),
|
||||
mInsertionPointTable(nsnull),
|
||||
mIsStyleBinding(PR_TRUE),
|
||||
mMarkedForDeath(PR_FALSE)
|
||||
{
|
||||
@ -277,6 +279,8 @@ nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding* aBinding)
|
||||
|
||||
nsXBLBinding::~nsXBLBinding(void)
|
||||
{
|
||||
delete mInsertionPointTable;
|
||||
|
||||
gRefCnt--;
|
||||
// printf("REF COUNT DOWN: %d %s\n", gRefCnt, (const char*)mID);
|
||||
|
||||
@ -437,6 +441,102 @@ nsXBLBinding::HasStyleSheets(PRBool* aResolveStyle)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct ContentListData {
|
||||
nsXBLBinding* mBinding;
|
||||
nsIBindingManager* mBindingManager;
|
||||
|
||||
ContentListData(nsXBLBinding* aBinding, nsIBindingManager* aManager)
|
||||
:mBinding(aBinding), mBindingManager(aManager)
|
||||
{};
|
||||
};
|
||||
|
||||
PRBool PR_CALLBACK BuildContentLists(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
{
|
||||
ContentListData* data = (ContentListData*)aClosure;
|
||||
nsIBindingManager* bm = data->mBindingManager;
|
||||
nsXBLBinding* binding = data->mBinding;
|
||||
|
||||
nsCOMPtr<nsIContent> boundElement;
|
||||
binding->GetBoundElement(getter_AddRefs(boundElement));
|
||||
|
||||
nsISupportsArray* arr = (nsISupportsArray*)aData;
|
||||
PRUint32 count;
|
||||
arr->Count(&count);
|
||||
|
||||
if (count == 0)
|
||||
return NS_OK;
|
||||
|
||||
// XXX Could this array just be altered in place and passed directly to
|
||||
// SetContentListFor? We'd save space if we could pull this off.
|
||||
nsCOMPtr<nsISupportsArray> contentList;
|
||||
NS_NewISupportsArray(getter_AddRefs(contentList));
|
||||
|
||||
// Figure out the relevant content node.
|
||||
PRUint32 j = 0;
|
||||
nsCOMPtr<nsIXBLInsertionPoint> currPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
PRUint32 currIndex;
|
||||
currPoint->GetInsertionParent(getter_AddRefs(parent));
|
||||
currPoint->GetInsertionIndex(&currIndex);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
||||
if (parent == boundElement) {
|
||||
// We are altering anonymous nodes to accommodate insertion points.
|
||||
binding->GetAnonymousNodes(getter_AddRefs(nodeList));
|
||||
}
|
||||
else {
|
||||
// We are altering the explicit content list of a node to accommodate insertion points.
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(parent));
|
||||
node->GetChildNodes(getter_AddRefs(nodeList));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXBLInsertionPoint> pseudoPoint;
|
||||
PRUint32 childCount;
|
||||
nodeList->GetLength(&childCount);
|
||||
for (PRUint32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nodeList->Item(i, getter_AddRefs(node));
|
||||
nsCOMPtr<nsIContent> child(do_QueryInterface(node));
|
||||
if (i == currIndex) {
|
||||
// Add the currPoint to the supports array.
|
||||
contentList->AppendElement(currPoint);
|
||||
|
||||
// Get the next real insertion point and update our currIndex.
|
||||
j++;
|
||||
if (j < count) {
|
||||
currPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
currPoint->GetInsertionIndex(&currIndex);
|
||||
}
|
||||
|
||||
// Null out our current pseudo-point.
|
||||
pseudoPoint = nsnull;
|
||||
}
|
||||
|
||||
if (!pseudoPoint) {
|
||||
NS_NewXBLInsertionPoint(parent, 0, getter_AddRefs(pseudoPoint));
|
||||
contentList->AppendElement(pseudoPoint);
|
||||
}
|
||||
|
||||
pseudoPoint->AddChild(child);
|
||||
}
|
||||
|
||||
// Add in all the remaining insertion points.
|
||||
for ( ; j < count; j++) {
|
||||
currPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
contentList->AppendElement(currPoint);
|
||||
}
|
||||
|
||||
// Now set the content list using the binding manager,
|
||||
// If the bound element is the parent, then we alter the anonymous node list
|
||||
// instead. This allows us to always maintain two distinct lists should
|
||||
// insertion points be nested into an inner binding.
|
||||
if (parent == boundElement)
|
||||
bm->SetAnonymousNodesFor(parent, contentList);
|
||||
else
|
||||
bm->SetContentListFor(parent, contentList);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
|
||||
{
|
||||
@ -499,6 +599,103 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
|
||||
|
||||
clonedContent = do_QueryInterface(clonedNode);
|
||||
SetAnonymousContent(clonedContent);
|
||||
|
||||
mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
|
||||
|
||||
if (hasInsertionPoints) {
|
||||
// Now check and see if we have a single insertion point
|
||||
// or multiple insertion points.
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
bindingManager->GetContentListFor(mBoundElement, getter_AddRefs(children));
|
||||
|
||||
// Enumerate the prototype binding's insertion table to build
|
||||
// our table of instantiated insertion points.
|
||||
mPrototypeBinding->InstantiateInsertionPoints(this);
|
||||
|
||||
// We now have our insertion point table constructed. We
|
||||
// enumerate this table. For each array of insertion points
|
||||
// bundled under the same content node, we generate a content
|
||||
// list. In the case of the bound element, we generate a new
|
||||
// anonymous node list that will be used in place of the binding's
|
||||
// cached anonymous node list.
|
||||
ContentListData data(this, bindingManager);
|
||||
mInsertionPointTable->Enumerate(BuildContentLists, &data);
|
||||
|
||||
// We need to place the children
|
||||
// at their respective insertion points.
|
||||
nsCOMPtr<nsIContent> singlePoint;
|
||||
PRUint32 index = 0;
|
||||
PRBool multiplePoints = PR_FALSE;
|
||||
GetSingleInsertionPoint(getter_AddRefs(singlePoint), &index, &multiplePoints);
|
||||
|
||||
if (children) {
|
||||
if (multiplePoints) {
|
||||
// We must walk the entire content list in order to determine where
|
||||
// each child belongs.
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRUint32 length;
|
||||
children->GetLength(&length);
|
||||
for (PRUint32 i = 0; i < length; i++) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
content = do_QueryInterface(node);
|
||||
|
||||
// Now determine the insertion point in the prototype table.
|
||||
nsCOMPtr<nsIContent> point;
|
||||
PRUint32 index;
|
||||
GetInsertionPoint(content, getter_AddRefs(point), &index);
|
||||
bindingManager->SetInsertionParent(content, point);
|
||||
|
||||
// Find the correct nsIXBLInsertion point in our table.
|
||||
nsCOMPtr<nsIXBLInsertionPoint> insertionPoint;
|
||||
nsCOMPtr<nsISupportsArray> arr;
|
||||
GetInsertionPointsFor(point, getter_AddRefs(arr));
|
||||
PRUint32 arrCount;
|
||||
arr->Count(&arrCount);
|
||||
for (PRUint32 j = 0; j < arrCount; j++) {
|
||||
insertionPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(j));
|
||||
PRBool matches;
|
||||
insertionPoint->Matches(point, index, &matches);
|
||||
if (matches)
|
||||
break;
|
||||
insertionPoint = nsnull;
|
||||
}
|
||||
|
||||
if (!insertionPoint) {
|
||||
NS_ERROR("Filtered insertion point wasn't properly constructed.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else
|
||||
insertionPoint->AddChild(content);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// All of our children are shunted to this single insertion point.
|
||||
nsCOMPtr<nsISupportsArray> arr;
|
||||
GetInsertionPointsFor(singlePoint, getter_AddRefs(arr));
|
||||
PRUint32 arrCount;
|
||||
arr->Count(&arrCount);
|
||||
nsCOMPtr<nsIXBLInsertionPoint> insertionPoint = getter_AddRefs((nsIXBLInsertionPoint*)arr->ElementAt(0));
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRUint32 length;
|
||||
children->GetLength(&length);
|
||||
for (PRUint32 i = 0; i < length; i++) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
content = do_QueryInterface(node);
|
||||
bindingManager->SetInsertionParent(content, singlePoint);
|
||||
insertionPoint->AddChild(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always check the content element for potential attributes.
|
||||
@ -529,9 +726,6 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
|
||||
mContent->UnsetAttribute(namespaceID, name, PR_FALSE);
|
||||
}
|
||||
|
||||
if (mContent)
|
||||
mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1407,25 +1601,42 @@ nsXBLBinding::AllowScripts()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetInsertionPoint(nsIContent* aChild, nsIContent** aResult)
|
||||
nsXBLBinding::GetInsertionPointsFor(nsIContent* aParent, nsISupportsArray** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->GetInsertionPoint(mBoundElement, mContent, aChild, aResult);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetInsertionPoint(aChild, aResult);
|
||||
if (!mInsertionPointTable)
|
||||
mInsertionPointTable = new nsSupportsHashtable(4);
|
||||
|
||||
nsISupportsKey key(aParent);
|
||||
*aResult = NS_STATIC_CAST(nsISupportsArray*, mInsertionPointTable->Get(&key));
|
||||
|
||||
if (!*aResult) {
|
||||
NS_NewISupportsArray(aResult);
|
||||
mInsertionPointTable->Put(&key, *aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetSingleInsertionPoint(nsIContent** aResult, PRBool* aMultipleInsertionPoints)
|
||||
nsXBLBinding::GetInsertionPoint(nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->GetInsertionPoint(mBoundElement, mContent, aChild, aResult, aIndex);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetInsertionPoint(aChild, aResult, aIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetSingleInsertionPoint(nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
*aMultipleInsertionPoints = PR_FALSE;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->GetSingleInsertionPoint(mBoundElement, mContent, aResult, aMultipleInsertionPoints);
|
||||
return mPrototypeBinding->GetSingleInsertionPoint(mBoundElement, mContent, aResult, aIndex, aMultipleInsertionPoints);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetSingleInsertionPoint(aResult, aMultipleInsertionPoints);
|
||||
return mNextBinding->GetSingleInsertionPoint(aResult, aIndex, aMultipleInsertionPoints);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1480,16 +1691,15 @@ nsXBLBinding::ImplementsInterface(REFNSIID aIID, PRBool* aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetAnonymousNodes(nsIDOMNodeList** aResult, nsIContent** aParent, PRBool* aMultipleInsertionPoints)
|
||||
nsXBLBinding::GetAnonymousNodes(nsIDOMNodeList** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (mContent) {
|
||||
GetSingleInsertionPoint(aParent, aMultipleInsertionPoints);
|
||||
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mContent));
|
||||
return elt->GetChildNodes(aResult);
|
||||
}
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->GetAnonymousNodes(aResult, aParent, aMultipleInsertionPoints);
|
||||
return mNextBinding->GetAnonymousNodes(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -79,8 +79,10 @@ class nsXBLBinding: public nsIXBLBinding
|
||||
NS_IMETHOD GetDocURI(nsCString& aResult);
|
||||
NS_IMETHOD GetID(nsCString& aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRBool* aMultipleInsertionPoints);
|
||||
NS_IMETHOD GetInsertionPointsFor(nsIContent* aParent, nsISupportsArray** aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent** aResult, PRUint32* aIndex, PRBool* aMultipleInsertionPoints);
|
||||
|
||||
NS_IMETHOD IsStyleBinding(PRBool* aResult) { *aResult = mIsStyleBinding; return NS_OK; };
|
||||
NS_IMETHOD SetIsStyleBinding(PRBool aIsStyle) { mIsStyleBinding = aIsStyle; return NS_OK; };
|
||||
@ -96,7 +98,7 @@ class nsXBLBinding: public nsIXBLBinding
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult);
|
||||
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult, nsIContent** aParent, PRBool* aMultipleInsertionPoints);
|
||||
NS_IMETHOD GetAnonymousNodes(nsIDOMNodeList** aResult);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult);
|
||||
|
||||
@ -172,6 +174,8 @@ protected:
|
||||
|
||||
nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
|
||||
|
||||
nsSupportsHashtable* mInsertionPointTable; // A hash from nsIContent* -> (a sorted array of nsIXBLInsertionPoint*)
|
||||
|
||||
PRPackedBool mIsStyleBinding;
|
||||
PRPackedBool mMarkedForDeath;
|
||||
};
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsINameSpace.h"
|
||||
#include "nsXBLService.h"
|
||||
#include "nsXBLBinding.h"
|
||||
#include "nsIXBLInsertionPoint.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "xptinfo.h"
|
||||
@ -108,6 +109,59 @@ public:
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXBLAttributeEntry, nsIXBLAttributeEntry)
|
||||
|
||||
// nsIXBLInsertionPointEntry and helpers. This class stores all the necessary
|
||||
// info to figure out the position of an insertion point.
|
||||
|
||||
// {76F238AE-5ACB-49e6-B2DE-FD1940637753}
|
||||
#define NS_IXBLINS_IID \
|
||||
{ 0x76f238ae, 0x5acb, 0x49e6, { 0xb2, 0xde, 0xfd, 0x19, 0x40, 0x63, 0x77, 0x53 } }
|
||||
|
||||
class nsIXBLInsertionPointEntry : public nsISupports {
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IXBLINS_IID; return iid; }
|
||||
|
||||
NS_IMETHOD GetInsertionParent(nsIContent** aResult)=0;
|
||||
|
||||
NS_IMETHOD GetInsertionIndex(PRUint32* aResult)=0;
|
||||
NS_IMETHOD SetInsertionIndex(PRUint32 aIndex)=0;
|
||||
};
|
||||
|
||||
class nsXBLInsertionPointEntry : public nsIXBLInsertionPointEntry {
|
||||
public:
|
||||
NS_IMETHOD GetInsertionParent(nsIContent** aResult)
|
||||
{
|
||||
*aResult = mInsertionParent;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHOD GetInsertionIndex(PRUint32* aResult) { *aResult = mInsertionIndex; return NS_OK; };
|
||||
NS_IMETHOD SetInsertionIndex(PRUint32 aIndex) { mInsertionIndex = aIndex; return NS_OK; };
|
||||
|
||||
nsCOMPtr<nsIContent> mInsertionParent;
|
||||
PRUint32 mInsertionIndex;
|
||||
|
||||
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
|
||||
return aAllocator.Alloc(aSize);
|
||||
}
|
||||
|
||||
static void operator delete(void* aPtr, size_t aSize) {
|
||||
nsFixedSizeAllocator::Free(aPtr, aSize);
|
||||
}
|
||||
|
||||
nsXBLInsertionPointEntry(nsIContent* aParent) {
|
||||
NS_INIT_REFCNT();
|
||||
mInsertionIndex = 0;
|
||||
mInsertionParent = aParent;
|
||||
};
|
||||
|
||||
virtual ~nsXBLInsertionPointEntry() {};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXBLInsertionPointEntry, nsIXBLInsertionPointEntry)
|
||||
|
||||
// =============================================================================
|
||||
|
||||
// Static initialization
|
||||
@ -123,15 +177,24 @@ nsIAtom* nsXBLPrototypeBinding::kValueAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kXBLTextAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementationAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementsAtom = nsnull;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kPool;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kAttrPool;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kInsPool;
|
||||
|
||||
static const size_t kBucketSizes[] = {
|
||||
static const PRInt32 kNumElements = 128;
|
||||
|
||||
static const size_t kAttrBucketSizes[] = {
|
||||
sizeof(nsXBLAttributeEntry)
|
||||
};
|
||||
|
||||
static const PRInt32 kNumBuckets = sizeof(kBucketSizes)/sizeof(size_t);
|
||||
static const PRInt32 kNumElements = 128;
|
||||
static const PRInt32 kInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLAttributeEntry))) * kNumElements;
|
||||
static const PRInt32 kAttrNumBuckets = sizeof(kAttrBucketSizes)/sizeof(size_t);
|
||||
static const PRInt32 kAttrInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLAttributeEntry))) * kNumElements;
|
||||
|
||||
static const size_t kInsBucketSizes[] = {
|
||||
sizeof(nsXBLInsertionPointEntry)
|
||||
};
|
||||
|
||||
static const PRInt32 kInsNumBuckets = sizeof(kInsBucketSizes)/sizeof(size_t);
|
||||
static const PRInt32 kInsInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLInsertionPointEntry))) * kNumElements;
|
||||
|
||||
// Implementation /////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -156,7 +219,8 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
// printf("REF COUNT UP: %d %s\n", gRefCnt, (const char*)mID);
|
||||
|
||||
if (gRefCnt == 1) {
|
||||
kPool.Init("XBL Attribute Entries", kBucketSizes, kNumBuckets, kInitialSize);
|
||||
kAttrPool.Init("XBL Attribute Entries", kAttrBucketSizes, kAttrNumBuckets, kAttrInitialSize);
|
||||
kInsPool.Init("XBL Insertion Point Entries", kInsBucketSizes, kInsNumBuckets, kInsInitialSize);
|
||||
|
||||
kInheritStyleAtom = NS_NewAtom("inheritstyle");
|
||||
kHandlersAtom = NS_NewAtom("handlers");
|
||||
@ -466,31 +530,107 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct InsertionData {
|
||||
nsIXBLBinding* mBinding;
|
||||
nsXBLPrototypeBinding* mPrototype;
|
||||
|
||||
InsertionData(nsIXBLBinding* aBinding,
|
||||
nsXBLPrototypeBinding* aPrototype)
|
||||
:mBinding(aBinding), mPrototype(aPrototype) {};
|
||||
};
|
||||
|
||||
PRBool PR_CALLBACK InstantiateInsertionPoint(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
{
|
||||
nsIXBLInsertionPointEntry* entry = (nsIXBLInsertionPointEntry*)aData;
|
||||
InsertionData* data = (InsertionData*)aClosure;
|
||||
nsIXBLBinding* binding = data->mBinding;
|
||||
nsXBLPrototypeBinding* proto = data->mPrototype;
|
||||
|
||||
// Get the insertion parent.
|
||||
nsCOMPtr<nsIContent> content;
|
||||
entry->GetInsertionParent(getter_AddRefs(content));
|
||||
PRUint32 index;
|
||||
entry->GetInsertionIndex(&index);
|
||||
|
||||
// Locate the real content.
|
||||
nsCOMPtr<nsIContent> realContent;
|
||||
nsCOMPtr<nsIContent> instanceRoot;
|
||||
binding->GetAnonymousContent(getter_AddRefs(instanceRoot));
|
||||
nsCOMPtr<nsIContent> templRoot;
|
||||
proto->GetImmediateChild(nsXBLPrototypeBinding::kContentAtom, getter_AddRefs(templRoot));
|
||||
proto->LocateInstance(templRoot, instanceRoot, content, getter_AddRefs(realContent));
|
||||
if (!realContent)
|
||||
binding->GetBoundElement(getter_AddRefs(realContent));
|
||||
|
||||
// Now that we have the real content, look it up in our table.
|
||||
nsCOMPtr<nsISupportsArray> points;
|
||||
binding->GetInsertionPointsFor(realContent, getter_AddRefs(points));
|
||||
nsCOMPtr<nsIXBLInsertionPoint> insertionPoint;
|
||||
PRUint32 count;
|
||||
points->Count(&count);
|
||||
PRUint32 i = 0, currIndex = 0;
|
||||
for ( ; i < count; i++) {
|
||||
nsCOMPtr<nsIXBLInsertionPoint> currPoint = getter_AddRefs((nsIXBLInsertionPoint*)points->ElementAt(i));
|
||||
currPoint->GetInsertionIndex(&currIndex);
|
||||
if (currIndex == index) {
|
||||
// This is a match. Break out of the loop and set our variable.
|
||||
insertionPoint = currPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
if (currIndex > index)
|
||||
// There was no match. Break.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!insertionPoint) {
|
||||
// We need to make a new insertion point.
|
||||
NS_NewXBLInsertionPoint(realContent, index, getter_AddRefs(insertionPoint));
|
||||
points->InsertElementAt(insertionPoint, i);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::InstantiateInsertionPoints(nsIXBLBinding* aBinding)
|
||||
{
|
||||
InsertionData data(aBinding, this);
|
||||
if (mInsertionPointTable)
|
||||
mInsertionPointTable->Enumerate(InstantiateInsertionPoint, &data);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent* aChild, nsIContent** aResult)
|
||||
nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
if (mInsertionPointTable) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aChild->GetTag(*getter_AddRefs(tag));
|
||||
nsISupportsKey key(tag);
|
||||
nsCOMPtr<nsIContent> content = getter_AddRefs(NS_STATIC_CAST(nsIContent*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
if (!content) {
|
||||
nsCOMPtr<nsIXBLInsertionPointEntry> entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
if (!entry) {
|
||||
nsISupportsKey key2(kChildrenAtom);
|
||||
content = getter_AddRefs(NS_STATIC_CAST(nsIContent*, mInsertionPointTable->Get(&key2)));
|
||||
entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*, mInsertionPointTable->Get(&key2)));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> realContent;
|
||||
if (content) {
|
||||
if (entry) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
entry->GetInsertionParent(getter_AddRefs(content));
|
||||
entry->GetInsertionIndex(aIndex);
|
||||
nsCOMPtr<nsIContent> templContent;
|
||||
GetImmediateChild(kContentAtom, getter_AddRefs(templContent));
|
||||
LocateInstance(templContent, aCopyRoot, content, getter_AddRefs(realContent));
|
||||
}
|
||||
|
||||
if (realContent)
|
||||
*aResult = realContent;
|
||||
else
|
||||
*aResult = aBoundElement;
|
||||
|
||||
NS_IF_ADDREF(*aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
@ -499,15 +639,19 @@ nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement, nsIContent*
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement,
|
||||
nsIContent* aCopyRoot,
|
||||
nsIContent** aResult, PRBool* aMultipleInsertionPoints)
|
||||
nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
if (mInsertionPointTable) {
|
||||
if(mInsertionPointTable->Count() == 1) {
|
||||
nsISupportsKey key(kChildrenAtom);
|
||||
nsCOMPtr<nsIContent> content = getter_AddRefs(NS_STATIC_CAST(nsIContent*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
nsCOMPtr<nsIXBLInsertionPointEntry> entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*,
|
||||
mInsertionPointTable->Get(&key)));
|
||||
nsCOMPtr<nsIContent> realContent;
|
||||
if (content) {
|
||||
if (entry) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
entry->GetInsertionParent(getter_AddRefs(content));
|
||||
entry->GetInsertionIndex(aIndex);
|
||||
nsCOMPtr<nsIContent> templContent;
|
||||
GetImmediateChild(kContentAtom, getter_AddRefs(templContent));
|
||||
LocateInstance(templContent, aCopyRoot, content, getter_AddRefs(realContent));
|
||||
@ -519,6 +663,7 @@ nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement,
|
||||
// match the filter will just go right underneath the bound element).
|
||||
*aMultipleInsertionPoints = PR_TRUE;
|
||||
*aResult = nsnull;
|
||||
*aIndex = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -527,6 +672,7 @@ nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement,
|
||||
*aResult = realContent;
|
||||
else
|
||||
*aResult = aBoundElement;
|
||||
|
||||
NS_IF_ADDREF(*aResult);
|
||||
}
|
||||
else
|
||||
@ -774,7 +920,7 @@ nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
}
|
||||
|
||||
// Create an XBL attribute entry.
|
||||
nsXBLAttributeEntry* xblAttr = new (kPool) nsXBLAttributeEntry(atom, attribute, aElement);
|
||||
nsXBLAttributeEntry* xblAttr = new (kAttrPool) nsXBLAttributeEntry(atom, attribute, aElement);
|
||||
|
||||
// Now we should see if some element within our anonymous
|
||||
// content is already observing this attribute.
|
||||
@ -826,7 +972,7 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
if (!childrenElements)
|
||||
return;
|
||||
|
||||
mInsertionPointTable = new nsSupportsHashtable;
|
||||
mInsertionPointTable = new nsSupportsHashtable(4);
|
||||
|
||||
PRUint32 count;
|
||||
childrenElements->Count(&count);
|
||||
@ -838,11 +984,15 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
if (child) {
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
child->GetParent(*getter_AddRefs(parent));
|
||||
|
||||
// Create an XBL insertion point entry.
|
||||
nsXBLInsertionPointEntry* xblIns = new (kInsPool) nsXBLInsertionPointEntry(parent);
|
||||
|
||||
nsAutoString includes;
|
||||
child->GetAttribute(kNameSpaceID_None, kIncludesAtom, includes);
|
||||
if (includes.IsEmpty()) {
|
||||
nsISupportsKey key(kChildrenAtom);
|
||||
mInsertionPointTable->Put(&key, parent);
|
||||
mInsertionPointTable->Put(&key, xblIns);
|
||||
}
|
||||
else {
|
||||
// The user specified at least one attribute.
|
||||
@ -860,26 +1010,28 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
atom = getter_AddRefs(NS_NewAtom(tok.GetUnicode()));
|
||||
|
||||
nsISupportsKey key(atom);
|
||||
mInsertionPointTable->Put(&key, parent);
|
||||
mInsertionPointTable->Put(&key, xblIns);
|
||||
|
||||
token = nsCRT::strtok( newStr, ", ", &newStr );
|
||||
}
|
||||
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove the <children> elements.
|
||||
for (i = 0; i < count; i++) {
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
childrenElements->GetElementAt(i, getter_AddRefs(supp));
|
||||
nsCOMPtr<nsIContent> child(do_QueryInterface(supp));
|
||||
if (child) {
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
child->GetParent(*getter_AddRefs(parent));
|
||||
// Compute the index of the <children> element. This index is
|
||||
// equal to the index of the <children> in the template minus the #
|
||||
// of previous insertion point siblings removed. Because our childrenElements
|
||||
// array was built in a DFS that went from left-to-right through siblings,
|
||||
// if we dynamically obtain our index each time, then the removals of previous
|
||||
// siblings will cause the index to adjust (and we won't have to take that into
|
||||
// account explicitly).
|
||||
PRInt32 index;
|
||||
parent->IndexOf(child, index);
|
||||
xblIns->SetInsertionIndex((PRUint32)index);
|
||||
|
||||
// Now remove the <children> element from the template. This ensures that the
|
||||
// binding instantiation will not contain a clone of the <children> element when
|
||||
// it clones the binding template.
|
||||
parent->RemoveChildAt(index, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -75,11 +75,13 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding
|
||||
|
||||
NS_IMETHOD HasInsertionPoints(PRBool* aResult) { *aResult = (mInsertionPointTable != nsnull); return NS_OK; };
|
||||
|
||||
NS_IMETHOD InstantiateInsertionPoints(nsIXBLBinding* aBinding);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent* aChild, nsIContent** aResult);
|
||||
nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aBoundElement, nsIContent* aCopyRoot,
|
||||
nsIContent** aResult, PRBool* aMultiple);
|
||||
nsIContent** aResult, PRUint32* aIndex, PRBool* aMultiple);
|
||||
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag);
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag);
|
||||
@ -107,7 +109,8 @@ public:
|
||||
static nsIAtom* kImplementationAtom;
|
||||
static nsIAtom* kImplementsAtom;
|
||||
|
||||
static nsFixedSizeAllocator kPool;
|
||||
static nsFixedSizeAllocator kAttrPool;
|
||||
static nsFixedSizeAllocator kInsPool;
|
||||
|
||||
// Internal member functions
|
||||
public:
|
||||
|
@ -710,31 +710,6 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsAReadableString& aURL,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::GetContentList(nsIContent* aContent, nsIDOMNodeList** aResult, nsIContent** aParent,
|
||||
PRBool* aMultipleInsertionPoints)
|
||||
{
|
||||
// Locate the primary binding and get the node list from its mContent parent.
|
||||
*aResult = nsnull;
|
||||
*aParent = nsnull;
|
||||
*aMultipleInsertionPoints = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
aContent->GetDocument(*getter_AddRefs(document));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
NS_ASSERTION(document, "no document");
|
||||
if (!document) return NS_ERROR_FAILURE;
|
||||
document->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
bindingManager->GetBinding(aContent, getter_AddRefs(binding));
|
||||
|
||||
binding->GetAnonymousNodes(getter_AddRefs(aResult), aParent, aMultipleInsertionPoints);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::FlushStyleBindings(nsIContent* aContent)
|
||||
{
|
||||
|
@ -65,11 +65,6 @@ class nsXBLService : public nsIXBLService, public nsIObserver, public nsSupports
|
||||
// This function clears out the bindings on a given content node.
|
||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsIDOMNodeList** aResult, nsIContent** aChildElement,
|
||||
PRBool* aMultipleInsertionPoints);
|
||||
|
||||
// Gets the object's base class type.
|
||||
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult);
|
||||
|
||||
|
@ -2899,17 +2899,12 @@ NS_IMETHODIMP
|
||||
nsXULDocument::GetAnonymousNodes(nsIDOMElement* aElement,
|
||||
nsIDOMNodeList** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Use the XBL service to get the anonymous node list.
|
||||
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
|
||||
if (!xblService)
|
||||
return rv;
|
||||
|
||||
PRBool dummy;
|
||||
nsCOMPtr<nsIContent> dummyElt;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return xblService->GetContentList(content, aResult, getter_AddRefs(dummyElt), &dummy);
|
||||
*aResult = nsnull;
|
||||
if (mBindingManager) {
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
return mBindingManager->GetAnonymousNodesFor(content, aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
Loading…
Reference in New Issue
Block a user