From 8ef28522441f8827b85c2e81adfbdb1d7781bcbe Mon Sep 17 00:00:00 2001 From: "bryner%brianryner.com" Date: Mon, 31 Jan 2005 23:41:00 +0000 Subject: [PATCH] Fix nsXFormsModelElement::Rebuild() to work correctly. Patch by aaronr@us.ibm.com, r=allan@beaufour.dk, sr=me. --- extensions/xforms/Makefile.in | 2 + .../xforms/nsXFormsContextContainer.cpp | 8 +++ extensions/xforms/nsXFormsControlStub.cpp | 26 ++++++++- extensions/xforms/nsXFormsControlStub.h | 1 + extensions/xforms/nsXFormsGroupElement.cpp | 45 ++++++-------- extensions/xforms/nsXFormsInputElement.cpp | 23 -------- extensions/xforms/nsXFormsLabelElement.cpp | 16 +---- extensions/xforms/nsXFormsModelElement.cpp | 58 ++++++++++++++++--- extensions/xforms/nsXFormsModelElement.h | 1 + extensions/xforms/nsXFormsRepeatElement.cpp | 7 +++ extensions/xforms/nsXFormsSelectElement.cpp | 14 ++--- extensions/xforms/nsXFormsSwitchElement.cpp | 45 +++++--------- extensions/xforms/nsXFormsTriggerElement.cpp | 14 ----- extensions/xforms/nsXFormsUploadElement.cpp | 16 ----- extensions/xforms/package/Makefile.in | 6 +- extensions/xforms/package/xforms.jst | 3 + extensions/xforms/xforms.js | 1 + 17 files changed, 139 insertions(+), 147 deletions(-) create mode 100755 extensions/xforms/xforms.js diff --git a/extensions/xforms/Makefile.in b/extensions/xforms/Makefile.in index f3b7a8acabf2..b30235f3668e 100644 --- a/extensions/xforms/Makefile.in +++ b/extensions/xforms/Makefile.in @@ -138,4 +138,6 @@ CPPSRCS = \ EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS) +PREF_JS_EXPORTS = $(srcdir)/xforms.js + include $(topsrcdir)/config/rules.mk diff --git a/extensions/xforms/nsXFormsContextContainer.cpp b/extensions/xforms/nsXFormsContextContainer.cpp index 0b09298ad0d0..c0e615e12d18 100644 --- a/extensions/xforms/nsXFormsContextContainer.cpp +++ b/extensions/xforms/nsXFormsContextContainer.cpp @@ -89,6 +89,7 @@ public: NS_IMETHOD CloneState(nsIDOMElement *aElement); // nsIXFormsControl + NS_IMETHOD Bind(); NS_IMETHOD Refresh(); // nsIXFormsContextControl @@ -214,6 +215,13 @@ nsXFormsContextContainer::GetContext(nsAString &aModelID, } // nsIXFormsControl + +NS_IMETHODIMP +nsXFormsContextContainer::Bind() +{ + return NS_OK; +} + nsresult nsXFormsContextContainer::Refresh() { diff --git a/extensions/xforms/nsXFormsControlStub.cpp b/extensions/xforms/nsXFormsControlStub.cpp index aaeaf8c57011..4c0502a05330 100644 --- a/extensions/xforms/nsXFormsControlStub.cpp +++ b/extensions/xforms/nsXFormsControlStub.cpp @@ -100,6 +100,30 @@ nsXFormsControlStub::GetElement(nsIDOMElement **aElement) return NS_OK; } +NS_IMETHODIMP +nsXFormsControlStub::ResetBoundNode() +{ + mBoundNode = nsnull; + + nsCOMPtr modelNode; + nsCOMPtr result; + nsresult rv = + ProcessNodeBinding(NS_LITERAL_STRING("ref"), + nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, + getter_AddRefs(result), + getter_AddRefs(modelNode)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!result) { + return NS_OK; + } + + // Get context node, if any + result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); + + return NS_OK; +} + /** * @note Refresh() is always called after a Bind(), so if a control decides to * do all the work in Refresh() this function implements a NOP Bind(). @@ -107,7 +131,7 @@ nsXFormsControlStub::GetElement(nsIDOMElement **aElement) NS_IMETHODIMP nsXFormsControlStub::Bind() { - return NS_OK; + return ResetBoundNode(); } NS_IMETHODIMP diff --git a/extensions/xforms/nsXFormsControlStub.h b/extensions/xforms/nsXFormsControlStub.h index 2241a06df02d..a501ba0ac3be 100644 --- a/extensions/xforms/nsXFormsControlStub.h +++ b/extensions/xforms/nsXFormsControlStub.h @@ -83,6 +83,7 @@ public: NS_IMETHOD GetBoundNode(nsIDOMNode **aBoundNode); NS_IMETHOD GetDependencies(nsIArray **aDependencies); NS_IMETHOD GetElement(nsIDOMElement **aElement); + NS_IMETHOD ResetBoundNode(); NS_IMETHOD Bind(); NS_IMETHOD TryFocus(PRBool* aOK); diff --git a/extensions/xforms/nsXFormsGroupElement.cpp b/extensions/xforms/nsXFormsGroupElement.cpp index 34d65d54e7ce..b192d1fdd06f 100644 --- a/extensions/xforms/nsXFormsGroupElement.cpp +++ b/extensions/xforms/nsXFormsGroupElement.cpp @@ -106,6 +106,7 @@ public: NS_IMETHOD OnDestroyed(); // nsIXFormsControl + NS_IMETHOD Bind(); NS_IMETHOD Refresh(); NS_IMETHOD TryFocus(PRBool* aOK); @@ -181,6 +182,22 @@ nsXFormsGroupElement::OnDestroyed() // nsIXFormsControl +NS_IMETHODIMP +nsXFormsGroupElement::Bind() +{ + mModelID.Truncate(); + + // Re-evaluate what instance node this element is bound to. + ResetBoundNode(); + + // Get model ID + nsCOMPtr modelElement = do_QueryInterface(mModel); + NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE); + modelElement->GetAttribute(NS_LITERAL_STRING("id"), mModelID); + + return NS_OK; +} + NS_IMETHODIMP nsXFormsGroupElement::Refresh() { @@ -188,34 +205,6 @@ nsXFormsGroupElement::Refresh() printf("nsXFormsGroupElement::Refresh()\n"); #endif - if (!mHTMLElement) - return NS_OK; - - mModelID.Truncate(); - - nsCOMPtr modelNode; - nsCOMPtr result; - nsresult rv = - ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result), - getter_AddRefs(modelNode)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!result) { - return NS_OK; - } - - - // Get model ID - nsCOMPtr modelElement = do_QueryInterface(modelNode); - NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE); - modelElement->GetAttribute(NS_LITERAL_STRING("id"), mModelID); - - // Get context node, if any - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - NS_ENSURE_STATE(mBoundNode); - return NS_OK; } diff --git a/extensions/xforms/nsXFormsInputElement.cpp b/extensions/xforms/nsXFormsInputElement.cpp index 85e7f2dbb797..917f94140e14 100644 --- a/extensions/xforms/nsXFormsInputElement.cpp +++ b/extensions/xforms/nsXFormsInputElement.cpp @@ -77,7 +77,6 @@ public: NS_IMETHOD OnDestroyed(); // nsIXFormsControl - NS_IMETHOD Bind(); NS_IMETHOD Refresh(); NS_IMETHOD TryFocus(PRBool* aOK); @@ -268,28 +267,6 @@ nsXFormsInputElement::Blur(nsIDOMEvent *aEvent) // nsIXFormsControl -NS_IMETHODIMP -nsXFormsInputElement::Bind() -{ - if (!mControl) - return NS_OK; - - mBoundNode = nsnull; - - nsCOMPtr result; - nsresult rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result)); - - NS_ENSURE_SUCCESS(rv, rv); - - if (result) { - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - } - - return NS_OK; -} - NS_IMETHODIMP nsXFormsInputElement::Refresh() { diff --git a/extensions/xforms/nsXFormsLabelElement.cpp b/extensions/xforms/nsXFormsLabelElement.cpp index 97e07512c256..4fa0de9caea9 100644 --- a/extensions/xforms/nsXFormsLabelElement.cpp +++ b/extensions/xforms/nsXFormsLabelElement.cpp @@ -168,22 +168,12 @@ nsXFormsLabelElement::RefreshLabel() // or linking attributes are present, we don't want to show the inline text // at all. - nsCOMPtr result; - nsresult rv = - ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result)); - nsAutoString labelValue; PRBool foundValue = PR_FALSE; - if (NS_SUCCEEDED(rv) && result) { - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - - if (mBoundNode) { - nsXFormsUtils::GetNodeValue(mBoundNode, labelValue); - foundValue = PR_TRUE; - } + if (mBoundNode) { + nsXFormsUtils::GetNodeValue(mBoundNode, labelValue); + foundValue = PR_TRUE; } // if (!foundValue) { diff --git a/extensions/xforms/nsXFormsModelElement.cpp b/extensions/xforms/nsXFormsModelElement.cpp index 7dcb584447bc..ff03c660418f 100644 --- a/extensions/xforms/nsXFormsModelElement.cpp +++ b/extensions/xforms/nsXFormsModelElement.cpp @@ -423,11 +423,39 @@ nsXFormsModelElement::Rebuild() // TODO: Clear graph and re-attach elements // 1 . Clear graph - // mMDG.Clear(); + mMDG.Clear(); // 2. Re-attach all elements + // Copy the form control list as it stands right now. + nsVoidArray *oldFormList = new nsVoidArray(); + *oldFormList = mFormControls; + + // Clear out mFormControls so that we can rebuild the list. We'll go control + // by control over the old list and rebind the controls. + mFormControls.Clear(); + + PRInt32 controlCount = oldFormList->Count(); + for (PRInt32 i = 0; i < controlCount; ++i) { + nsIXFormsControl* control = NS_STATIC_CAST(nsIXFormsControl*, + (*oldFormList)[i]); + /// @todo If a control is removed because of previous control has been + /// refreshed, we do, obviously, not need to refresh it. So mFormControls + /// should have weak bindings to the controls I guess? (XXX) + /// + /// This could happen for \s for example. + if (!control) { + continue; + } + + // run bind to reset mBoundNode for all of these controls and also, in the + // process, they will be added to the model that they should be bound to. + control->Bind(); + } + // 3. Rebuild graph + ProcessBindElements(); + return mMDG.Rebuild(); } @@ -948,14 +976,13 @@ nsXFormsModelElement::FindInstanceDocument(const nsAString &aID) } nsresult -nsXFormsModelElement::FinishConstruction() +nsXFormsModelElement::ProcessBindElements() { - // 3. if applicable, initialize P3P - - // 4. construct instance data from initial instance data. apply all - // elements in document order. - - // we get the instance data from our instance child nodes + // ProcessBindElements() will go through each xforms:bind element in + // document order and apply all of the Model Item Properties to the + // instance items in the nodeset. This information will also be entered + // in the Master Dependency Graph. Most of this work is done in the + // ProcessBind() method. nsCOMPtr firstInstanceDoc = FindInstanceDocument(EmptyString()); @@ -996,6 +1023,21 @@ nsXFormsModelElement::FinishConstruction() } } + return NS_OK; +} + +nsresult +nsXFormsModelElement::FinishConstruction() +{ + // 3. if applicable, initialize P3P + + // 4. construct instance data from initial instance data. apply all + // elements in document order. + + // we get the instance data from our instance child nodes + + ProcessBindElements(); + // 5. dispatch xforms-rebuild, xforms-recalculate, xforms-revalidate nsXFormsUtils::DispatchEvent(mElement, eEvent_Rebuild); diff --git a/extensions/xforms/nsXFormsModelElement.h b/extensions/xforms/nsXFormsModelElement.h index 868674622d46..c05d574e3056 100644 --- a/extensions/xforms/nsXFormsModelElement.h +++ b/extensions/xforms/nsXFormsModelElement.h @@ -101,6 +101,7 @@ private: NS_HIDDEN_(already_AddRefed) FindInstanceDocument(const nsAString &aID); + NS_HIDDEN_(nsresult) ProcessBindElements(); NS_HIDDEN_(nsresult) FinishConstruction(); NS_HIDDEN_(void) MaybeNotifyCompletion(); diff --git a/extensions/xforms/nsXFormsRepeatElement.cpp b/extensions/xforms/nsXFormsRepeatElement.cpp index 18071ee6d41b..462eeefe59e5 100644 --- a/extensions/xforms/nsXFormsRepeatElement.cpp +++ b/extensions/xforms/nsXFormsRepeatElement.cpp @@ -159,6 +159,7 @@ public: NS_IMETHOD DoneAddingChildren(); // nsIXFormsControl + NS_IMETHOD Bind(); NS_IMETHOD Refresh(); NS_IMETHOD TryFocus(PRBool* aOK); @@ -280,6 +281,12 @@ nsXFormsRepeatElement::DoneAddingChildren() // nsXFormsControl +NS_IMETHODIMP +nsXFormsRepeatElement::Bind() +{ + return NS_OK; +} + NS_IMETHODIMP nsXFormsRepeatElement::Refresh() { diff --git a/extensions/xforms/nsXFormsSelectElement.cpp b/extensions/xforms/nsXFormsSelectElement.cpp index 13f90e091aa4..23a9054d1e38 100644 --- a/extensions/xforms/nsXFormsSelectElement.cpp +++ b/extensions/xforms/nsXFormsSelectElement.cpp @@ -297,17 +297,11 @@ nsXFormsSelectElement::Refresh() mSelect->SetSelectedIndex(-1); } - nsCOMPtr result; - rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result)); - NS_ENSURE_SUCCESS(rv, rv); - - if (result) - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - - if (!mBoundNode) + // since single node binding is optional, we won't send an error code. But + // there is no point continuing below without mBoundNode. + if(!mBoundNode) { return NS_OK; + } nsCOMPtr children; mBoundNode->GetChildNodes(getter_AddRefs(children)); diff --git a/extensions/xforms/nsXFormsSwitchElement.cpp b/extensions/xforms/nsXFormsSwitchElement.cpp index 431d54a2a0da..07689c0e0d1d 100644 --- a/extensions/xforms/nsXFormsSwitchElement.cpp +++ b/extensions/xforms/nsXFormsSwitchElement.cpp @@ -88,6 +88,7 @@ public: NS_DECL_NSIXFORMSSWITCHELEMENT // nsIXFormsControl + NS_IMETHOD Bind(); NS_IMETHOD Refresh(); NS_DECL_NSIXFORMSCONTEXTCONTROL @@ -117,8 +118,6 @@ private: */ void SetFocus(nsIDOMElement* aDeselected, nsIDOMElement* aSelected); - nsresult Process(); - nsCOMPtr mVisual; nsCOMPtr mSelected; PRBool mDoneAddingChildren; @@ -227,47 +226,29 @@ nsXFormsSwitchElement::DoneAddingChildren() // nsIXFormsControl NS_IMETHODIMP -nsXFormsSwitchElement::Refresh() -{ - nsresult rv = NS_OK; - if (mDoneAddingChildren) { - rv = Process(); - } - return rv; -} - -// nsXFormsSwitchElement - -nsresult -nsXFormsSwitchElement::Process() +nsXFormsSwitchElement::Bind() { mModelID.Truncate(); - nsCOMPtr modelNode; - nsCOMPtr result; - nsresult rv = - ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result), - getter_AddRefs(modelNode)); - - NS_ENSURE_SUCCESS(rv, rv); - - if (!result) { - return NS_OK; - } + // Re-evaluate what instance node this element is bound to. + ResetBoundNode(); // Get model ID - nsCOMPtr modelElement = do_QueryInterface(modelNode); + nsCOMPtr modelElement = do_QueryInterface(mModel); NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE); modelElement->GetAttribute(NS_LITERAL_STRING("id"), mModelID); - // Get context node, if any - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - return NS_OK; } +NS_IMETHODIMP +nsXFormsSwitchElement::Refresh() +{ + return NS_OK; +} + +// nsXFormsSwitchElement + NS_IMETHODIMP nsXFormsSwitchElement::SetContextNode(nsIDOMNode *aContextNode) { diff --git a/extensions/xforms/nsXFormsTriggerElement.cpp b/extensions/xforms/nsXFormsTriggerElement.cpp index 956c464ed813..3b08603e0f65 100644 --- a/extensions/xforms/nsXFormsTriggerElement.cpp +++ b/extensions/xforms/nsXFormsTriggerElement.cpp @@ -122,20 +122,6 @@ nsXFormsTriggerElement::GetInsertionPoint(nsIDOMElement **aElement) NS_IMETHODIMP nsXFormsTriggerElement::Refresh() { - nsCOMPtr result; - nsresult rv = - ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!result) { - return NS_OK; - } - - // Get context node, if any - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - return NS_OK; } diff --git a/extensions/xforms/nsXFormsUploadElement.cpp b/extensions/xforms/nsXFormsUploadElement.cpp index 1b466c9772e8..234398942c39 100644 --- a/extensions/xforms/nsXFormsUploadElement.cpp +++ b/extensions/xforms/nsXFormsUploadElement.cpp @@ -248,22 +248,6 @@ nsXFormsUploadElement::Refresh() if (!mInput) return NS_OK; - mBoundNode = nsnull; - - nsCOMPtr result; - nsresult rv = - ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result)); - NS_ENSURE_SUCCESS(rv, rv); - - - if (result) - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - - if (!mBoundNode) - return NS_OK; - nsCOMPtr content = do_QueryInterface(mBoundNode); NS_ENSURE_STATE(content); diff --git a/extensions/xforms/package/Makefile.in b/extensions/xforms/package/Makefile.in index 6c310319a48b..65d7f1b5d996 100755 --- a/extensions/xforms/package/Makefile.in +++ b/extensions/xforms/package/Makefile.in @@ -63,9 +63,11 @@ PACKAGE_VERSION = 0.1 xpi: @echo Copying files to staging area... rm -rf stage - $(NSINSTALL) -D stage + $(INSTALL) -D stage $(PERL) $(topsrcdir)/xpinstall/packager/pkgcp.pl -o $(PKGCP_PLATFORM) -s $(DIST)/bin -d stage -f $(srcdir)/$(PACKAGE_FILE) -v - $(NSINSTALL) $(srcdir)/install.rdf stage/xforms + $(INSTALL) $(srcdir)/install.rdf stage/xforms + $(INSTALL) -D stage/xforms/defaults/preferences + $(INSTALL) $(srcdir)/../xforms.js stage/xforms/defaults/preferences @echo Creating install.js... rm -f xforms.js $(PERL) $(topsrcdir)/toolkit/mozapps/installer/makejs.pl $(srcdir)/xforms.jst $(PACKAGE_VERSION) stage/xforms diff --git a/extensions/xforms/package/xforms.jst b/extensions/xforms/package/xforms.jst index 87c290027de6..b64e1d2e5d49 100755 --- a/extensions/xforms/package/xforms.jst +++ b/extensions/xforms/package/xforms.jst @@ -11,6 +11,9 @@ if (verifyDiskSpace(fProgram, srChrome + srComponents)) logComment("addDirectory components: " + err); err = addDirectory("", "0.1", "chrome", fProgram, "chrome", true); logComment("addDirectory chrome: " + err); + err = addFile("", "0.1", "defaults/preferences/xforms.js", fProgram, + "defaults/pref/xforms.js", true); + logComment("addFile xforms.js: " + err); registerChrome(PACKAGE | DELAYED_CHROME, getFolder("Chrome", "xforms.jar"), "content/xforms/"); diff --git a/extensions/xforms/xforms.js b/extensions/xforms/xforms.js new file mode 100755 index 000000000000..a48afc0f0b44 --- /dev/null +++ b/extensions/xforms/xforms.js @@ -0,0 +1 @@ +pref("general.useragent.productComment", "xforms/1.0");