diff --git a/mozilla/extensions/xforms/nsXFormsContextContainer.cpp b/mozilla/extensions/xforms/nsXFormsContextContainer.cpp index e8f8840d332..7518e25221a 100644 --- a/mozilla/extensions/xforms/nsXFormsContextContainer.cpp +++ b/mozilla/extensions/xforms/nsXFormsContextContainer.cpp @@ -98,7 +98,6 @@ public: // nsIXFormsControl NS_IMETHOD Bind(); - NS_IMETHOD Refresh(); NS_IMETHOD SetContext(nsIDOMNode *aContextNode, PRInt32 aContextPosition, PRInt32 aContextSize); @@ -260,20 +259,10 @@ nsXFormsContextContainer::Bind() nsresult rv = BindToModel(); NS_ENSURE_SUCCESS(rv, rv); - - if (mModel) { - mModel->SetStates(this, mBoundNode); - } return NS_OK; } -nsresult -nsXFormsContextContainer::Refresh() -{ - return NS_OK; -} - NS_IMETHODIMP nsXFormsContextContainer::IsEventTarget(PRBool* aOK) { diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.cpp b/mozilla/extensions/xforms/nsXFormsControlStub.cpp index 2faee0fe9e1..25c610b2bf8 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.cpp +++ b/mozilla/extensions/xforms/nsXFormsControlStub.cpp @@ -148,26 +148,27 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute, // Clear existing bound node, etc. mBoundNode = nsnull; mUsesModelBinding = PR_FALSE; + mAppearDisabled = PR_FALSE; mDependencies.Clear(); RemoveIndexListeners(); - if (!mHasParent || !mBindAttrsCount) + if (!mHasParent || !HasBindingAttribute()) return NS_OK; nsCOMPtr result; - nsresult rv = - ProcessNodeBinding(aBindAttribute, - aResultType, - getter_AddRefs(result)); + nsresult rv = ProcessNodeBinding(aBindAttribute, aResultType, + getter_AddRefs(result)); if (NS_FAILED(rv)) { nsXFormsUtils::ReportError(NS_LITERAL_STRING("controlBindError"), mElement); return rv; } - - if (!result) + + if (rv == NS_OK_XFORMS_DEFERRED || !result) { + // Binding was deferred, or not bound return NS_OK; - + } + // Get context node, if any if (mUsesModelBinding) { // When bound via @bind, we'll get a snapshot back @@ -176,24 +177,21 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute, result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); } - if (mBoundNode && mModel) { - mModel->SetStates(this, mBoundNode); - } else if (mModel) { - // we should have been successful. Must be pointing to a node that - // doesn't exist in the instance document. Disable the control - // per 4.2.2 in the spec + if (!mBoundNode) { + // If there's no result (ie, no instance node) returned by the above, it + // means that the binding is not pointing to an instance data node, so we + // should disable the control. + mAppearDisabled = PR_TRUE; - nsCOMPtr xtfWrap(do_QueryInterface(mElement)); - NS_ENSURE_STATE(xtfWrap); - xtfWrap->SetIntrinsicState(NS_EVENT_STATE_DISABLED); + nsCOMPtr wrapper(do_QueryInterface(mElement)); + NS_ENSURE_STATE(wrapper); - // Dispatch event - nsXFormsUtils::DispatchEvent(mElement, eEvent_Disabled); + return wrapper->SetIntrinsicState(kDisabledIntrinsicState); } if (aResult) { *aResult = nsnull; - result.swap(*aResult); + result.swap(*aResult); // transfers ref } return NS_OK; @@ -206,6 +204,15 @@ nsXFormsControlStubBase::Bind() nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE); } +NS_IMETHODIMP +nsXFormsControlStubBase::Refresh() +{ + // XXX: In theory refresh should never be called when there is no model, + // but that's definately not the case now. + return (mModel && !mAppearDisabled) ? mModel->SetStates(this, mBoundNode) + : NS_OK; +} + NS_IMETHODIMP nsXFormsControlStubBase::TryFocus(PRBool* aOK) { @@ -258,6 +265,14 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt { nsStringArray indexesUsed; + if (aResult) { + *aResult = nsnull; + } + + if (aModel) { + *aModel = nsnull; + } + // let's not go through all of this rigamarol if we don't have a chance // in heck of binding anyhow. Check to see if the models will be receptive // to some binding. readyForBindProperty is set when they are. Make sure @@ -269,7 +284,7 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt if (!nsXFormsUtils::IsDocumentReadyForBind(domDoc)) { nsXFormsModelElement::DeferElementBind(domDoc, this); - return NS_OK; + return NS_OK_XFORMS_DEFERRED; } nsresult rv; @@ -287,6 +302,7 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt getter_AddRefs(parentControl), &mDependencies, &indexesUsed); + NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_STATE(mModel); rv = MaybeAddToModel(oldModel, parentControl); @@ -555,25 +571,23 @@ nsXFormsControlStubBase::ForceModelRebind() } nsresult rv = Bind(); NS_ENSURE_SUCCESS(rv, rv); - return Refresh(); + return rv == NS_OK_XFORMS_DEFERRED ? NS_OK : Refresh(); } nsresult nsXFormsControlStubBase::DocumentChanged(nsIDOMDocument *aNewDocument) { - // We need to re-evaluate our instance data binding when our document - // changes, since our context can change - - if (aNewDocument) { - // The intrinsic state needs to be initialized here since - // SetIntrinsicState will do nothing until the element lives in a document. - ResetProperties(); - - return ForceModelRebind(); + // If we are inserted into a document and we have no model, we are probably + // being initialized, so we should set our intrinsic state to the default + // value + if (aNewDocument && !mModel && mElement) { + nsCOMPtr xtfWrap(do_QueryInterface(mElement)); + NS_ENSURE_STATE(xtfWrap); + xtfWrap->SetIntrinsicState(kDefaultIntrinsicState); } - return NS_OK; + return ForceModelRebind(); } nsresult @@ -582,7 +596,7 @@ nsXFormsControlStubBase::ParentChanged(nsIDOMElement *aNewParent) mHasParent = aNewParent != nsnull; // We need to re-evaluate our instance data binding when our parent changes, // since xmlns declarations or our context could have changed. - return mHasParent ? ForceModelRebind() : NS_OK; + return ForceModelRebind(); } nsresult @@ -663,18 +677,6 @@ nsXFormsControlStubBase::GetContext(nsAString &aModelID, return NS_OK; } -void -nsXFormsControlStubBase::ResetProperties() -{ - nsCOMPtr xtfWrap(do_QueryInterface(mElement)); - if (!xtfWrap) { - return; - } - - // enabled is on pr. default - xtfWrap->SetIntrinsicState(NS_EVENT_STATE_ENABLED); -} - void nsXFormsControlStubBase::AddRemoveSNBAttr(nsIAtom *aName, const nsAString &aValue) { @@ -691,9 +693,6 @@ nsXFormsControlStubBase::AddRemoveSNBAttr(nsIAtom *aName, const nsAString &aValu // empty value, treat it like the binding attr is being removed. --mBindAttrsCount; NS_ASSERTION(mBindAttrsCount>=0, "bad mojo! mBindAttrsCount < 0!"); - if (!mBindAttrsCount) { - ResetProperties(); - } } } @@ -713,8 +712,9 @@ void nsXFormsControlStubBase::AfterSetAttribute(nsIAtom *aName) { if (IsBindingAttribute(aName)) { - Bind(); - Refresh(); + nsresult rv = Bind(); + if (NS_SUCCEEDED(rv) && rv != NS_OK_XFORMS_DEFERRED) + Refresh(); } } diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.h b/mozilla/extensions/xforms/nsXFormsControlStub.h index f0fd11f70c6..b040db30216 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.h +++ b/mozilla/extensions/xforms/nsXFormsControlStub.h @@ -87,6 +87,7 @@ public: PRUint16 aResultType, nsIDOMXPathResult **aResult = nsnull); NS_IMETHOD Bind(); + NS_IMETHOD Refresh(); NS_IMETHOD TryFocus(PRBool* aOK); NS_IMETHOD IsEventTarget(PRBool *aOK); NS_IMETHOD GetUsesModelBinding(PRBool *aRes); @@ -142,6 +143,7 @@ public: mHasParent(PR_FALSE), mPreventLoop(PR_FALSE), mUsesModelBinding(PR_FALSE), + mAppearDisabled(PR_FALSE), mBindAttrsCount(0) {}; @@ -174,6 +176,12 @@ protected: */ PRPackedBool mUsesModelBinding; + /** + * Should the control appear disabled. This is f.x. used when a valid single + * node binding is not pointing to an instance data node. + */ + PRPackedBool mAppearDisabled; + /** * Array of repeat-elements of which the control uses repeat-index. */ @@ -185,12 +193,25 @@ protected: */ PRInt32 mBindAttrsCount; + /** + * Does control have a binding attribute? + */ + PRBool HasBindingAttribute() const { return mBindAttrsCount != 0; }; + /** Returns the relevant state of the control */ PRBool GetRelevantState(); /** - * Processes the node binding of a control, get the current MDG (mMDG) and - * binds the control to its model. + * Processes the node binding of a control, get the current Model (mModel) + * and binds the control to it. + * + * @note Will return NS_OK_XFORMS_DEFERRED if the binding is being + * deferred. + * + * @param aBindingAttr The default binding attribute + * @param aResultType The XPath result type requested + * @param aResult The XPath result + * @param aModel The model */ nsresult ProcessNodeBinding(const nsString &aBindingAttr, @@ -204,12 +225,6 @@ protected: */ void ResetHelpAndHint(PRBool aInitialize); - /** - * Removes all of the attributes that may have been added to the control due - * to binding with an instance node. - */ - void ResetProperties(); - /** * Checks whether an attribute is a binding attribute for the control. This * should be overriden by controls that have "non-standard" binding diff --git a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp index e1dd8925b97..70ad7681958 100644 --- a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp +++ b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp @@ -110,6 +110,9 @@ nsXFormsDelegateStub::Refresh() return NS_OK_XFORMS_NOREFRESH; } + nsresult rv = nsXFormsBindableControlStub::Refresh(); + NS_ENSURE_SUCCESS(rv, rv); + SetMozTypeAttribute(); nsCOMPtr widget = do_QueryInterface(mElement); @@ -193,7 +196,7 @@ nsXFormsDelegateStub::WidgetAttached() if (UpdateRepeatState() == eType_Template) return NS_OK; - if (mBindAttrsCount) { + if (HasBindingAttribute()) { // If control is bounded to instance data then we should ask for refresh // only when model is loaded entirely. The reason is control is refreshed // by model when it get loaded. diff --git a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp index badcc3e623c..13a1c97232d 100644 --- a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp @@ -134,9 +134,11 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, nsCOMPtr contextNode; nodeset->SnapshotItem(0, getter_AddRefs(contextNode)); - nsCOMPtr at = - nsXFormsUtils::EvaluateXPath(atExpr, contextNode, mElement, - nsIDOMXPathResult::NUMBER_TYPE, 1, setSize); + nsCOMPtr at; + rv = nsXFormsUtils::EvaluateXPath(atExpr, contextNode, mElement, + nsIDOMXPathResult::NUMBER_TYPE, + getter_AddRefs(at), 1, setSize); + NS_ENSURE_SUCCESS(rv, rv); if (!at) return NS_OK; diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.cpp b/mozilla/extensions/xforms/nsXFormsModelElement.cpp index f35b01d3364..19988617a2b 100644 --- a/mozilla/extensions/xforms/nsXFormsModelElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsModelElement.cpp @@ -102,12 +102,14 @@ GetSchemaElementById(nsIDOMElement *contextNode, expr.Append(id); expr.AppendLiteral("\"]"); - nsCOMPtr xpRes = - nsXFormsUtils::EvaluateXPath(expr, - contextNode, - contextNode, - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE); - if (xpRes) { + nsCOMPtr xpRes; + nsresult rv = + nsXFormsUtils::EvaluateXPath(expr, + contextNode, + contextNode, + nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, + getter_AddRefs(xpRes)); + if (NS_SUCCEEDED(rv) && xpRes) { nsCOMPtr node; xpRes->GetSingleNodeValue(getter_AddRefs(node)); if (node) { @@ -1028,14 +1030,11 @@ nsXFormsModelElement::SetSingleState(nsIDOMElement *aElement, nsXFormsUtils::DispatchEvent(aElement, event); } -nsresult -nsXFormsModelElement::SetStatesInternal(nsIXFormsControl *aControl, - nsIDOMNode *aNode, - PRBool aDispatchEvents) +NS_IMETHODIMP +nsXFormsModelElement::SetStates(nsIXFormsControl *aControl, + nsIDOMNode *aNode) { NS_ENSURE_ARG(aControl); - if (!aNode) - return NS_OK; nsCOMPtr element; aControl->GetElement(getter_AddRefs(element)); @@ -1044,13 +1043,22 @@ nsXFormsModelElement::SetStatesInternal(nsIXFormsControl *aControl, nsCOMPtr xtfWrap(do_QueryInterface(element)); NS_ENSURE_STATE(xtfWrap); - const nsXFormsNodeState *ns = mMDG.GetNodeState(aNode); - NS_ENSURE_STATE(ns); - - nsresult rv = xtfWrap->SetIntrinsicState(ns->GetIntrinsicState()); + PRInt32 iState; + const nsXFormsNodeState* ns = nsnull; + if (aNode) { + ns = mMDG.GetNodeState(aNode); + NS_ENSURE_STATE(ns); + iState = ns->GetIntrinsicState(); + } else { + iState = kDefaultIntrinsicState; + } + + nsresult rv = xtfWrap->SetIntrinsicState(iState); NS_ENSURE_SUCCESS(rv, rv); - if (!aDispatchEvents) + // Event dispatching is defined by the bound node, so if there's no bound + // node, there are no events to send. + if (!ns) return NS_OK; if (ns->ShouldDispatchValid()) { @@ -1229,8 +1237,6 @@ nsXFormsModelElement::RefreshSubTree(nsXFormsControlListItem *aCurrent, // Handle refreshing if (rebind || refresh) { - rv = SetStatesInternal(control, boundNode); - NS_ENSURE_SUCCESS(rv, rv); control->Refresh(); // XXX: we should really check the return result, but f.x. select1 // returns error because of no widget...? so we should ensure that an @@ -1957,10 +1963,6 @@ nsXFormsModelElement::InitializeControls() rv = control->GetBoundNode(getter_AddRefs(boundNode)); NS_ENSURE_SUCCESS(rv, rv); - // Set MIP states on control - rv = SetStatesInternal(control, boundNode, PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - // Refresh controls rv = control->Refresh(); NS_ENSURE_SUCCESS(rv, rv); @@ -2271,12 +2273,6 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator, } NS_IMETHODIMP -nsXFormsModelElement::SetStates(nsIXFormsControl *aControl, nsIDOMNode *aBoundNode) -{ - return SetStatesInternal(aControl, aBoundNode, PR_FALSE); -} - -nsresult nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate *aInstEle) { NS_ENSURE_STATE(mInstanceDocuments); @@ -2285,7 +2281,7 @@ nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate *aInstEle) return NS_OK; } -nsresult +NS_IMETHODIMP nsXFormsModelElement::RemoveInstanceElement(nsIInstanceElementPrivate *aInstEle) { NS_ENSURE_STATE(mInstanceDocuments); @@ -2294,7 +2290,7 @@ nsXFormsModelElement::RemoveInstanceElement(nsIInstanceElementPrivate *aInstEle) return NS_OK; } -nsresult +NS_IMETHODIMP nsXFormsModelElement::MessageLoadFinished() { // This is our signal that all external message links have been tested. If diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.h b/mozilla/extensions/xforms/nsXFormsModelElement.h index 20d20847396..ea156ce6e07 100644 --- a/mozilla/extensions/xforms/nsXFormsModelElement.h +++ b/mozilla/extensions/xforms/nsXFormsModelElement.h @@ -301,20 +301,6 @@ private: NS_HIDDEN_(void) RemoveModelFromDocument(); - /** - * Set the states on the control |aControl| bound to the instance data node - * |aNode|. It dispatches the necessary events and sets the pseudo class - * states. |aAllStates| determines whether all states should be set, or only - * changed. - * - * @param aControl The event target - * @param aNode The instance node - * @param aAllStates Set all states (PR_TRUE), or only changed - */ - NS_HIDDEN_(nsresult) SetStatesInternal(nsIXFormsControl *aControl, - nsIDOMNode *aNode, - PRBool aDispatchEvents = PR_TRUE); - /** * Sets the state of a specific state. * diff --git a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp index 76a011bd131..acab4e82a60 100755 --- a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp @@ -67,6 +67,10 @@ /** * Implementation of the XForms \ element. * + * \ is not really that different from \ + * (ie. nsXFormsDelegateStub), except that it has an "value" attribute that + * must be handled seperately because it is evaluated to a string result. + * * @see http://www.w3.org/TR/xforms/slice8.html#ui-output */ class nsXFormsOutputElement : public nsXFormsDelegateStub @@ -78,20 +82,23 @@ public: NS_IMETHOD GetBoundNode(nsIDOMNode **aBoundNode); // nsIXFormsDelegate - NS_IMETHOD GetValue(nsAString& aValue); + NS_IMETHOD GetValue(nsAString& aValue); + NS_IMETHOD SetValue(const nsAString& aValue); NS_IMETHOD GetHasBoundNode(PRBool *aHasBoundNode); nsXFormsOutputElement(); private: - PRPackedBool mHasBinding; - PRPackedBool mValueIsDirty; + // The value of the "value" attribute (if any). Updated by Bind() nsString mValue; + + // Use the "value" attribute + PRBool mUseValueAttribute; }; nsXFormsOutputElement::nsXFormsOutputElement() : nsXFormsDelegateStub(NS_LITERAL_STRING("output")), - mHasBinding(PR_FALSE), mValueIsDirty(PR_TRUE) + mUseValueAttribute(PR_FALSE) { } @@ -100,116 +107,96 @@ nsXFormsOutputElement::nsXFormsOutputElement() nsresult nsXFormsOutputElement::Bind() { - // Clear existing bound node, etc. - mBoundNode = nsnull; - mDependencies.Clear(); - RemoveIndexListeners(); + SetDOMStringToNull(mValue); + mUseValueAttribute = PR_FALSE; - if (!mHasParent) + nsresult rv = nsXFormsDelegateStub::Bind(); + NS_ENSURE_SUCCESS(rv, rv); + + if (!mHasParent || !mElement || rv == NS_OK_XFORMS_DEFERRED) return NS_OK; - PRBool tmp; - nsresult rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &tmp); - NS_ENSURE_SUCCESS(rv, rv); - mHasBinding = tmp; - if (!mHasBinding) { - rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &tmp); + // Besides the standard single node binding (SNB) attributes, \ + // also has a "value" attribute, which is used when there are not other SNB + // attributes. + if (!HasBindingAttribute()) { + mUseValueAttribute = PR_TRUE; + } else { + PRBool hasAttr; + rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &hasAttr); NS_ENSURE_SUCCESS(rv, rv); - mHasBinding = tmp; - - if (!mHasBinding) { - // If output only has a value attribute, it can't have a proper single - // node binding. In an effort to streamline this a bit, we'll just bind - // to the model here and add output to the deferred bind list if - // necessary. This should be all that we need from the services that - // ProcessNodeBinding provides. ProcessNodeBinding is called during - // ::Refresh (via GetValue) so we just need a few things set up before - // ::Refresh gets called (usually right after ::Bind) - - nsCOMPtr domDoc; - mElement->GetOwnerDocument(getter_AddRefs(domDoc)); - if (!nsXFormsUtils::IsDocumentReadyForBind(domDoc)) { - nsXFormsModelElement::DeferElementBind(domDoc, this); - } - - return BindToModel(PR_TRUE); + if (!hasAttr) { + rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &hasAttr); + NS_ENSURE_SUCCESS(rv, rv); + mUseValueAttribute = !hasAttr; } } + if (!mUseValueAttribute) + return NS_OK; + + // Bind to model and set mBoundNode . The bound node is used for setting + // context for our children (our parent's context in the case of @value), + // and the call to ProcessNodeBinding() will not set it. + rv = BindToModel(PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + + // Process node binding nsCOMPtr result; - rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, + rv = ProcessNodeBinding(NS_LITERAL_STRING("value"), + nsIDOMXPathResult::STRING_TYPE, getter_AddRefs(result)); - - if (NS_FAILED(rv)) { - nsXFormsUtils::ReportError(NS_LITERAL_STRING("controlBindError"), mElement); - return rv; + NS_ENSURE_SUCCESS(rv, rv); + + if (rv == NS_OK_XFORMS_DEFERRED) { + return NS_OK; } if (result) { - if (mUsesModelBinding) { - // When bound via @bind, we'll get a snapshot back - result->SnapshotItem(0, getter_AddRefs(mBoundNode)); - } else { - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); - } + rv = result->GetStringValue(mValue); + NS_ENSURE_SUCCESS(rv, rv); } - if (mBoundNode && mModel) { - mModel->SetStates(this, mBoundNode); - } - - return rv; + return NS_OK; } NS_IMETHODIMP nsXFormsOutputElement::Refresh() { - mValueIsDirty = PR_TRUE; return nsXFormsDelegateStub::Refresh(); } NS_IMETHODIMP nsXFormsOutputElement::GetBoundNode(nsIDOMNode **aBoundNode) { - return mHasBinding ? nsXFormsDelegateStub::GetBoundNode(aBoundNode) : NS_OK; + return !mUseValueAttribute ? nsXFormsDelegateStub::GetBoundNode(aBoundNode) + : NS_OK; } NS_IMETHODIMP nsXFormsOutputElement::GetHasBoundNode(PRBool *aHasBoundNode) { NS_ENSURE_ARG_POINTER(aHasBoundNode); - *aHasBoundNode = (mBoundNode && mHasBinding) ? PR_TRUE : PR_FALSE; + *aHasBoundNode = (mBoundNode && !mUseValueAttribute) ? PR_TRUE : PR_FALSE; return NS_OK; } NS_IMETHODIMP nsXFormsOutputElement::GetValue(nsAString& aValue) { - NS_ENSURE_STATE(mModel); - - if (mValueIsDirty) { - if (mHasBinding) { - NS_ENSURE_STATE(mBoundNode); - nsXFormsUtils::GetNodeValue(mBoundNode, mValue); - } else { - nsCOMPtr result; - nsresult rv = ProcessNodeBinding(NS_LITERAL_STRING("value"), - nsIDOMXPathResult::STRING_TYPE, - getter_AddRefs(result)); - NS_ENSURE_SUCCESS(rv, rv); - - if (result) { - SetDOMStringToNull(mValue); - rv = result->GetStringValue(mValue); - NS_ENSURE_SUCCESS(rv, rv); - } - } - mValueIsDirty = PR_FALSE; + if (mUseValueAttribute) { + aValue = mValue; + return NS_OK; } - aValue = mValue; - return NS_OK; + return nsXFormsDelegateStub::GetValue(aValue); +} + +NS_IMETHODIMP +nsXFormsOutputElement::SetValue(const nsAString& aValue) +{ + // Setting the value on an output controls seems wrong semantically. + return NS_ERROR_NOT_AVAILABLE; } NS_HIDDEN_(nsresult) diff --git a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp index 39582adb5a2..49600a32d46 100644 --- a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp @@ -77,26 +77,27 @@ nsXFormsSetValueElement::HandleAction(nsIDOMEvent* aEvent, nsAutoString value; nsAutoString valueAttr; + nsresult rv; mElement->GetAttribute(NS_LITERAL_STRING("value"), valueAttr); - if(!valueAttr.IsEmpty()) { + if (!valueAttr.IsEmpty()) { // According to the XForms Errata, the context node for the XPath expression // stored in @value should be the node that setvalue is bound to. - nsCOMPtr xpResult = - nsXFormsUtils::EvaluateXPath(valueAttr, singleNode, mElement, - nsIDOMXPathResult::STRING_TYPE); + nsCOMPtr xpResult; + rv = nsXFormsUtils::EvaluateXPath(valueAttr, singleNode, mElement, + nsIDOMXPathResult::STRING_TYPE, + getter_AddRefs(xpResult)); + NS_ENSURE_SUCCESS(rv, rv); if (!xpResult) return NS_OK; xpResult->GetStringValue(value); - } - else { + } else { nsCOMPtr n3(do_QueryInterface(mElement)); n3->GetTextContent(value); } PRBool changed; - nsresult rv = - modelPriv->SetNodeValue(singleNode, value, &changed); + rv = modelPriv->SetNodeValue(singleNode, value, &changed); NS_ENSURE_SUCCESS(rv, rv); if (changed) { diff --git a/mozilla/extensions/xforms/nsXFormsUtils.cpp b/mozilla/extensions/xforms/nsXFormsUtils.cpp index 480eb7de76f..c1cfb043d06 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.cpp +++ b/mozilla/extensions/xforms/nsXFormsUtils.cpp @@ -97,6 +97,7 @@ #include "nsIDOMDocumentType.h" #include "nsIDOMEntity.h" #include "nsIDOMNotation.h" +#include "nsIEventStateManager.h" #define CANCELABLE 0x01 #define BUBBLES 0x02 @@ -182,6 +183,18 @@ static const EventData sEventDefaultsEntries[] = { static nsDataHashtable sXFormsEvents; static nsDataHashtable sEventDefaults; +const PRInt32 kDefaultIntrinsicState = + NS_EVENT_STATE_ENABLED | + NS_EVENT_STATE_VALID | + NS_EVENT_STATE_OPTIONAL | + NS_EVENT_STATE_MOZ_READWRITE; + +const PRInt32 kDisabledIntrinsicState = + NS_EVENT_STATE_DISABLED | + NS_EVENT_STATE_VALID | + NS_EVENT_STATE_OPTIONAL | + NS_EVENT_STATE_MOZ_READWRITE; + /* static */ nsresult nsXFormsUtils::Init() { @@ -395,26 +408,27 @@ nsXFormsUtils::GetModel(nsIDOMElement *aElement, return result; } -/* static */ already_AddRefed +/* static */ nsresult nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, nsIDOMNode *aContextNode, nsIDOMNode *aResolverNode, PRUint16 aResultType, + nsIDOMXPathResult **aResult, PRInt32 aContextPosition, PRInt32 aContextSize, nsCOMArray *aSet, nsStringArray *aIndexesUsed) { + NS_ENSURE_ARG_POINTER(aResult); + *aResult = nsnull; + nsCOMPtr eval = do_CreateInstance("@mozilla.org/dom/xforms-xpath-evaluator;1"); - NS_ENSURE_TRUE(eval, nsnull); + NS_ENSURE_STATE(eval); nsCOMPtr expression; - eval->CreateExpression(aExpression, - aResolverNode, + nsresult rv = eval->CreateExpression(aExpression, aResolverNode, getter_AddRefs(expression)); - - nsIDOMXPathResult *result = nsnull; PRBool throwException = PR_FALSE; if (!expression) { const nsPromiseFlatString& flat = PromiseFlatString(aExpression); @@ -424,12 +438,12 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, throwException = PR_TRUE; } else { nsCOMPtr supResult; - nsresult rv = expression->EvaluateWithContext(aContextNode, - aContextPosition, - aContextSize, - aResultType, - nsnull, - getter_AddRefs(supResult)); + rv = expression->EvaluateWithContext(aContextNode, + aContextPosition, + aContextSize, + aResultType, + nsnull, + getter_AddRefs(supResult)); if (NS_SUCCEEDED(rv) && supResult) { /// @todo beaufour: This is somewhat "hackish". Hopefully, this will @@ -447,13 +461,17 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, aContextPosition, aContextSize, aResultType == nsIDOMXPathResult::STRING_TYPE); - NS_ENSURE_SUCCESS(rv, nsnull); + NS_ENSURE_SUCCESS(rv, rv); if (aIndexesUsed) *aIndexesUsed = analyzer.IndexesUsed(); } - CallQueryInterface(supResult, &result); // addrefs - } else if (rv == NS_ERROR_XFORMS_CALCUATION_EXCEPTION) { + + CallQueryInterface(supResult, aResult); // addrefs + return NS_OK; + } + + if (rv == NS_ERROR_XFORMS_CALCUATION_EXCEPTION) { const nsPromiseFlatString& flat = PromiseFlatString(aExpression); const PRUnichar *strings[] = { flat.get() }; nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprEvaluateError"), @@ -470,7 +488,7 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, DispatchEvent(model, eEvent_ComputeException); } - return result; + return rv; } /* static */ nsresult @@ -527,17 +545,17 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, NS_STATIC_CAST(nsIDOMXPathResult*, content->GetProperty(nsXFormsAtoms::bind))); *aUsesModelBind = PR_TRUE; - } else { - // References to inner binds are not defined. - // "When you refer to @id on a nested bind it returns an emtpy nodeset - // because it has no meaning. The XForms WG will assign meaning in the - // future." - // @see http://www.w3.org/MarkUp/Group/2004/11/f2f/2004Nov11#resolution6 - nsXFormsUtils::ReportError(NS_LITERAL_STRING("innerBindRefError"), - aElement); + return NS_OK; } - return NS_OK; + // References to inner binds are not defined. + // "When you refer to @id on a nested bind it returns an emtpy nodeset + // because it has no meaning. The XForms WG will assign meaning in the + // future." + // @see http://www.w3.org/MarkUp/Group/2004/11/f2f/2004Nov11#resolution6 + nsXFormsUtils::ReportError(NS_LITERAL_STRING("innerBindRefError"), + aElement); + return NS_ERROR_FAILURE; } @@ -556,14 +574,11 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, } // Evaluate |expr| - nsCOMPtr res = EvaluateXPath(expr, - contextNode, - aElement, - aResultType, - contextPosition, - contextSize, - aDeps, - aIndexesUsed); + nsCOMPtr res; + rv = EvaluateXPath(expr, contextNode, aElement, aResultType, + getter_AddRefs(res), contextPosition, contextSize, + aDeps, aIndexesUsed); + NS_ENSURE_SUCCESS(rv, rv); //////////////////// // STEP 3: Check for lazy binding @@ -623,9 +638,10 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, // now that we inserted the lazy authored node, try to bind // again - res = EvaluateXPath(expr, contextNode, aElement, aResultType, - contextPosition, contextSize, aDeps, - aIndexesUsed); + rv = EvaluateXPath(expr, contextNode, aElement, aResultType, + getter_AddRefs(res), contextPosition, + contextSize, aDeps, aIndexesUsed); + NS_ENSURE_SUCCESS(rv, rv); } else { const PRUnichar *strings[] = { expr.get() }; nsXFormsUtils::ReportError(NS_LITERAL_STRING("invalidQName"), diff --git a/mozilla/extensions/xforms/nsXFormsUtils.h b/mozilla/extensions/xforms/nsXFormsUtils.h index 522026726f0..f8612f20918 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.h +++ b/mozilla/extensions/xforms/nsXFormsUtils.h @@ -72,6 +72,8 @@ class nsIDOMEvent; #define NS_OK_XFORMS_NOREFRESH \ NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 1) +#define NS_OK_XFORMS_DEFERRED \ +NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 2) /** * XForms event types @@ -136,6 +138,12 @@ struct EventData extern const EventData sXFormsEventsEntries[42]; +// Default intrinsic state for XForms Controls +extern const PRInt32 kDefaultIntrinsicState; + +// Disabled intrinsic state for XForms Controls +extern const PRInt32 kDisabledIntrinsicState; + /** * This class has static helper methods that don't fit into a specific place * in the class hierarchy. @@ -246,11 +254,12 @@ public: * nsIXFormsXPathEvaluator::Evalute using the given expression, context node, * namespace resolver, and result type. */ - static NS_HIDDEN_(already_AddRefed) + static NS_HIDDEN_(nsresult) EvaluateXPath(const nsAString &aExpression, nsIDOMNode *aContextNode, nsIDOMNode *aResolverNode, PRUint16 aResultType, + nsIDOMXPathResult **aResult, PRInt32 aContextPosition = 1, PRInt32 aContextSize = 1, nsCOMArray *aSet = nsnull,