зеркало из https://github.com/mozilla/gecko-dev.git
Backing out changes for 39054, which caused several template regressions.
This commit is contained in:
Родитель
b1a810b0aa
Коммит
5cc33330bf
|
@ -89,9 +89,6 @@ public:
|
|||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList) = 0;
|
||||
|
||||
// Encapsulates logic for handling both of above
|
||||
NS_IMETHOD GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints) = 0;
|
||||
|
|
|
@ -348,8 +348,6 @@ public:
|
|||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList);
|
||||
|
||||
NS_IMETHOD GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints);
|
||||
|
@ -782,28 +780,6 @@ nsBindingManager::SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* a
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult)
|
||||
{
|
||||
PRUint32 length;
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
GetAnonymousNodesFor(aContent, aResult);
|
||||
if (*aResult) {
|
||||
(*aResult)->GetLength(&length);
|
||||
if (length == 0)
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
||||
// We may have an altered list of children from XBL insertion points.
|
||||
// If we don't have any anonymous kids, we next check to see if we have
|
||||
// insertion points.
|
||||
if (! *aResult)
|
||||
GetContentListFor(aContent, aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIXMLContent.h"
|
||||
#include "nsIXULContent.h"
|
||||
#include "nsIXULDocument.h"
|
||||
#include "nsIXMLContentSink.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsXMLDocument.h"
|
||||
|
@ -362,9 +361,7 @@ nsXBLBinding::SetAnonymousContent(nsIContent* aParent)
|
|||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
|
||||
mContent->SetDocument(doc, PR_TRUE, AllowScripts());
|
||||
|
||||
nsCOMPtr<nsIXULDocument> xuldoc(do_QueryInterface(doc));
|
||||
|
||||
|
||||
// (2) The children's parent back pointer should not be to this synthetic root
|
||||
// but should instead point to the bound element.
|
||||
PRInt32 childCount;
|
||||
|
@ -374,12 +371,6 @@ nsXBLBinding::SetAnonymousContent(nsIContent* aParent)
|
|||
mContent->ChildAt(i, *getter_AddRefs(child));
|
||||
child->SetParent(mBoundElement);
|
||||
child->SetBindingParent(mBoundElement);
|
||||
|
||||
// To make XUL templates work (and other goodies that happen when
|
||||
// an element is added to a XUL document), we need to notify the
|
||||
// XUL document using its special API.
|
||||
if (xuldoc)
|
||||
xuldoc->AddSubtreeToDocument(child);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1298,25 +1289,9 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
|
|||
nsCOMPtr<nsIContent> anonymous;
|
||||
GetAnonymousContent(getter_AddRefs(anonymous));
|
||||
if (anonymous) {
|
||||
// To make XUL templates work (and other XUL-specific stuff),
|
||||
// we'll need to notify it using its add & remove APIs. Grab the
|
||||
// interface now...
|
||||
nsCOMPtr<nsIXULDocument> xuldoc(do_QueryInterface(aOldDocument));
|
||||
|
||||
if (mIsStyleBinding) {
|
||||
if (mIsStyleBinding)
|
||||
anonymous->SetDocument(nsnull, PR_TRUE, PR_TRUE); // Kill it.
|
||||
if (xuldoc)
|
||||
xuldoc->RemoveSubtreeFromDocument(anonymous);
|
||||
}
|
||||
else {
|
||||
anonymous->SetDocument(aNewDocument, PR_TRUE, AllowScripts()); // Keep it around.
|
||||
if (xuldoc)
|
||||
xuldoc->RemoveSubtreeFromDocument(anonymous);
|
||||
|
||||
xuldoc = do_QueryInterface(aNewDocument);
|
||||
if (xuldoc)
|
||||
xuldoc->AddSubtreeToDocument(anonymous);
|
||||
}
|
||||
else anonymous->SetDocument(aNewDocument, PR_TRUE, AllowScripts()); // Keep it around.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,16 +126,6 @@ public:
|
|||
* Load inline and attribute style sheets
|
||||
*/
|
||||
NS_IMETHOD PrepareStyleSheets(nsIURI* aURI) = 0;
|
||||
|
||||
/**
|
||||
* Notify the XUL document that a subtree has been added
|
||||
*/
|
||||
NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement) = 0;
|
||||
|
||||
/**
|
||||
* Notify the XUL document that a subtree has been removed
|
||||
*/
|
||||
NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement) = 0;
|
||||
};
|
||||
|
||||
// factory functions
|
||||
|
|
|
@ -228,6 +228,8 @@ protected:
|
|||
|
||||
nsresult GetTopNode(nsXULPrototypeNode** aNode);
|
||||
nsresult GetTopChildren(nsVoidArray** aChildren);
|
||||
|
||||
PRBool IsInsideXULTemplate();
|
||||
};
|
||||
|
||||
friend class ContextStack;
|
||||
|
@ -328,6 +330,31 @@ XULContentSinkImpl::ContextStack::GetTopChildren(nsVoidArray** aChildren)
|
|||
}
|
||||
|
||||
|
||||
PRBool
|
||||
XULContentSinkImpl::ContextStack::IsInsideXULTemplate()
|
||||
{
|
||||
if (mDepth) {
|
||||
Entry* entry = mTop;
|
||||
while (entry) {
|
||||
nsXULPrototypeNode* node = entry->mNode;
|
||||
|
||||
if (node->mType == nsXULPrototypeNode::eType_Element) {
|
||||
nsXULPrototypeElement* element =
|
||||
NS_REINTERPRET_CAST(nsXULPrototypeElement*, node);
|
||||
|
||||
if (element->mNodeInfo->Equals(kTemplateAtom,
|
||||
kNameSpaceID_XUL)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
entry = entry->mNext;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -1197,16 +1224,50 @@ XULContentSinkImpl::AddAttributes(const nsIParserNode& aNode, nsXULPrototypeElem
|
|||
nsresult rv;
|
||||
PRInt32 count = aNode.GetAttributeCount();
|
||||
|
||||
PRBool generateIDAttr = PR_FALSE;
|
||||
if (mContextStack.IsInsideXULTemplate()) {
|
||||
// Check for an 'id' attribute. If we're inside a XUL
|
||||
// template, then _everything_ needs to have an ID for the
|
||||
// 'template' attribute hookup.
|
||||
generateIDAttr = PR_TRUE;
|
||||
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
if (aNode.GetKeyAt(i).Equals(NS_LITERAL_STRING("id"))) {
|
||||
generateIDAttr = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create storage for the attributes
|
||||
PRInt32 numattrs = count;
|
||||
if (generateIDAttr)
|
||||
++numattrs;
|
||||
|
||||
nsXULPrototypeAttribute* attrs = nsnull;
|
||||
if (count > 0) {
|
||||
attrs = new nsXULPrototypeAttribute[count];
|
||||
if (numattrs > 0) {
|
||||
attrs = new nsXULPrototypeAttribute[numattrs];
|
||||
if (! attrs)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
aElement->mAttributes = attrs;
|
||||
aElement->mNumAttributes = count;
|
||||
aElement->mNumAttributes = numattrs;
|
||||
|
||||
if (generateIDAttr) {
|
||||
// Deal with generating an ID attribute for stuff inside a XUL
|
||||
// template
|
||||
nsAutoString id; id.AssignWithConversion("$");
|
||||
id.AppendInt(PRInt32(aElement), 16);
|
||||
|
||||
mNodeInfoManager->GetNodeInfo(kIdAtom, nsnull, kNameSpaceID_None,
|
||||
*getter_AddRefs(attrs->mNodeInfo));
|
||||
NS_ENSURE_TRUE(attrs->mNodeInfo, NS_ERROR_FAILURE);
|
||||
|
||||
attrs->mValue.SetValue( id );
|
||||
|
||||
++attrs;
|
||||
}
|
||||
|
||||
// Copy the attributes into the prototype
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
|
|
|
@ -3141,7 +3141,7 @@ nsXULDocument::GetElementsByTagNameNS(const nsAReadableString& aNamespaceURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
nsXULDocument::AddSubtreeToDocument(nsIContent* aElement)
|
||||
{
|
||||
// Do a bunch of work that's necessary when an element gets added
|
||||
|
@ -3194,13 +3194,10 @@ nsXULDocument::AddSubtreeToDocument(nsIContent* aElement)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// 5. See if we need to attach a XUL template to this node
|
||||
CheckTemplateBuilder(aElement);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement)
|
||||
{
|
||||
// Do a bunch of cleanup to remove an element from the XUL
|
||||
|
@ -5048,12 +5045,26 @@ nsXULDocument::ResumeWalk()
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx >= proto->mNumChildren) {
|
||||
// We've processed all of the prototype's children. If
|
||||
// we're in the master prototype, do document-level
|
||||
// hookup. (An overlay will get its document hookup
|
||||
// done when it's successfully resolved.)
|
||||
if (element && (mState == eState_Master))
|
||||
AddSubtreeToDocument(element);
|
||||
if (element && ((mState == eState_Master) || (mContextStack.Depth() > 2))) {
|
||||
// We've processed all of the prototype's children.
|
||||
// Check the element for a 'datasources' attribute, in
|
||||
// which case we'll need to create a template builder
|
||||
// and construct the first 'ply' of elements beneath
|
||||
// it.
|
||||
//
|
||||
// N.B. that we do this -after- all other XUL children
|
||||
// have been created: this ensures that there'll be a
|
||||
// <template> tag available when we try to build that
|
||||
// first ply of generated elements.
|
||||
//
|
||||
// N.B. that we do -not- do this if we are dealing
|
||||
// with an 'overlay element'; that is, an element
|
||||
// in the first ply of an overlay
|
||||
// document. OverlayForwardReference::Merge() will
|
||||
// handle that case.
|
||||
rv = CheckTemplateBuilder(element);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Now pop the context stack back up to the parent
|
||||
// element and continue the prototype walk.
|
||||
|
@ -5087,6 +5098,15 @@ nsXULDocument::ResumeWalk()
|
|||
// ...and append it to the content model.
|
||||
rv = element->AppendChildTo(child, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// ...but only do document-level hookup if we're
|
||||
// in the master document. For an overlay, this
|
||||
// will happend when the overlay is successfully
|
||||
// resolved.
|
||||
if (mState == eState_Master) {
|
||||
rv = AddSubtreeToDocument(child);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We're in the "first ply" of an overlay: the
|
||||
|
@ -5586,19 +5606,6 @@ nsXULDocument::CheckTemplateBuilder(nsIContent* aElement)
|
|||
// one, create and initialize a template builder.
|
||||
nsresult rv;
|
||||
|
||||
// See if the element already has a `database' attribute. If it
|
||||
// does, then the template builder has already been created.
|
||||
//
|
||||
// XXX this approach will crash and burn (well, maybe not _that_
|
||||
// bad) if aElement is not a XUL element.
|
||||
nsCOMPtr<nsIDOMXULElement> xulele = do_QueryInterface(aElement);
|
||||
if (xulele) {
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> ds;
|
||||
xulele->GetDatabase(getter_AddRefs(ds));
|
||||
if (ds)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString datasources;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kDataSourcesAtom, datasources);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -5868,11 +5875,6 @@ nsXULDocument::OverlayForwardReference::Resolve()
|
|||
|
||||
rv = Merge(target, mOverlay);
|
||||
if (NS_FAILED(rv)) return eResolve_Error;
|
||||
|
||||
// Add child and any descendants to the element map
|
||||
rv = mDocument->AddSubtreeToDocument(target);
|
||||
if (NS_FAILED(rv)) return eResolve_Error;
|
||||
|
||||
nsCAutoString idC;
|
||||
idC.AssignWithConversion(id);
|
||||
PR_LOG(gXULLog, PR_LOG_ALWAYS,
|
||||
|
@ -5901,6 +5903,12 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
// XXX - ??? - waterson says this should be moved elsewhere.
|
||||
// This'll get set to PR_TRUE if a new 'datasources' attribute is
|
||||
// set on the element. In which case, we need to add a template
|
||||
// builder.
|
||||
PRBool datasources = PR_FALSE;
|
||||
|
||||
// Merge attributes from the overlay content node to that of the
|
||||
// actual document.
|
||||
PRInt32 attrCount, i;
|
||||
|
@ -5951,6 +5959,11 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
|
|||
|
||||
rv = aTargetNode->SetAttribute(ni, value, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX - ???
|
||||
if (/* ignore namespace && */ attr.get() == kDataSourcesAtom) {
|
||||
datasources = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6029,6 +6042,18 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Add child and any descendants to the element map
|
||||
rv = mDocument->AddSubtreeToDocument(aTargetNode);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (datasources) {
|
||||
// If a new 'datasources' attribute was added via the
|
||||
// overlay, then initialize the <template> builder on the
|
||||
// element.
|
||||
rv = CheckTemplateBuilder(aTargetNode);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -299,9 +299,6 @@ public:
|
|||
NS_IMETHOD SetCurrentPrototype(nsIXULPrototypeDocument* aDocument);
|
||||
NS_IMETHOD SetDocumentURL(nsIURI* anURL);
|
||||
NS_IMETHOD PrepareStyleSheets(nsIURI* anURL);
|
||||
NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement);
|
||||
NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement);
|
||||
|
||||
|
||||
// nsIStreamLoadableDocument interface
|
||||
NS_IMETHOD LoadFromStream(nsIInputStream& xulStream,
|
||||
|
@ -390,6 +387,12 @@ protected:
|
|||
nsresult CloseWidgetItem(nsIContent* aElement);
|
||||
nsresult RebuildWidgetItem(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
AddSubtreeToDocument(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
RemoveSubtreeFromDocument(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
AddElementToMap(nsIContent* aElement);
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@
|
|||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIBindingManager.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIElementFactory.h"
|
||||
#include "nsINameSpace.h"
|
||||
|
@ -81,7 +79,6 @@
|
|||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISecurityCheckedComponent.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsITextContent.h"
|
||||
#include "nsITimer.h"
|
||||
|
@ -109,8 +106,6 @@
|
|||
#include "rdfutil.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "pldhash.h"
|
||||
#include "plhash.h"
|
||||
|
||||
// Return values for EnsureElementHasGenericChild()
|
||||
#define NS_RDF_ELEMENT_GOT_CREATED NS_RDF_NO_VALUE
|
||||
|
@ -2514,7 +2509,6 @@ ContentSupportMap::Get(nsIContent* aElement, Match** aMatch)
|
|||
|
||||
class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
|
||||
public nsIRDFContentModelBuilder,
|
||||
public nsISecurityCheckedComponent,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
|
@ -2529,9 +2523,6 @@ public:
|
|||
// nsIXULTemplateBuilder interface
|
||||
NS_DECL_NSIXULTEMPLATEBUILDER
|
||||
|
||||
// nsISecurityCheckedComponent
|
||||
NS_DECL_NSISECURITYCHECKEDCOMPONENT
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIXULDocument* aDocument);
|
||||
NS_IMETHOD SetDataBase(nsIRDFCompositeDataSource* aDataBase);
|
||||
|
@ -2559,9 +2550,6 @@ public:
|
|||
nsresult
|
||||
GetFlags();
|
||||
|
||||
static PRBool
|
||||
IsTemplateElement(nsIContent* aContent);
|
||||
|
||||
nsresult
|
||||
CompileRules();
|
||||
|
||||
|
@ -2697,7 +2685,7 @@ public:
|
|||
|
||||
nsresult
|
||||
CreateTemplateContents(nsIContent* aElement,
|
||||
nsIContent* aTemplateElement,
|
||||
const nsString& aTemplateID,
|
||||
nsIContent** aContainer,
|
||||
PRInt32* aNewIndexInContainer);
|
||||
|
||||
|
@ -2892,82 +2880,6 @@ protected:
|
|||
};
|
||||
|
||||
friend class ContentTestNode;
|
||||
|
||||
class TemplateMap {
|
||||
protected:
|
||||
struct Entry {
|
||||
PLDHashEntryHdr mHdr;
|
||||
nsIContent* mContent;
|
||||
nsIContent* mTemplate;
|
||||
};
|
||||
|
||||
PLDHashTable mTable;
|
||||
|
||||
void
|
||||
Init() { PL_DHashTableInit(&mTable, PL_DHashGetStubOps(), nsnull, sizeof(Entry), PL_DHASH_MIN_SIZE); }
|
||||
|
||||
void
|
||||
Finish() { PL_DHashTableFinish(&mTable); }
|
||||
|
||||
public:
|
||||
TemplateMap() { Init(); }
|
||||
|
||||
~TemplateMap() { Finish(); }
|
||||
|
||||
void
|
||||
Put(nsIContent* aContent, nsIContent* aTemplate) {
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP)),
|
||||
"aContent already in map");
|
||||
|
||||
Entry* entry =
|
||||
NS_REINTERPRET_CAST(Entry*, PL_DHashTableOperate(&mTable, aContent, PL_DHASH_ADD));
|
||||
|
||||
if (entry) {
|
||||
entry->mContent = aContent;
|
||||
entry->mTemplate = aTemplate;
|
||||
} }
|
||||
|
||||
void
|
||||
Remove(nsIContent* aContent) {
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP)),
|
||||
"aContent not in map");
|
||||
|
||||
PL_DHashTableOperate(&mTable, aContent, PL_DHASH_REMOVE);
|
||||
|
||||
PRInt32 count;
|
||||
|
||||
// If possible, use the special nsIXULContent interface to
|
||||
// "peek" at the child count without accidentally creating
|
||||
// children as a side effect, since we're about to rip 'em
|
||||
// outta the map anyway.
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(aContent);
|
||||
if (xulcontent) {
|
||||
xulcontent->PeekChildCount(count);
|
||||
}
|
||||
else {
|
||||
aContent->ChildCount(count);
|
||||
}
|
||||
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aContent->ChildAt(i, *getter_AddRefs(child));
|
||||
|
||||
Remove(child);
|
||||
} }
|
||||
|
||||
|
||||
void
|
||||
GetTemplateFor(nsIContent* aContent, nsIContent** aResult) {
|
||||
Entry* entry =
|
||||
NS_REINTERPRET_CAST(Entry*, PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP));
|
||||
|
||||
NS_IF_ADDREF(*aResult = entry->mTemplate); }
|
||||
|
||||
void
|
||||
Clear() { Finish(); Init(); }
|
||||
};
|
||||
|
||||
TemplateMap mTemplateMap;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -4285,10 +4197,9 @@ nsXULTemplateBuilder::Init()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsXULTemplateBuilder,
|
||||
NS_IMPL_ISUPPORTS3(nsXULTemplateBuilder,
|
||||
nsIXULTemplateBuilder,
|
||||
nsIRDFContentModelBuilder,
|
||||
nsISecurityCheckedComponent,
|
||||
nsIRDFObserver);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -4566,7 +4477,6 @@ nsXULTemplateBuilder::RebuildContainerInternal(nsIContent* aElement, PRBool aRec
|
|||
if (aElement == mRoot.get()) {
|
||||
// Nuke the content support map and conflict set completely.
|
||||
mContentSupportMap.Clear();
|
||||
mTemplateMap.Clear();
|
||||
mConflictSet.Clear();
|
||||
|
||||
if (aRecompileRules) {
|
||||
|
@ -5633,10 +5543,15 @@ nsXULTemplateBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
*aNewIndexInContainer = indx;
|
||||
}
|
||||
|
||||
// Remember the template kid from which we created the
|
||||
// real kid. This allows us to sync back up with the
|
||||
// template to incrementally build content.
|
||||
mTemplateMap.Put(realKid, tmplKid);
|
||||
// Mark the node with the ID of the template node used to
|
||||
// create this element. This allows us to sync back up
|
||||
// with the template to incrementally build content.
|
||||
nsAutoString templateID;
|
||||
rv = tmplKid->GetAttribute(kNameSpaceID_None, nsXULAtoms::id, templateID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = realKid->SetAttribute(kNameSpaceID_None, nsXULAtoms::Template, templateID, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Copy all attributes from the template to the new
|
||||
// element.
|
||||
|
@ -5925,8 +5840,26 @@ nsXULTemplateBuilder::SynchronizeAll(nsIRDFResource* aSource,
|
|||
if (! IsElementContainedBy(element, parent))
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIContent> templateNode;
|
||||
mTemplateMap.GetTemplateFor(element, getter_AddRefs(templateNode));
|
||||
nsAutoString templateID;
|
||||
rv = element->GetAttribute(kNameSpaceID_None,
|
||||
nsXULAtoms::Template,
|
||||
templateID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc;
|
||||
xulDoc = do_QueryInterface(mDocument);
|
||||
if (! xulDoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement;
|
||||
rv = xulDoc->GetElementById(templateID, getter_AddRefs(domElement));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find template node");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIContent> templateNode = do_QueryInterface(domElement);
|
||||
if (! templateNode)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
|
@ -6056,10 +5989,30 @@ nsXULTemplateBuilder::IsDirectlyContainedBy(nsIContent* aChild, nsIContent* aPar
|
|||
if (! aChild)
|
||||
return PR_FALSE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Every generated element has a "template" attribute that gives
|
||||
// us the ID of the template node that it was created from.
|
||||
nsCOMPtr<nsIContent> tmpl;
|
||||
mTemplateMap.GetTemplateFor(aChild, getter_AddRefs(tmpl));
|
||||
nsAutoString tmplID;
|
||||
rv = aChild->GetAttribute(kNameSpaceID_None, nsXULAtoms::Template, tmplID);
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
return PR_FALSE;
|
||||
|
||||
// We've got the template ID; find the element in the content
|
||||
// model.
|
||||
nsCOMPtr<nsIDOMXULDocument> xuldoc( do_QueryInterface(mDocument) );
|
||||
NS_ASSERTION(xuldoc != nsnull, "not an nsIDOMXULDocument");
|
||||
if (! xuldoc)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> tmplele;
|
||||
xuldoc->GetElementById(tmplID, getter_AddRefs(tmplele));
|
||||
NS_ASSERTION(tmplele != nsnull, "couldn't find template element");
|
||||
if (! tmplele)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> tmpl( do_QueryInterface(tmplele) );
|
||||
NS_ASSERTION(tmpl != nsnull, "not an nsIContent");
|
||||
if (! tmpl)
|
||||
return PR_FALSE;
|
||||
|
||||
|
@ -6149,9 +6102,6 @@ nsXULTemplateBuilder::RemoveMember(nsIContent* aContainerElement,
|
|||
// Remove from the content support map.
|
||||
mContentSupportMap.Remove(child);
|
||||
|
||||
// Remove from the template map
|
||||
mTemplateMap.Remove(child);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_ALWAYS)) {
|
||||
nsCOMPtr<nsIAtom> parentTag;
|
||||
|
@ -6199,6 +6149,7 @@ nsXULTemplateBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
|
|||
// Generate both 1) the template content for the current element,
|
||||
// and 2) recursive subcontent (if the current element refers to a
|
||||
// container resource in the RDF graph).
|
||||
nsresult rv;
|
||||
|
||||
// If we're asked to return the first generated child, then
|
||||
// initialize to "none".
|
||||
|
@ -6209,19 +6160,23 @@ nsXULTemplateBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
|
|||
|
||||
// Create the current resource's contents from the template, if
|
||||
// appropriate
|
||||
nsCOMPtr<nsIContent> tmpl;
|
||||
mTemplateMap.GetTemplateFor(aElement, getter_AddRefs(tmpl));
|
||||
nsAutoString templateID;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, nsXULAtoms::Template, templateID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tmpl)
|
||||
CreateTemplateContents(aElement, tmpl, aContainer, aNewIndexInContainer);
|
||||
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
|
||||
rv = CreateTemplateContents(aElement, templateID, aContainer, aNewIndexInContainer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
gXULUtils->GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
if (resource) {
|
||||
rv = gXULUtils->GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
CreateContainerContents(aElement, resource, PR_FALSE, aContainer, aNewIndexInContainer);
|
||||
rv = CreateContainerContents(aElement, resource, PR_FALSE, aContainer, aNewIndexInContainer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -6336,7 +6291,7 @@ nsXULTemplateBuilder::CreateContainerContents(nsIContent* aElement,
|
|||
|
||||
nsresult
|
||||
nsXULTemplateBuilder::CreateTemplateContents(nsIContent* aElement,
|
||||
nsIContent* aTemplateElement,
|
||||
const nsString& aTemplateID,
|
||||
nsIContent** aContainer,
|
||||
PRInt32* aNewIndexInContainer)
|
||||
{
|
||||
|
@ -6370,6 +6325,14 @@ nsXULTemplateBuilder::CreateTemplateContents(nsIContent* aElement,
|
|||
if (! xulDoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> tmplNode;
|
||||
rv = xulDoc->GetElementById(aTemplateID, getter_AddRefs(tmplNode));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIContent> tmpl = do_QueryInterface(tmplNode);
|
||||
if (! tmpl)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// Crawl up the content model until we find the "resource" element
|
||||
// that spawned this template.
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
|
@ -6389,7 +6352,7 @@ nsXULTemplateBuilder::CreateTemplateContents(nsIContent* aElement,
|
|||
Match* match;
|
||||
mContentSupportMap.Get(element, &match);
|
||||
|
||||
rv = BuildContentFromTemplate(aTemplateElement, aElement, aElement, PR_FALSE, resource, PR_FALSE,
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, aElement, PR_FALSE, resource, PR_FALSE,
|
||||
match, aContainer, aNewIndexInContainer);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -6531,6 +6494,22 @@ nsXULTemplateBuilder::IsElementInWidget(nsIContent* aElement)
|
|||
nsresult
|
||||
nsXULTemplateBuilder::RemoveGeneratedContent(nsIContent* aElement)
|
||||
{
|
||||
// Remove and re-insert the element into the document. This'll
|
||||
// minimize the number of notifications that the layout engine has
|
||||
// to deal with.
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
aElement->GetParent(*getter_AddRefs(parent));
|
||||
|
||||
NS_ASSERTION(parent != nsnull, "huh? no parent!");
|
||||
if (! parent)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
PRInt32 pos;
|
||||
parent->IndexOf(aElement, pos);
|
||||
parent->RemoveChildAt(pos, PR_TRUE);
|
||||
|
||||
#define FAST_REMOVE_GENERATED_CONTENT
|
||||
#ifdef FAST_REMOVE_GENERATED_CONTENT
|
||||
// Keep a queue of "ungenerated" elements that we have to probe
|
||||
// for generated content.
|
||||
nsAutoVoidArray ungenerated;
|
||||
|
@ -6561,19 +6540,23 @@ nsXULTemplateBuilder::RemoveGeneratedContent(nsIContent* aElement)
|
|||
if (tag.get() == nsXULAtoms::Template)
|
||||
continue;
|
||||
|
||||
// If the element is in the template map, then we
|
||||
// If the element has a 'template' attribute, then we
|
||||
// assume it's been generated and nuke it.
|
||||
nsCOMPtr<nsIContent> tmpl;
|
||||
mTemplateMap.GetTemplateFor(child, getter_AddRefs(tmpl));
|
||||
nsAutoString tmplID;
|
||||
child->GetAttribute(kNameSpaceID_None, nsXULAtoms::Template, tmplID);
|
||||
|
||||
if (! tmpl) {
|
||||
// Not in the template map, so this must not have been
|
||||
if (tmplID.Length() == 0) {
|
||||
// No 'template' attribute, so this must not have been
|
||||
// generated. We'll need to examine its kids.
|
||||
ungenerated.AppendElement(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we get here, it's "generated". Bye bye!
|
||||
element->RemoveChildAt(i, PR_TRUE);
|
||||
// If we get here, it's "generated". Bye bye! Remove it
|
||||
// from the content model "quietly", because we'll remove
|
||||
// and re-insert the top-level element into the document
|
||||
// to minimze reflow.
|
||||
element->RemoveChildAt(i, PR_FALSE);
|
||||
child->SetDocument(nsnull, PR_TRUE, PR_TRUE);
|
||||
|
||||
// Remove element from the conflict set.
|
||||
|
@ -6583,12 +6566,31 @@ nsXULTemplateBuilder::RemoveGeneratedContent(nsIContent* aElement)
|
|||
|
||||
// Remove this and any children from the content support map.
|
||||
mContentSupportMap.Remove(child);
|
||||
|
||||
// Remove from the template map
|
||||
mTemplateMap.Remove(child);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Compute the retractions that'll occur when we remove the
|
||||
// element from the conflict set.
|
||||
MatchSet firings, retractions;
|
||||
mConflictSet.Remove(ContentTestNode::Element(aElement), firings, retractions);
|
||||
|
||||
// Removing the generated content, quietly.
|
||||
MatchSet::Iterator last = retractions.Last();
|
||||
for (MatchSet::Iterator match = retractions.First(); match != last; ++match) {
|
||||
Value memberval;
|
||||
match->mAssignments.GetAssignmentFor(match->mRule->GetMemberVariable(), &memberval);
|
||||
|
||||
RemoveMember(aElement, VALUE_TO_IRDFRESOURCE(memberval), PR_FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
aElement->SetDocument(doc, PR_TRUE, PR_TRUE);
|
||||
|
||||
parent->InsertChildAt(aElement, pos, PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -7169,23 +7171,6 @@ nsXULTemplateBuilder::GetFlags()
|
|||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsXULTemplateBuilder::IsTemplateElement(nsIContent* aContent)
|
||||
{
|
||||
PRInt32 nameSpaceID;
|
||||
aContent->GetNameSpaceID(nameSpaceID);
|
||||
|
||||
if (nameSpaceID == nsXULTemplateBuilder::kNameSpaceID_XUL) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContent->GetTag(*getter_AddRefs(tag));
|
||||
|
||||
if (tag.get() == nsXULAtoms::Template)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULTemplateBuilder::CompileRules()
|
||||
|
@ -7235,32 +7220,31 @@ nsXULTemplateBuilder::CompileRules()
|
|||
// If root node has no template attribute, then look for a child
|
||||
// node which is a template tag
|
||||
if (! tmpl) {
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
PRInt32 count;
|
||||
rv = mRoot->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (bindingManager) {
|
||||
nsCOMPtr<nsIDOMNodeList> kids;
|
||||
bindingManager->GetXBLChildNodesFor(mRoot, getter_AddRefs(kids));
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = mRoot->ChildAt(i, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (kids) {
|
||||
PRUint32 length;
|
||||
kids->GetLength(&length);
|
||||
PRInt32 nameSpaceID;
|
||||
rv = child->GetNameSpaceID(nameSpaceID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
kids->Item(i, getter_AddRefs(node));
|
||||
if (! node)
|
||||
continue;
|
||||
if (nameSpaceID != kNameSpaceID_XUL)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIContent> child = do_QueryInterface(node);
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = child->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (IsTemplateElement(child)) {
|
||||
tmpl = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag.get() != nsXULAtoms::Template)
|
||||
continue;
|
||||
|
||||
tmpl = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8131,35 +8115,3 @@ nsXULTemplateBuilder::CompileBinding(Rule* aRule,
|
|||
|
||||
return aRule->AddBinding(svar, pres, ovar);
|
||||
}
|
||||
|
||||
/* string canCreateWrapper (in nsIIDPtr iid); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanCreateWrapper(const nsIID * iid, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -805,9 +805,21 @@ struct ChildIterator
|
|||
doc->GetBindingManager(getter_AddRefs(mBindingManager));
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
mBindingManager->GetXBLChildNodesFor(mContent, getter_AddRefs(mNodes));
|
||||
if (mNodes)
|
||||
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() {
|
||||
|
|
|
@ -805,9 +805,21 @@ struct ChildIterator
|
|||
doc->GetBindingManager(getter_AddRefs(mBindingManager));
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
mBindingManager->GetXBLChildNodesFor(mContent, getter_AddRefs(mNodes));
|
||||
if (mNodes)
|
||||
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() {
|
||||
|
|
|
@ -89,9 +89,6 @@ public:
|
|||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList) = 0;
|
||||
|
||||
// Encapsulates logic for handling both of above
|
||||
NS_IMETHOD GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult) = 0;
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex) = 0;
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints) = 0;
|
||||
|
|
|
@ -348,8 +348,6 @@ public:
|
|||
NS_IMETHOD GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
NS_IMETHOD SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* aList);
|
||||
|
||||
NS_IMETHOD GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult);
|
||||
|
||||
NS_IMETHOD GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex);
|
||||
NS_IMETHOD GetSingleInsertionPoint(nsIContent* aParent, nsIContent** aResult, PRUint32* aIndex,
|
||||
PRBool* aMultipleInsertionPoints);
|
||||
|
@ -782,28 +780,6 @@ nsBindingManager::SetAnonymousNodesFor(nsIContent* aContent, nsISupportsArray* a
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult)
|
||||
{
|
||||
PRUint32 length;
|
||||
|
||||
// Retrieve the anonymous content that we should build.
|
||||
GetAnonymousNodesFor(aContent, aResult);
|
||||
if (*aResult) {
|
||||
(*aResult)->GetLength(&length);
|
||||
if (length == 0)
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
||||
// We may have an altered list of children from XBL insertion points.
|
||||
// If we don't have any anonymous kids, we next check to see if we have
|
||||
// insertion points.
|
||||
if (! *aResult)
|
||||
GetContentListFor(aContent, aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult, PRUint32* aIndex)
|
||||
{
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIXMLContent.h"
|
||||
#include "nsIXULContent.h"
|
||||
#include "nsIXULDocument.h"
|
||||
#include "nsIXMLContentSink.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsXMLDocument.h"
|
||||
|
@ -362,9 +361,7 @@ nsXBLBinding::SetAnonymousContent(nsIContent* aParent)
|
|||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
|
||||
mContent->SetDocument(doc, PR_TRUE, AllowScripts());
|
||||
|
||||
nsCOMPtr<nsIXULDocument> xuldoc(do_QueryInterface(doc));
|
||||
|
||||
|
||||
// (2) The children's parent back pointer should not be to this synthetic root
|
||||
// but should instead point to the bound element.
|
||||
PRInt32 childCount;
|
||||
|
@ -374,12 +371,6 @@ nsXBLBinding::SetAnonymousContent(nsIContent* aParent)
|
|||
mContent->ChildAt(i, *getter_AddRefs(child));
|
||||
child->SetParent(mBoundElement);
|
||||
child->SetBindingParent(mBoundElement);
|
||||
|
||||
// To make XUL templates work (and other goodies that happen when
|
||||
// an element is added to a XUL document), we need to notify the
|
||||
// XUL document using its special API.
|
||||
if (xuldoc)
|
||||
xuldoc->AddSubtreeToDocument(child);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1298,25 +1289,9 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
|
|||
nsCOMPtr<nsIContent> anonymous;
|
||||
GetAnonymousContent(getter_AddRefs(anonymous));
|
||||
if (anonymous) {
|
||||
// To make XUL templates work (and other XUL-specific stuff),
|
||||
// we'll need to notify it using its add & remove APIs. Grab the
|
||||
// interface now...
|
||||
nsCOMPtr<nsIXULDocument> xuldoc(do_QueryInterface(aOldDocument));
|
||||
|
||||
if (mIsStyleBinding) {
|
||||
if (mIsStyleBinding)
|
||||
anonymous->SetDocument(nsnull, PR_TRUE, PR_TRUE); // Kill it.
|
||||
if (xuldoc)
|
||||
xuldoc->RemoveSubtreeFromDocument(anonymous);
|
||||
}
|
||||
else {
|
||||
anonymous->SetDocument(aNewDocument, PR_TRUE, AllowScripts()); // Keep it around.
|
||||
if (xuldoc)
|
||||
xuldoc->RemoveSubtreeFromDocument(anonymous);
|
||||
|
||||
xuldoc = do_QueryInterface(aNewDocument);
|
||||
if (xuldoc)
|
||||
xuldoc->AddSubtreeToDocument(anonymous);
|
||||
}
|
||||
else anonymous->SetDocument(aNewDocument, PR_TRUE, AllowScripts()); // Keep it around.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,16 +126,6 @@ public:
|
|||
* Load inline and attribute style sheets
|
||||
*/
|
||||
NS_IMETHOD PrepareStyleSheets(nsIURI* aURI) = 0;
|
||||
|
||||
/**
|
||||
* Notify the XUL document that a subtree has been added
|
||||
*/
|
||||
NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement) = 0;
|
||||
|
||||
/**
|
||||
* Notify the XUL document that a subtree has been removed
|
||||
*/
|
||||
NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement) = 0;
|
||||
};
|
||||
|
||||
// factory functions
|
||||
|
|
|
@ -228,6 +228,8 @@ protected:
|
|||
|
||||
nsresult GetTopNode(nsXULPrototypeNode** aNode);
|
||||
nsresult GetTopChildren(nsVoidArray** aChildren);
|
||||
|
||||
PRBool IsInsideXULTemplate();
|
||||
};
|
||||
|
||||
friend class ContextStack;
|
||||
|
@ -328,6 +330,31 @@ XULContentSinkImpl::ContextStack::GetTopChildren(nsVoidArray** aChildren)
|
|||
}
|
||||
|
||||
|
||||
PRBool
|
||||
XULContentSinkImpl::ContextStack::IsInsideXULTemplate()
|
||||
{
|
||||
if (mDepth) {
|
||||
Entry* entry = mTop;
|
||||
while (entry) {
|
||||
nsXULPrototypeNode* node = entry->mNode;
|
||||
|
||||
if (node->mType == nsXULPrototypeNode::eType_Element) {
|
||||
nsXULPrototypeElement* element =
|
||||
NS_REINTERPRET_CAST(nsXULPrototypeElement*, node);
|
||||
|
||||
if (element->mNodeInfo->Equals(kTemplateAtom,
|
||||
kNameSpaceID_XUL)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
entry = entry->mNext;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -1197,16 +1224,50 @@ XULContentSinkImpl::AddAttributes(const nsIParserNode& aNode, nsXULPrototypeElem
|
|||
nsresult rv;
|
||||
PRInt32 count = aNode.GetAttributeCount();
|
||||
|
||||
PRBool generateIDAttr = PR_FALSE;
|
||||
if (mContextStack.IsInsideXULTemplate()) {
|
||||
// Check for an 'id' attribute. If we're inside a XUL
|
||||
// template, then _everything_ needs to have an ID for the
|
||||
// 'template' attribute hookup.
|
||||
generateIDAttr = PR_TRUE;
|
||||
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
if (aNode.GetKeyAt(i).Equals(NS_LITERAL_STRING("id"))) {
|
||||
generateIDAttr = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create storage for the attributes
|
||||
PRInt32 numattrs = count;
|
||||
if (generateIDAttr)
|
||||
++numattrs;
|
||||
|
||||
nsXULPrototypeAttribute* attrs = nsnull;
|
||||
if (count > 0) {
|
||||
attrs = new nsXULPrototypeAttribute[count];
|
||||
if (numattrs > 0) {
|
||||
attrs = new nsXULPrototypeAttribute[numattrs];
|
||||
if (! attrs)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
aElement->mAttributes = attrs;
|
||||
aElement->mNumAttributes = count;
|
||||
aElement->mNumAttributes = numattrs;
|
||||
|
||||
if (generateIDAttr) {
|
||||
// Deal with generating an ID attribute for stuff inside a XUL
|
||||
// template
|
||||
nsAutoString id; id.AssignWithConversion("$");
|
||||
id.AppendInt(PRInt32(aElement), 16);
|
||||
|
||||
mNodeInfoManager->GetNodeInfo(kIdAtom, nsnull, kNameSpaceID_None,
|
||||
*getter_AddRefs(attrs->mNodeInfo));
|
||||
NS_ENSURE_TRUE(attrs->mNodeInfo, NS_ERROR_FAILURE);
|
||||
|
||||
attrs->mValue.SetValue( id );
|
||||
|
||||
++attrs;
|
||||
}
|
||||
|
||||
// Copy the attributes into the prototype
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
|
|
|
@ -3141,7 +3141,7 @@ nsXULDocument::GetElementsByTagNameNS(const nsAReadableString& aNamespaceURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
nsXULDocument::AddSubtreeToDocument(nsIContent* aElement)
|
||||
{
|
||||
// Do a bunch of work that's necessary when an element gets added
|
||||
|
@ -3194,13 +3194,10 @@ nsXULDocument::AddSubtreeToDocument(nsIContent* aElement)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// 5. See if we need to attach a XUL template to this node
|
||||
CheckTemplateBuilder(aElement);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement)
|
||||
{
|
||||
// Do a bunch of cleanup to remove an element from the XUL
|
||||
|
@ -5048,12 +5045,26 @@ nsXULDocument::ResumeWalk()
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx >= proto->mNumChildren) {
|
||||
// We've processed all of the prototype's children. If
|
||||
// we're in the master prototype, do document-level
|
||||
// hookup. (An overlay will get its document hookup
|
||||
// done when it's successfully resolved.)
|
||||
if (element && (mState == eState_Master))
|
||||
AddSubtreeToDocument(element);
|
||||
if (element && ((mState == eState_Master) || (mContextStack.Depth() > 2))) {
|
||||
// We've processed all of the prototype's children.
|
||||
// Check the element for a 'datasources' attribute, in
|
||||
// which case we'll need to create a template builder
|
||||
// and construct the first 'ply' of elements beneath
|
||||
// it.
|
||||
//
|
||||
// N.B. that we do this -after- all other XUL children
|
||||
// have been created: this ensures that there'll be a
|
||||
// <template> tag available when we try to build that
|
||||
// first ply of generated elements.
|
||||
//
|
||||
// N.B. that we do -not- do this if we are dealing
|
||||
// with an 'overlay element'; that is, an element
|
||||
// in the first ply of an overlay
|
||||
// document. OverlayForwardReference::Merge() will
|
||||
// handle that case.
|
||||
rv = CheckTemplateBuilder(element);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Now pop the context stack back up to the parent
|
||||
// element and continue the prototype walk.
|
||||
|
@ -5087,6 +5098,15 @@ nsXULDocument::ResumeWalk()
|
|||
// ...and append it to the content model.
|
||||
rv = element->AppendChildTo(child, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// ...but only do document-level hookup if we're
|
||||
// in the master document. For an overlay, this
|
||||
// will happend when the overlay is successfully
|
||||
// resolved.
|
||||
if (mState == eState_Master) {
|
||||
rv = AddSubtreeToDocument(child);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We're in the "first ply" of an overlay: the
|
||||
|
@ -5586,19 +5606,6 @@ nsXULDocument::CheckTemplateBuilder(nsIContent* aElement)
|
|||
// one, create and initialize a template builder.
|
||||
nsresult rv;
|
||||
|
||||
// See if the element already has a `database' attribute. If it
|
||||
// does, then the template builder has already been created.
|
||||
//
|
||||
// XXX this approach will crash and burn (well, maybe not _that_
|
||||
// bad) if aElement is not a XUL element.
|
||||
nsCOMPtr<nsIDOMXULElement> xulele = do_QueryInterface(aElement);
|
||||
if (xulele) {
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> ds;
|
||||
xulele->GetDatabase(getter_AddRefs(ds));
|
||||
if (ds)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString datasources;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kDataSourcesAtom, datasources);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -5868,11 +5875,6 @@ nsXULDocument::OverlayForwardReference::Resolve()
|
|||
|
||||
rv = Merge(target, mOverlay);
|
||||
if (NS_FAILED(rv)) return eResolve_Error;
|
||||
|
||||
// Add child and any descendants to the element map
|
||||
rv = mDocument->AddSubtreeToDocument(target);
|
||||
if (NS_FAILED(rv)) return eResolve_Error;
|
||||
|
||||
nsCAutoString idC;
|
||||
idC.AssignWithConversion(id);
|
||||
PR_LOG(gXULLog, PR_LOG_ALWAYS,
|
||||
|
@ -5901,6 +5903,12 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
// XXX - ??? - waterson says this should be moved elsewhere.
|
||||
// This'll get set to PR_TRUE if a new 'datasources' attribute is
|
||||
// set on the element. In which case, we need to add a template
|
||||
// builder.
|
||||
PRBool datasources = PR_FALSE;
|
||||
|
||||
// Merge attributes from the overlay content node to that of the
|
||||
// actual document.
|
||||
PRInt32 attrCount, i;
|
||||
|
@ -5951,6 +5959,11 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
|
|||
|
||||
rv = aTargetNode->SetAttribute(ni, value, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX - ???
|
||||
if (/* ignore namespace && */ attr.get() == kDataSourcesAtom) {
|
||||
datasources = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6029,6 +6042,18 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Add child and any descendants to the element map
|
||||
rv = mDocument->AddSubtreeToDocument(aTargetNode);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (datasources) {
|
||||
// If a new 'datasources' attribute was added via the
|
||||
// overlay, then initialize the <template> builder on the
|
||||
// element.
|
||||
rv = CheckTemplateBuilder(aTargetNode);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -299,9 +299,6 @@ public:
|
|||
NS_IMETHOD SetCurrentPrototype(nsIXULPrototypeDocument* aDocument);
|
||||
NS_IMETHOD SetDocumentURL(nsIURI* anURL);
|
||||
NS_IMETHOD PrepareStyleSheets(nsIURI* anURL);
|
||||
NS_IMETHOD AddSubtreeToDocument(nsIContent* aElement);
|
||||
NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement);
|
||||
|
||||
|
||||
// nsIStreamLoadableDocument interface
|
||||
NS_IMETHOD LoadFromStream(nsIInputStream& xulStream,
|
||||
|
@ -390,6 +387,12 @@ protected:
|
|||
nsresult CloseWidgetItem(nsIContent* aElement);
|
||||
nsresult RebuildWidgetItem(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
AddSubtreeToDocument(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
RemoveSubtreeFromDocument(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
AddElementToMap(nsIContent* aElement);
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@
|
|||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIBindingManager.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIElementFactory.h"
|
||||
#include "nsINameSpace.h"
|
||||
|
@ -81,7 +79,6 @@
|
|||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISecurityCheckedComponent.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsITextContent.h"
|
||||
#include "nsITimer.h"
|
||||
|
@ -109,8 +106,6 @@
|
|||
#include "rdfutil.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "pldhash.h"
|
||||
#include "plhash.h"
|
||||
|
||||
// Return values for EnsureElementHasGenericChild()
|
||||
#define NS_RDF_ELEMENT_GOT_CREATED NS_RDF_NO_VALUE
|
||||
|
@ -2514,7 +2509,6 @@ ContentSupportMap::Get(nsIContent* aElement, Match** aMatch)
|
|||
|
||||
class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
|
||||
public nsIRDFContentModelBuilder,
|
||||
public nsISecurityCheckedComponent,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
|
@ -2529,9 +2523,6 @@ public:
|
|||
// nsIXULTemplateBuilder interface
|
||||
NS_DECL_NSIXULTEMPLATEBUILDER
|
||||
|
||||
// nsISecurityCheckedComponent
|
||||
NS_DECL_NSISECURITYCHECKEDCOMPONENT
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIXULDocument* aDocument);
|
||||
NS_IMETHOD SetDataBase(nsIRDFCompositeDataSource* aDataBase);
|
||||
|
@ -2559,9 +2550,6 @@ public:
|
|||
nsresult
|
||||
GetFlags();
|
||||
|
||||
static PRBool
|
||||
IsTemplateElement(nsIContent* aContent);
|
||||
|
||||
nsresult
|
||||
CompileRules();
|
||||
|
||||
|
@ -2697,7 +2685,7 @@ public:
|
|||
|
||||
nsresult
|
||||
CreateTemplateContents(nsIContent* aElement,
|
||||
nsIContent* aTemplateElement,
|
||||
const nsString& aTemplateID,
|
||||
nsIContent** aContainer,
|
||||
PRInt32* aNewIndexInContainer);
|
||||
|
||||
|
@ -2892,82 +2880,6 @@ protected:
|
|||
};
|
||||
|
||||
friend class ContentTestNode;
|
||||
|
||||
class TemplateMap {
|
||||
protected:
|
||||
struct Entry {
|
||||
PLDHashEntryHdr mHdr;
|
||||
nsIContent* mContent;
|
||||
nsIContent* mTemplate;
|
||||
};
|
||||
|
||||
PLDHashTable mTable;
|
||||
|
||||
void
|
||||
Init() { PL_DHashTableInit(&mTable, PL_DHashGetStubOps(), nsnull, sizeof(Entry), PL_DHASH_MIN_SIZE); }
|
||||
|
||||
void
|
||||
Finish() { PL_DHashTableFinish(&mTable); }
|
||||
|
||||
public:
|
||||
TemplateMap() { Init(); }
|
||||
|
||||
~TemplateMap() { Finish(); }
|
||||
|
||||
void
|
||||
Put(nsIContent* aContent, nsIContent* aTemplate) {
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP)),
|
||||
"aContent already in map");
|
||||
|
||||
Entry* entry =
|
||||
NS_REINTERPRET_CAST(Entry*, PL_DHashTableOperate(&mTable, aContent, PL_DHASH_ADD));
|
||||
|
||||
if (entry) {
|
||||
entry->mContent = aContent;
|
||||
entry->mTemplate = aTemplate;
|
||||
} }
|
||||
|
||||
void
|
||||
Remove(nsIContent* aContent) {
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP)),
|
||||
"aContent not in map");
|
||||
|
||||
PL_DHashTableOperate(&mTable, aContent, PL_DHASH_REMOVE);
|
||||
|
||||
PRInt32 count;
|
||||
|
||||
// If possible, use the special nsIXULContent interface to
|
||||
// "peek" at the child count without accidentally creating
|
||||
// children as a side effect, since we're about to rip 'em
|
||||
// outta the map anyway.
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(aContent);
|
||||
if (xulcontent) {
|
||||
xulcontent->PeekChildCount(count);
|
||||
}
|
||||
else {
|
||||
aContent->ChildCount(count);
|
||||
}
|
||||
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aContent->ChildAt(i, *getter_AddRefs(child));
|
||||
|
||||
Remove(child);
|
||||
} }
|
||||
|
||||
|
||||
void
|
||||
GetTemplateFor(nsIContent* aContent, nsIContent** aResult) {
|
||||
Entry* entry =
|
||||
NS_REINTERPRET_CAST(Entry*, PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP));
|
||||
|
||||
NS_IF_ADDREF(*aResult = entry->mTemplate); }
|
||||
|
||||
void
|
||||
Clear() { Finish(); Init(); }
|
||||
};
|
||||
|
||||
TemplateMap mTemplateMap;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -4285,10 +4197,9 @@ nsXULTemplateBuilder::Init()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsXULTemplateBuilder,
|
||||
NS_IMPL_ISUPPORTS3(nsXULTemplateBuilder,
|
||||
nsIXULTemplateBuilder,
|
||||
nsIRDFContentModelBuilder,
|
||||
nsISecurityCheckedComponent,
|
||||
nsIRDFObserver);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -4566,7 +4477,6 @@ nsXULTemplateBuilder::RebuildContainerInternal(nsIContent* aElement, PRBool aRec
|
|||
if (aElement == mRoot.get()) {
|
||||
// Nuke the content support map and conflict set completely.
|
||||
mContentSupportMap.Clear();
|
||||
mTemplateMap.Clear();
|
||||
mConflictSet.Clear();
|
||||
|
||||
if (aRecompileRules) {
|
||||
|
@ -5633,10 +5543,15 @@ nsXULTemplateBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
*aNewIndexInContainer = indx;
|
||||
}
|
||||
|
||||
// Remember the template kid from which we created the
|
||||
// real kid. This allows us to sync back up with the
|
||||
// template to incrementally build content.
|
||||
mTemplateMap.Put(realKid, tmplKid);
|
||||
// Mark the node with the ID of the template node used to
|
||||
// create this element. This allows us to sync back up
|
||||
// with the template to incrementally build content.
|
||||
nsAutoString templateID;
|
||||
rv = tmplKid->GetAttribute(kNameSpaceID_None, nsXULAtoms::id, templateID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = realKid->SetAttribute(kNameSpaceID_None, nsXULAtoms::Template, templateID, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Copy all attributes from the template to the new
|
||||
// element.
|
||||
|
@ -5925,8 +5840,26 @@ nsXULTemplateBuilder::SynchronizeAll(nsIRDFResource* aSource,
|
|||
if (! IsElementContainedBy(element, parent))
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIContent> templateNode;
|
||||
mTemplateMap.GetTemplateFor(element, getter_AddRefs(templateNode));
|
||||
nsAutoString templateID;
|
||||
rv = element->GetAttribute(kNameSpaceID_None,
|
||||
nsXULAtoms::Template,
|
||||
templateID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc;
|
||||
xulDoc = do_QueryInterface(mDocument);
|
||||
if (! xulDoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement;
|
||||
rv = xulDoc->GetElementById(templateID, getter_AddRefs(domElement));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find template node");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIContent> templateNode = do_QueryInterface(domElement);
|
||||
if (! templateNode)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
|
@ -6056,10 +5989,30 @@ nsXULTemplateBuilder::IsDirectlyContainedBy(nsIContent* aChild, nsIContent* aPar
|
|||
if (! aChild)
|
||||
return PR_FALSE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Every generated element has a "template" attribute that gives
|
||||
// us the ID of the template node that it was created from.
|
||||
nsCOMPtr<nsIContent> tmpl;
|
||||
mTemplateMap.GetTemplateFor(aChild, getter_AddRefs(tmpl));
|
||||
nsAutoString tmplID;
|
||||
rv = aChild->GetAttribute(kNameSpaceID_None, nsXULAtoms::Template, tmplID);
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
return PR_FALSE;
|
||||
|
||||
// We've got the template ID; find the element in the content
|
||||
// model.
|
||||
nsCOMPtr<nsIDOMXULDocument> xuldoc( do_QueryInterface(mDocument) );
|
||||
NS_ASSERTION(xuldoc != nsnull, "not an nsIDOMXULDocument");
|
||||
if (! xuldoc)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> tmplele;
|
||||
xuldoc->GetElementById(tmplID, getter_AddRefs(tmplele));
|
||||
NS_ASSERTION(tmplele != nsnull, "couldn't find template element");
|
||||
if (! tmplele)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> tmpl( do_QueryInterface(tmplele) );
|
||||
NS_ASSERTION(tmpl != nsnull, "not an nsIContent");
|
||||
if (! tmpl)
|
||||
return PR_FALSE;
|
||||
|
||||
|
@ -6149,9 +6102,6 @@ nsXULTemplateBuilder::RemoveMember(nsIContent* aContainerElement,
|
|||
// Remove from the content support map.
|
||||
mContentSupportMap.Remove(child);
|
||||
|
||||
// Remove from the template map
|
||||
mTemplateMap.Remove(child);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_ALWAYS)) {
|
||||
nsCOMPtr<nsIAtom> parentTag;
|
||||
|
@ -6199,6 +6149,7 @@ nsXULTemplateBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
|
|||
// Generate both 1) the template content for the current element,
|
||||
// and 2) recursive subcontent (if the current element refers to a
|
||||
// container resource in the RDF graph).
|
||||
nsresult rv;
|
||||
|
||||
// If we're asked to return the first generated child, then
|
||||
// initialize to "none".
|
||||
|
@ -6209,19 +6160,23 @@ nsXULTemplateBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
|
|||
|
||||
// Create the current resource's contents from the template, if
|
||||
// appropriate
|
||||
nsCOMPtr<nsIContent> tmpl;
|
||||
mTemplateMap.GetTemplateFor(aElement, getter_AddRefs(tmpl));
|
||||
nsAutoString templateID;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, nsXULAtoms::Template, templateID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tmpl)
|
||||
CreateTemplateContents(aElement, tmpl, aContainer, aNewIndexInContainer);
|
||||
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
|
||||
rv = CreateTemplateContents(aElement, templateID, aContainer, aNewIndexInContainer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
gXULUtils->GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
if (resource) {
|
||||
rv = gXULUtils->GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
CreateContainerContents(aElement, resource, PR_FALSE, aContainer, aNewIndexInContainer);
|
||||
rv = CreateContainerContents(aElement, resource, PR_FALSE, aContainer, aNewIndexInContainer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -6336,7 +6291,7 @@ nsXULTemplateBuilder::CreateContainerContents(nsIContent* aElement,
|
|||
|
||||
nsresult
|
||||
nsXULTemplateBuilder::CreateTemplateContents(nsIContent* aElement,
|
||||
nsIContent* aTemplateElement,
|
||||
const nsString& aTemplateID,
|
||||
nsIContent** aContainer,
|
||||
PRInt32* aNewIndexInContainer)
|
||||
{
|
||||
|
@ -6370,6 +6325,14 @@ nsXULTemplateBuilder::CreateTemplateContents(nsIContent* aElement,
|
|||
if (! xulDoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> tmplNode;
|
||||
rv = xulDoc->GetElementById(aTemplateID, getter_AddRefs(tmplNode));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIContent> tmpl = do_QueryInterface(tmplNode);
|
||||
if (! tmpl)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// Crawl up the content model until we find the "resource" element
|
||||
// that spawned this template.
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
|
@ -6389,7 +6352,7 @@ nsXULTemplateBuilder::CreateTemplateContents(nsIContent* aElement,
|
|||
Match* match;
|
||||
mContentSupportMap.Get(element, &match);
|
||||
|
||||
rv = BuildContentFromTemplate(aTemplateElement, aElement, aElement, PR_FALSE, resource, PR_FALSE,
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, aElement, PR_FALSE, resource, PR_FALSE,
|
||||
match, aContainer, aNewIndexInContainer);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -6531,6 +6494,22 @@ nsXULTemplateBuilder::IsElementInWidget(nsIContent* aElement)
|
|||
nsresult
|
||||
nsXULTemplateBuilder::RemoveGeneratedContent(nsIContent* aElement)
|
||||
{
|
||||
// Remove and re-insert the element into the document. This'll
|
||||
// minimize the number of notifications that the layout engine has
|
||||
// to deal with.
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
aElement->GetParent(*getter_AddRefs(parent));
|
||||
|
||||
NS_ASSERTION(parent != nsnull, "huh? no parent!");
|
||||
if (! parent)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
PRInt32 pos;
|
||||
parent->IndexOf(aElement, pos);
|
||||
parent->RemoveChildAt(pos, PR_TRUE);
|
||||
|
||||
#define FAST_REMOVE_GENERATED_CONTENT
|
||||
#ifdef FAST_REMOVE_GENERATED_CONTENT
|
||||
// Keep a queue of "ungenerated" elements that we have to probe
|
||||
// for generated content.
|
||||
nsAutoVoidArray ungenerated;
|
||||
|
@ -6561,19 +6540,23 @@ nsXULTemplateBuilder::RemoveGeneratedContent(nsIContent* aElement)
|
|||
if (tag.get() == nsXULAtoms::Template)
|
||||
continue;
|
||||
|
||||
// If the element is in the template map, then we
|
||||
// If the element has a 'template' attribute, then we
|
||||
// assume it's been generated and nuke it.
|
||||
nsCOMPtr<nsIContent> tmpl;
|
||||
mTemplateMap.GetTemplateFor(child, getter_AddRefs(tmpl));
|
||||
nsAutoString tmplID;
|
||||
child->GetAttribute(kNameSpaceID_None, nsXULAtoms::Template, tmplID);
|
||||
|
||||
if (! tmpl) {
|
||||
// Not in the template map, so this must not have been
|
||||
if (tmplID.Length() == 0) {
|
||||
// No 'template' attribute, so this must not have been
|
||||
// generated. We'll need to examine its kids.
|
||||
ungenerated.AppendElement(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we get here, it's "generated". Bye bye!
|
||||
element->RemoveChildAt(i, PR_TRUE);
|
||||
// If we get here, it's "generated". Bye bye! Remove it
|
||||
// from the content model "quietly", because we'll remove
|
||||
// and re-insert the top-level element into the document
|
||||
// to minimze reflow.
|
||||
element->RemoveChildAt(i, PR_FALSE);
|
||||
child->SetDocument(nsnull, PR_TRUE, PR_TRUE);
|
||||
|
||||
// Remove element from the conflict set.
|
||||
|
@ -6583,12 +6566,31 @@ nsXULTemplateBuilder::RemoveGeneratedContent(nsIContent* aElement)
|
|||
|
||||
// Remove this and any children from the content support map.
|
||||
mContentSupportMap.Remove(child);
|
||||
|
||||
// Remove from the template map
|
||||
mTemplateMap.Remove(child);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Compute the retractions that'll occur when we remove the
|
||||
// element from the conflict set.
|
||||
MatchSet firings, retractions;
|
||||
mConflictSet.Remove(ContentTestNode::Element(aElement), firings, retractions);
|
||||
|
||||
// Removing the generated content, quietly.
|
||||
MatchSet::Iterator last = retractions.Last();
|
||||
for (MatchSet::Iterator match = retractions.First(); match != last; ++match) {
|
||||
Value memberval;
|
||||
match->mAssignments.GetAssignmentFor(match->mRule->GetMemberVariable(), &memberval);
|
||||
|
||||
RemoveMember(aElement, VALUE_TO_IRDFRESOURCE(memberval), PR_FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
aElement->SetDocument(doc, PR_TRUE, PR_TRUE);
|
||||
|
||||
parent->InsertChildAt(aElement, pos, PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -7169,23 +7171,6 @@ nsXULTemplateBuilder::GetFlags()
|
|||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsXULTemplateBuilder::IsTemplateElement(nsIContent* aContent)
|
||||
{
|
||||
PRInt32 nameSpaceID;
|
||||
aContent->GetNameSpaceID(nameSpaceID);
|
||||
|
||||
if (nameSpaceID == nsXULTemplateBuilder::kNameSpaceID_XUL) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContent->GetTag(*getter_AddRefs(tag));
|
||||
|
||||
if (tag.get() == nsXULAtoms::Template)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULTemplateBuilder::CompileRules()
|
||||
|
@ -7235,32 +7220,31 @@ nsXULTemplateBuilder::CompileRules()
|
|||
// If root node has no template attribute, then look for a child
|
||||
// node which is a template tag
|
||||
if (! tmpl) {
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
PRInt32 count;
|
||||
rv = mRoot->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (bindingManager) {
|
||||
nsCOMPtr<nsIDOMNodeList> kids;
|
||||
bindingManager->GetXBLChildNodesFor(mRoot, getter_AddRefs(kids));
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = mRoot->ChildAt(i, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (kids) {
|
||||
PRUint32 length;
|
||||
kids->GetLength(&length);
|
||||
PRInt32 nameSpaceID;
|
||||
rv = child->GetNameSpaceID(nameSpaceID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
kids->Item(i, getter_AddRefs(node));
|
||||
if (! node)
|
||||
continue;
|
||||
if (nameSpaceID != kNameSpaceID_XUL)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIContent> child = do_QueryInterface(node);
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = child->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (IsTemplateElement(child)) {
|
||||
tmpl = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag.get() != nsXULAtoms::Template)
|
||||
continue;
|
||||
|
||||
tmpl = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8131,35 +8115,3 @@ nsXULTemplateBuilder::CompileBinding(Rule* aRule,
|
|||
|
||||
return aRule->AddBinding(svar, pres, ovar);
|
||||
}
|
||||
|
||||
/* string canCreateWrapper (in nsIIDPtr iid); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanCreateWrapper(const nsIID * iid, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
|
||||
{
|
||||
*_retval = PL_strdup("AllAccess");
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче