From 24c4b2f21e335259ce8aa7672576da6cabb88ed6 Mon Sep 17 00:00:00 2001 From: "Olli.Pettay%helsinki.fi" Date: Fri, 28 Oct 2005 18:52:56 +0000 Subject: [PATCH] Bug 308106, controls not bound to external instance data in xul, r=aaronr+allan --- .../xforms/nsIInstanceElementPrivate.idl | 4 +- extensions/xforms/nsXFormsInstanceElement.cpp | 160 +++++++----------- extensions/xforms/nsXFormsInstanceElement.h | 5 +- extensions/xforms/nsXFormsModelElement.cpp | 45 ++++- extensions/xforms/nsXFormsModelElement.h | 5 + 5 files changed, 114 insertions(+), 105 deletions(-) diff --git a/extensions/xforms/nsIInstanceElementPrivate.idl b/extensions/xforms/nsIInstanceElementPrivate.idl index 1caef76db2f2..c3373046e3a7 100644 --- a/extensions/xforms/nsIInstanceElementPrivate.idl +++ b/extensions/xforms/nsIInstanceElementPrivate.idl @@ -44,7 +44,7 @@ interface nsIDOMElement; /** * Private interface implemented by the instance element. */ -[uuid(446dc7b6-91fc-4de5-b6de-5ac22538ee5e)] +[uuid(debb24ef-7ba1-4e01-9f62-18106b25c993)] interface nsIInstanceElementPrivate : nsISupports { /** @@ -54,5 +54,5 @@ interface nsIInstanceElementPrivate : nsISupports readonly attribute nsIDOMElement element; void backupOriginalDocument(); void restoreOriginalDocument(); - void initializeLazyInstance(); + void initialize(); }; diff --git a/extensions/xforms/nsXFormsInstanceElement.cpp b/extensions/xforms/nsXFormsInstanceElement.cpp index 46d60e02545c..e576b521d01f 100644 --- a/extensions/xforms/nsXFormsInstanceElement.cpp +++ b/extensions/xforms/nsXFormsInstanceElement.cpp @@ -63,7 +63,7 @@ NS_IMPL_ISUPPORTS_INHERITED5(nsXFormsInstanceElement, nsXFormsInstanceElement::nsXFormsInstanceElement() : mElement(nsnull) - , mAddingChildren(PR_FALSE) + , mInitialized(PR_FALSE) , mLazy(PR_FALSE) { } @@ -87,7 +87,7 @@ NS_IMETHODIMP nsXFormsInstanceElement::AttributeSet(nsIAtom *aName, const nsAString &aNewValue) { - if (mAddingChildren || mLazy) + if (!mInitialized || mLazy) return NS_OK; if (aName == nsXFormsAtoms::src) { @@ -100,7 +100,7 @@ nsXFormsInstanceElement::AttributeSet(nsIAtom *aName, NS_IMETHODIMP nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName) { - if (mAddingChildren || mLazy) + if (!mInitialized || mLazy) return NS_OK; if (aName == nsXFormsAtoms::src) { @@ -135,51 +135,11 @@ nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName) return NS_OK; } -NS_IMETHODIMP -nsXFormsInstanceElement::BeginAddingChildren() -{ - mAddingChildren = PR_TRUE; - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsInstanceElement::DoneAddingChildren() -{ - - mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY), - NS_LITERAL_STRING("lazy"), &mLazy); - if (!mLazy) { - nsCOMPtr model = GetModel(); - NS_ENSURE_TRUE(model, NS_ERROR_FAILURE); - model->AddInstanceElement(this); - - // By the time this is called, we should be inserted in the document and - // have all of our child elements, so this is our first opportunity to - // create the instance document. - - nsAutoString src; - mElement->GetAttribute(NS_LITERAL_STRING("src"), src); - - if (src.IsEmpty()) { - // If we don't have a linked external instance, use our inline data. - CloneInlineInstance(); - } else { - LoadExternalInstance(src); - } - } - - mAddingChildren = PR_FALSE; - return NS_OK; -} - NS_IMETHODIMP nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper) { aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET | - nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED | - nsIXTFElement::NOTIFY_PARENT_CHANGED | - nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN | - nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN); + nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED); nsCOMPtr node; aWrapper->GetElementNode(getter_AddRefs(node)); @@ -194,22 +154,6 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper) return NS_OK; } -NS_IMETHODIMP -nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent) -{ - if (!aNewParent || mAddingChildren || mLazy) - return NS_OK; - - // Once we are set up in the DOM, can find the model and make sure that this - // instance is on the list of instance elements that model keeps - nsCOMPtr model = GetModel(); - if (model) { - model->AddInstanceElement(this); - } - - return NS_OK; -} - // nsIInterfaceRequestor NS_IMETHODIMP @@ -445,49 +389,73 @@ nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement) } NS_IMETHODIMP -nsXFormsInstanceElement::InitializeLazyInstance() +nsXFormsInstanceElement::Initialize() { - NS_ENSURE_STATE(mElement); - if (!mLazy) { - mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY), - NS_LITERAL_STRING("lazy"), &mLazy); + if (mInitialized || !mElement) { + return NS_OK; } - NS_ENSURE_STATE(mLazy); + mInitialized = PR_TRUE; - nsCOMPtr domDoc; - mElement->GetOwnerDocument(getter_AddRefs(domDoc)); - NS_ENSURE_STATE(domDoc); + nsCOMPtr model = GetModel(); + NS_ENSURE_TRUE(model, NS_ERROR_FAILURE); + model->AddInstanceElement(this); - nsCOMPtr domImpl; - nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl)); - NS_ENSURE_SUCCESS(rv, rv); + mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY), + NS_LITERAL_STRING("lazy"), &mLazy); - nsCOMPtr newDoc; - rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull, - getter_AddRefs(newDoc)); - NS_ENSURE_SUCCESS(rv, rv); + // Lazy instance + if (mLazy) { + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + NS_ENSURE_STATE(domDoc); + + nsCOMPtr domImpl; + nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr newDoc; + rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull, + getter_AddRefs(newDoc)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetDocument(newDoc); + NS_ENSURE_SUCCESS(rv, rv); + + // Lazy authored instance documents have a root named "instanceData" + nsCOMPtr instanceDataElement; + nsCOMPtr childReturn; + rv = mDocument->CreateElementNS(EmptyString(), + NS_LITERAL_STRING("instanceData"), + getter_AddRefs(instanceDataElement)); + NS_ENSURE_SUCCESS(rv, rv); + rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn)); + NS_ENSURE_SUCCESS(rv, rv); + + // I don't know if not being able to create a backup document is worth + // failing this function. Since it probably won't be used often, we'll + // let it slide. But it probably does mean that things are going south + // with the browser. + domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull, + getter_AddRefs(mOriginalDocument)); + NS_WARN_IF_FALSE(mOriginalDocument, "Couldn't create mOriginalDocument!!"); + } else { + // Normal instance - rv = SetDocument(newDoc); - NS_ENSURE_SUCCESS(rv, rv); - - // Lazy authored instance documents have a root named "instanceData" - nsCOMPtr instanceDataElement; - nsCOMPtr childReturn; - rv = mDocument->CreateElementNS(EmptyString(), - NS_LITERAL_STRING("instanceData"), - getter_AddRefs(instanceDataElement)); - NS_ENSURE_SUCCESS(rv, rv); - rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn)); - NS_ENSURE_SUCCESS(rv, rv); - - // I don't know if not being able to create a backup document is worth - // failing this function. Since it probably won't be used often, we'll - // let it slide. But it probably does mean that things are going south - // with the browser. - domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull, - getter_AddRefs(mOriginalDocument)); - NS_WARN_IF_FALSE(mOriginalDocument, "Couldn't create mOriginalDocument!!"); + // By the time this is called, we should be inserted in the document and + // have all of our child elements, so this is our first opportunity to + // create the instance document. + + nsAutoString src; + mElement->GetAttribute(NS_LITERAL_STRING("src"), src); + + if (src.IsEmpty()) { + // If we don't have a linked external instance, use our inline data. + CloneInlineInstance(); + } else { + LoadExternalInstance(src); + } + } return NS_OK; } diff --git a/extensions/xforms/nsXFormsInstanceElement.h b/extensions/xforms/nsXFormsInstanceElement.h index f0531da5a887..81a2e364c38c 100644 --- a/extensions/xforms/nsXFormsInstanceElement.h +++ b/extensions/xforms/nsXFormsInstanceElement.h @@ -75,10 +75,7 @@ public: NS_IMETHOD OnDestroyed(); NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aNewValue); NS_IMETHOD AttributeRemoved(nsIAtom *aName); - NS_IMETHOD BeginAddingChildren(); - NS_IMETHOD DoneAddingChildren(); NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper); - NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); nsXFormsInstanceElement() NS_HIDDEN; @@ -92,7 +89,7 @@ private: nsCOMPtr mOriginalDocument; nsIDOMElement *mElement; nsCOMPtr mListener; - PRBool mAddingChildren; + PRBool mInitialized; PRBool mLazy; nsCOMPtr mChannel; }; diff --git a/extensions/xforms/nsXFormsModelElement.cpp b/extensions/xforms/nsXFormsModelElement.cpp index 1b4725a29ebc..9cbcca4c5944 100644 --- a/extensions/xforms/nsXFormsModelElement.cpp +++ b/extensions/xforms/nsXFormsModelElement.cpp @@ -260,6 +260,7 @@ nsXFormsModelElement::nsXFormsModelElement() mPendingInstanceCount(0), mDocumentLoaded(PR_FALSE), mNeedsRefresh(PR_FALSE), + mInstancesInitialized(PR_FALSE), mInstanceDocuments(nsnull), mLazyModel(PR_FALSE) { @@ -346,6 +347,36 @@ nsXFormsModelElement::DocumentChanged(nsIDOMDocument* aNewDocument) NS_IMETHODIMP nsXFormsModelElement::DoneAddingChildren() { + return InitializeInstances(); +} + +nsresult +nsXFormsModelElement::InitializeInstances() +{ + if (mInstancesInitialized || !mElement) { + return NS_OK; + } + + mInstancesInitialized = PR_TRUE; + + nsCOMPtr children; + mElement->GetChildNodes(getter_AddRefs(children)); + + PRUint32 childCount = 0; + if (children) { + children->GetLength(&childCount); + } + + for (PRUint32 i = 0; i < childCount; ++i) { + nsCOMPtr child; + children->Item(i, getter_AddRefs(child)); + if (nsXFormsUtils::IsXFormsElement(child, NS_LITERAL_STRING("instance"))) { + nsCOMPtr instance(do_QueryInterface(child)); + if (instance) { + instance->Initialize(); + } + } + } // (XForms 4.2.1) // 1. load xml schemas @@ -427,6 +458,9 @@ nsXFormsModelElement::DoneAddingChildren() PRUint32 instCount; mInstanceDocuments->GetLength(&instCount); if (!instCount) { +#ifdef DEBUG + printf("Creating lazy instance\n"); +#endif nsCOMPtr domDoc; mElement->GetOwnerDocument(getter_AddRefs(domDoc)); nsCOMPtr xblDoc(do_QueryInterface(domDoc)); @@ -437,8 +471,6 @@ nsXFormsModelElement::DoneAddingChildren() NS_ENSURE_SUCCESS(rv, rv); mInstanceDocuments->GetLength(&instCount); - NS_WARN_IF_FALSE(instCount == 1, - "Installing lazy instance didn't succeed!"); nsCOMPtr list; xblDoc->GetAnonymousNodes(mElement, getter_AddRefs(list)); @@ -454,7 +486,7 @@ nsXFormsModelElement::DoneAddingChildren() nsCOMPtr instance = do_QueryInterface(item); if (instance) { - rv = instance->InitializeLazyInstance(); + rv = instance->Initialize(); NS_ENSURE_SUCCESS(rv, rv); mLazyModel = PR_TRUE; @@ -463,6 +495,7 @@ nsXFormsModelElement::DoneAddingChildren() } } } + NS_WARN_IF_FALSE(mLazyModel, "Installing lazy instance didn't succeed!"); } // (XForms 4.2.1 - cont) @@ -893,6 +926,12 @@ nsXFormsModelElement::HandleEvent(nsIDOMEvent* aEvent) if (!type.EqualsLiteral("DOMContentLoaded")) return NS_OK; + if (!mInstancesInitialized) { + // XXX This is for Bug 308106. In Gecko 1.8 DoneAddingChildren is not + // called in XUL if the element doesn't have any child nodes. + InitializeInstances(); + } + mDocumentLoaded = PR_TRUE; // dispatch xforms-model-construct, xforms-rebuild, xforms-recalculate, diff --git a/extensions/xforms/nsXFormsModelElement.h b/extensions/xforms/nsXFormsModelElement.h index 2af15abbd439..161c6542cc64 100644 --- a/extensions/xforms/nsXFormsModelElement.h +++ b/extensions/xforms/nsXFormsModelElement.h @@ -178,6 +178,8 @@ private: /** Initializes the MIPs on all form controls */ NS_HIDDEN_(nsresult) InitializeControls(); + NS_HIDDEN_(nsresult) InitializeInstances(); + NS_HIDDEN_(nsresult) ProcessBindElements(); NS_HIDDEN_(nsresult) FinishConstruction(); NS_HIDDEN_(nsresult) ConstructDone(); @@ -253,6 +255,9 @@ private: // xforms-revalidate yet PRBool mNeedsRefresh; + // This flag indicates whether instance elements have been initialized + PRBool mInstancesInitialized; + /** * All instance documents contained by this model, including lazy-authored * instance documents.