diff --git a/mozilla/extensions/xforms/nsXFormsContextContainer.cpp b/mozilla/extensions/xforms/nsXFormsContextContainer.cpp index ad378e6caf5..9587166cfa1 100644 --- a/mozilla/extensions/xforms/nsXFormsContextContainer.cpp +++ b/mozilla/extensions/xforms/nsXFormsContextContainer.cpp @@ -137,6 +137,9 @@ public: nsresult HandleFocus(nsIDOMEvent *aEvent); + // Overriding to make sure only appropriate values can be set. + void SetRepeatState(nsRepeatState aState); + #ifdef DEBUG_smaug virtual const char* Name() { if (mElement) { @@ -362,6 +365,21 @@ nsXFormsContextContainer::GetContextPosition(PRInt32 *aContextPosition) return NS_OK; } +void +nsXFormsContextContainer::SetRepeatState(nsRepeatState aState) +{ + // A context container can have one of two states...eType_Unknown + // (uninitialized) and eType_GeneratedContent. This assumes + // that one cannot be generated outside of the repeat or itemset code. + + nsRepeatState state = aState; + if (state != eType_Unknown) { + state = eType_GeneratedContent; + } + + return nsXFormsControlStub::SetRepeatState(state); +} + // Factory NS_HIDDEN_(nsresult) NS_NewXFormsContextContainer(nsIXTFElement **aResult) diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.cpp b/mozilla/extensions/xforms/nsXFormsControlStub.cpp index 95d8a5e1551..c577dd0aa50 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.cpp +++ b/mozilla/extensions/xforms/nsXFormsControlStub.cpp @@ -303,6 +303,12 @@ nsresult nsXFormsControlStub::MaybeAddToModel(nsIModelElementPrivate *aOldModel, nsIXFormsControl *aParent) { + if (GetRepeatState() == eType_Template) { + // No sense going any further. A template control has no need to bind, + // refresh, etc. so no reason to put it on the model's control list + return NS_OK; + } + // XXX: just doing pointer comparison would be nice.... PRBool sameModel = PR_FALSE; nsresult rv; @@ -410,6 +416,12 @@ nsXFormsControlStub::ProcessNodeBinding(const nsString &aBindingAttr, NS_IMETHODIMP nsXFormsControlStub::BindToModel(PRBool aSetBoundNode) { + if (GetRepeatState() == eType_Template) { + // No sense going any further. A template control has no need to bind, + // refresh, etc. so no reason to put it on the model's control list + return NS_OK; + } + nsCOMPtr oldModel(mModel); nsCOMPtr parentControl; @@ -654,6 +666,7 @@ nsXFormsControlStub::ForceModelDetach(PRBool aRebind) NS_IMETHODIMP nsXFormsControlStub::WillChangeDocument(nsIDOMDocument *aNewDocument) { + SetRepeatState(eType_Unknown); ResetHelpAndHint(PR_FALSE); return NS_OK; } @@ -679,10 +692,21 @@ nsXFormsControlStub::DocumentChanged(nsIDOMDocument *aNewDocument) return ForceModelDetach(mHasParent && aNewDocument); } +NS_IMETHODIMP +nsXFormsControlStub::WillChangeParent(nsIDOMElement *aNewParent) +{ + SetRepeatState(eType_Unknown); + return NS_OK; +} + + NS_IMETHODIMP nsXFormsControlStub::ParentChanged(nsIDOMElement *aNewParent) { mHasParent = aNewParent != nsnull; + + UpdateRepeatState(aNewParent); + // We need to re-evaluate our instance data binding when our parent changes, // since xmlns declarations or our context could have changed. return ForceModelDetach(mHasParent); @@ -866,6 +890,47 @@ nsXFormsControlStub::IsContentComplex() return isComplex; } +nsRepeatState +nsXFormsControlStub::GetRepeatState() +{ + return mRepeatState; +} + +void +nsXFormsControlStub::SetRepeatState(nsRepeatState aState) +{ + mRepeatState = aState; + return; +} + +nsRepeatState +nsXFormsControlStub::UpdateRepeatState(nsIDOMNode *aParent) +{ + nsRepeatState repeatState = eType_NotApplicable; + + nsCOMPtr parent = aParent; + while (parent) { + if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("contextcontainer"))) { + repeatState = eType_GeneratedContent; + break; + } + if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("repeat"))) { + repeatState = eType_Template; + break; + } + if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("itemset"))) { + repeatState = eType_Template; + break; + } + nsCOMPtr tmp; + parent->GetParentNode(getter_AddRefs(tmp)); + parent = tmp; + } + + SetRepeatState(repeatState); + return repeatState; +} + NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsControlStub, nsXFormsStubElement, nsIXFormsContextControl, diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.h b/mozilla/extensions/xforms/nsXFormsControlStub.h index e55f686327e..44d5228a275 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.h +++ b/mozilla/extensions/xforms/nsXFormsControlStub.h @@ -60,6 +60,18 @@ class nsIDOMEvent; class nsIDOMXPathResult; +/** + * nsRepeatState is used to indicate whether the element + * is inside \'s template. If it is, there is no need + * to refresh the widget bound to the element. + */ +enum nsRepeatState { + eType_Unknown, + eType_Template, + eType_GeneratedContent, + eType_NotApplicable +}; + /** * Common stub for all XForms controls that inherit from nsIXFormsControl and * is bound to an instance node. @@ -105,6 +117,7 @@ public: NS_IMETHOD OnDestroyed(); NS_IMETHOD WillChangeDocument(nsIDOMDocument *aNewDocument); NS_IMETHOD DocumentChanged(nsIDOMDocument *aNewDocument); + NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue); NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue); @@ -144,6 +157,14 @@ public: */ virtual PRBool IsContentComplex(); + /** + * Get/Set the repeat state for the control. The repeat state indicates + * whether the control lives inside a context container, a repeat element, + * an itemset or non of the above. + */ + virtual nsRepeatState GetRepeatState(); + virtual void SetRepeatState(nsRepeatState aState); + // nsIXFormsContextControl NS_DECL_NSIXFORMSCONTEXTCONTROL @@ -160,6 +181,7 @@ public: nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED | nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT | nsIXTFElement::NOTIFY_DOCUMENT_CHANGED | + nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT | nsIXTFElement::NOTIFY_PARENT_CHANGED | nsIXTFElement::NOTIFY_HANDLE_DEFAULT), kElementFlags(nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR), @@ -168,7 +190,8 @@ public: mUsesModelBinding(PR_FALSE), mAppearDisabled(PR_FALSE), mOnDeferredBindList(PR_FALSE), - mBindAttrsCount(0) + mBindAttrsCount(0), + mRepeatState(eType_Unknown) {}; protected: @@ -217,6 +240,8 @@ protected: */ PRInt8 mBindAttrsCount; + nsRepeatState mRepeatState; + /** * List of repeats that the node binding depends on. This happens when using * the index() function in the binding expression. @@ -305,6 +330,16 @@ protected: * bound. */ nsresult GetBoundBuiltinType(PRUint16 *aBuiltinType); + + /** + * This is called when the parent node for a XForms control changes. + * It checks the ancestors of the element and returns an nsRepeatState + * depending on the element's place in the document. + * + * @param aParent The new parent of the XForms control + */ + nsRepeatState UpdateRepeatState(nsIDOMNode *aParent); + }; #endif diff --git a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp index 4a6a5b48806..b6d0b28205b 100644 --- a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp +++ b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp @@ -61,19 +61,6 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsDelegateStub, nsIXFormsDelegate) -NS_IMETHODIMP -nsXFormsDelegateStub::WillChangeDocument(nsIDOMDocument *aNewDocument) -{ - mRepeatState = eType_Unknown; - return nsXFormsControlStub::WillChangeDocument(aNewDocument); -} - -NS_IMETHODIMP -nsXFormsDelegateStub::WillChangeParent(nsIDOMElement *aNewParent) -{ - mRepeatState = eType_Unknown; - return nsXFormsControlStub::WillChangeParent(aNewParent); -} NS_IMETHODIMP nsXFormsDelegateStub::GetAccesskeyNode(nsIDOMAttr** aNode) @@ -99,7 +86,6 @@ nsXFormsDelegateStub::OnCreated(nsIXTFElementWrapper *aWrapper) nsresult rv = nsXFormsControlStub::OnCreated(aWrapper); NS_ENSURE_SUCCESS(rv, rv); aWrapper->SetNotificationMask(kStandardNotificationMask | - nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT | nsIXTFElement::NOTIFY_PERFORM_ACCESSKEY); return rv; } @@ -119,7 +105,7 @@ nsXFormsDelegateStub::OnDestroyed() NS_IMETHODIMP nsXFormsDelegateStub::Refresh() { - if (mRepeatState == eType_Template) + if (GetRepeatState() == eType_Template) return NS_OK_XFORMS_NOREFRESH; const nsVoidArray* list = nsPostRefresh::PostRefreshList(); @@ -205,7 +191,7 @@ nsXFormsDelegateStub::ReportErrorMessage(const nsAString& aErrorMsg) NS_IMETHODIMP nsXFormsDelegateStub::WidgetAttached() { - if (UpdateRepeatState() == eType_Template) + if (GetRepeatState() == eType_Template) return NS_OK; if (HasBindingAttribute()) { @@ -235,32 +221,6 @@ nsXFormsDelegateStub::IsTypeAllowed(PRUint16 aType, PRBool *aIsAllowed, return NS_OK; } -nsRepeatState -nsXFormsDelegateStub::UpdateRepeatState() -{ - mRepeatState = eType_NotApplicable; - nsCOMPtr parent; - mElement->GetParentNode(getter_AddRefs(parent)); - while (parent) { - if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("contextcontainer"))) { - mRepeatState = eType_GeneratedContent; - break; - } - if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("repeat"))) { - mRepeatState = eType_Template; - break; - } - if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("itemset"))) { - mRepeatState = eType_Template; - break; - } - nsCOMPtr tmp; - parent->GetParentNode(getter_AddRefs(tmp)); - parent = tmp; - } - return mRepeatState; -} - void nsXFormsDelegateStub::SetMozTypeAttribute() { diff --git a/mozilla/extensions/xforms/nsXFormsDelegateStub.h b/mozilla/extensions/xforms/nsXFormsDelegateStub.h index 7f7841a6539..cef71c8d82b 100644 --- a/mozilla/extensions/xforms/nsXFormsDelegateStub.h +++ b/mozilla/extensions/xforms/nsXFormsDelegateStub.h @@ -51,18 +51,6 @@ class nsIAtom; -/** - * nsRepeatState is used to indicate whether the element - * is inside \'s template. If it is, there is no need - * to refresh the widget bound to the element. - */ -enum nsRepeatState { - eType_Unknown, - eType_Template, - eType_GeneratedContent, - eType_NotApplicable -}; - enum nsRestrictionFlag { eTypes_NoRestriction, eTypes_Inclusive, @@ -82,8 +70,6 @@ public: NS_IMETHOD OnCreated(nsIXTFElementWrapper *aWrapper); NS_IMETHOD OnDestroyed(); - NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); - NS_IMETHOD WillChangeDocument(nsIDOMDocument *aNewDocument); NS_IMETHOD GetAccesskeyNode(nsIDOMAttr** aNode); NS_IMETHOD PerformAccesskey(); @@ -124,21 +110,14 @@ public: nsXFormsDelegateStub(const nsAString& aType = EmptyString()) - : mControlType(aType), mRepeatState(eType_Unknown) {} + : mControlType(aType) {} protected: - // This is called when XBL widget is attached to the XForms control. - // It checks the ancestors of the element and returns an nsRepeatState - // depending on the elements place in the document. - nsRepeatState UpdateRepeatState(); - // Sets/removes the moz:type attribute. The attribute can be used to detect the // type of the node, which is bound the the control. void SetMozTypeAttribute(); nsString mControlType; - nsRepeatState mRepeatState; - /** The accessors object for this delegate */ nsRefPtr mAccessor; }; diff --git a/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp b/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp index 9e33b46a307..57f94f0bb8b 100644 --- a/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp @@ -99,6 +99,8 @@ nsXFormsItemSetElement::OnCreated(nsIXTFElementWrapper *aWrapper) NS_IMETHODIMP nsXFormsItemSetElement::ParentChanged(nsIDOMElement *aNewParent) { + UpdateRepeatState(aNewParent); + if (aNewParent) Refresh();