зеркало из https://github.com/mozilla/gecko-dev.git
XForms bug 284469 - Calling ProcessNodeBind unnecessarily. Patch by aaronr, r=beaufour,me, a=mkaply
This commit is contained in:
Родитель
34e5bd90c5
Коммит
3bbabc8a29
|
@ -111,7 +111,7 @@ nsXFormsControlStub::ResetBoundNode()
|
|||
{
|
||||
mBoundNode = nsnull;
|
||||
|
||||
if (!mHasParent)
|
||||
if (!mHasParent || !mBindAttrsCount)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIModelElementPrivate> modelNode;
|
||||
|
@ -354,26 +354,28 @@ nsXFormsControlStub::ParentChanged(nsIDOMElement *aNewParent)
|
|||
NS_IMETHODIMP
|
||||
nsXFormsControlStub::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::model ||
|
||||
aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::ref) {
|
||||
if (mModel)
|
||||
mModel->RemoveFormControl(this);
|
||||
}
|
||||
|
||||
MaybeRemoveFromModel(aName, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsControlStub::AttributeSet(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::model ||
|
||||
aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::ref) {
|
||||
Bind();
|
||||
Refresh();
|
||||
}
|
||||
MaybeBindAndRefresh(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsControlStub::WillRemoveAttribute(nsIAtom *aName)
|
||||
{
|
||||
MaybeRemoveFromModel(aName, EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsControlStub::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
MaybeBindAndRefresh(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -412,3 +414,71 @@ nsXFormsControlStub::GetContext(nsAString &aModelID,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsControlStub::ResetProperties()
|
||||
{
|
||||
if (!mElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("valid"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("invalid"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("enabled"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("disabled"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("required"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("optional"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("read-only"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("read-write"));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsControlStub::AddRemoveSNBAttr(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
nsAutoString attrStr, attrValue;
|
||||
aName->ToString(attrStr);
|
||||
mElement->GetAttribute(attrStr, attrValue);
|
||||
|
||||
// if we are setting a single node binding attribute that we don't already
|
||||
// have, bump the count.
|
||||
if (!aValue.IsEmpty() && attrValue.IsEmpty()) {
|
||||
++mBindAttrsCount;
|
||||
} else if (!attrValue.IsEmpty()) {
|
||||
// if we are setting a currently existing binding attribute to have an
|
||||
// empty value, treat it like the binding attr is being removed.
|
||||
--mBindAttrsCount;
|
||||
NS_ASSERTION(mBindAttrsCount>=0, "bad mojo! mBindAttrsCount < 0!");
|
||||
if (!mBindAttrsCount) {
|
||||
ResetProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsControlStub::MaybeBindAndRefresh(nsIAtom *aName)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::ref ||
|
||||
aName == nsXFormsAtoms::model) {
|
||||
|
||||
Bind();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsControlStub::MaybeRemoveFromModel(nsIAtom *aName,
|
||||
const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::model ||
|
||||
aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::ref) {
|
||||
if (mModel)
|
||||
mModel->RemoveFormControl(this);
|
||||
|
||||
if (aName != nsXFormsAtoms::model) {
|
||||
AddRemoveSNBAttr(aName, aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,26 @@ public:
|
|||
NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
|
||||
NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue);
|
||||
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
|
||||
NS_IMETHOD WillRemoveAttribute(nsIAtom *aName);
|
||||
NS_IMETHOD AttributeRemoved(nsIAtom *aName);
|
||||
|
||||
/**
|
||||
* This function manages the mBindAttrsCount value. mBindAttrsCount will
|
||||
* be incremented if a single node binding attribute is specified that isn't
|
||||
* currently on the control AND aValue isn't empty. Otherwise, if the control
|
||||
* already contains this attribute with a non-empty value and aValue is empty,
|
||||
* then mBindAttrsCount is decremented.
|
||||
*
|
||||
* aName - Atom of the single node binding attribute ('bind', 'ref', etc.).
|
||||
* Using an atom to make it a tad harder to misuse by passing in
|
||||
* any old string, for instance. Since different controls may have
|
||||
* different binding attrs, we do NO validation on the attr. We
|
||||
* assume that the caller is smart enough to only send us a
|
||||
* binding attr atom.
|
||||
* aValue - The string value that the SNB attribute is being set to.
|
||||
*
|
||||
*/
|
||||
void AddRemoveSNBAttr(nsIAtom *aName, const nsAString &aValue);
|
||||
|
||||
// nsIXFormsContextControl
|
||||
NS_DECL_NSIXFORMSCONTEXTCONTROL
|
||||
|
@ -111,11 +131,14 @@ public:
|
|||
nsXFormsControlStub() :
|
||||
kStandardNotificationMask(nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE |
|
||||
nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
|
||||
nsIXTFElement::NOTIFY_WILL_REMOVE_ATTRIBUTE |
|
||||
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
|
||||
nsIXTFElement::NOTIFY_DOCUMENT_CHANGED |
|
||||
nsIXTFElement::NOTIFY_PARENT_CHANGED |
|
||||
nsIXTFElement::NOTIFY_HANDLE_DEFAULT),
|
||||
kElementFlags(nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR),
|
||||
mHasParent(PR_FALSE)
|
||||
mHasParent(PR_FALSE),
|
||||
mBindAttrsCount(0)
|
||||
{};
|
||||
|
||||
protected:
|
||||
|
@ -137,6 +160,12 @@ protected:
|
|||
/** State that tells whether control has a parent or not */
|
||||
PRBool mHasParent;
|
||||
|
||||
/**
|
||||
* Used to keep track of whether this control has any single node binding
|
||||
* attributes.
|
||||
*/
|
||||
PRInt32 mBindAttrsCount;
|
||||
|
||||
/** Returns the read only state of the control (ie. mBoundNode) */
|
||||
PRBool GetReadOnlyState();
|
||||
|
||||
|
@ -167,6 +196,29 @@ protected:
|
|||
* xforms-hint and xforms-help events.
|
||||
*/
|
||||
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();
|
||||
|
||||
/**
|
||||
* Causes Bind() and Refresh() to be called if aName is the atom of a
|
||||
* single node binding attribute for this control. Called by AttributeSet
|
||||
* and AttributeRemoved.
|
||||
*/
|
||||
void MaybeBindAndRefresh(nsIAtom *aName);
|
||||
|
||||
/**
|
||||
* Removes this control from its model's list of controls if a single node
|
||||
* binding attribute is removed. Called by WillSetAttribute and
|
||||
* WillRemoveAttribute.
|
||||
*
|
||||
* @param aName - atom of the attribute being changed
|
||||
* @param aValue - value that the attribute is being changed to.
|
||||
*/
|
||||
void MaybeRemoveFromModel(nsIAtom *aName, const nsAString &aValue);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,7 @@ public:
|
|||
// nsIXTFElement overrides
|
||||
NS_IMETHOD OnDestroyed();
|
||||
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
|
||||
NS_IMETHOD AttributeRemoved(nsIAtom *aName);
|
||||
NS_IMETHOD HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled);
|
||||
|
||||
// nsIXFormsControl
|
||||
|
@ -222,6 +223,32 @@ nsXFormsInputElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
nsXFormsControlStub::AttributeRemoved(aName);
|
||||
|
||||
if (aName == nsXFormsAtoms::incremental) {
|
||||
/* if we remove the incremental attribute, then we need to go back to the
|
||||
* default value. True if it is a checkbox, false otherwise.
|
||||
*
|
||||
* XXX - Once we get more input types, the default value for incremental
|
||||
* should probably be abstracted out somewhere.
|
||||
*/
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(mControl);
|
||||
NS_ENSURE_STATE(input);
|
||||
nsAutoString type;
|
||||
input->GetType(type);
|
||||
if (mType == eType_Input && type.EqualsLiteral("checkbox")) {
|
||||
mIncremental = PR_TRUE;
|
||||
} else {
|
||||
mIncremental = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::HandleDefault(nsIDOMEvent *aEvent,
|
||||
PRBool *aHandled)
|
||||
|
|
|
@ -79,12 +79,17 @@ public:
|
|||
NS_IMETHOD OnDestroyed();
|
||||
NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue);
|
||||
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
|
||||
NS_IMETHOD WillRemoveAttribute(nsIAtom *aName);
|
||||
NS_IMETHOD AttributeRemoved(nsIAtom *aName);
|
||||
|
||||
// nsIXFormsControl
|
||||
NS_IMETHOD Bind();
|
||||
NS_IMETHOD Refresh();
|
||||
|
||||
private:
|
||||
void MaybeBindAndRefresh(nsIAtom *aName);
|
||||
void MaybeRemoveFromModel(nsIAtom *aName, const nsAString &aValue);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> mLabel;
|
||||
nsCOMPtr<nsIDOMElement> mContainer;
|
||||
nsCOMPtr<nsIDOMElement> mValue;
|
||||
|
@ -174,28 +179,28 @@ nsXFormsOutputElement::OnDestroyed()
|
|||
NS_IMETHODIMP
|
||||
nsXFormsOutputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::ref ||
|
||||
aName == nsXFormsAtoms::model ||
|
||||
aName == nsXFormsAtoms::value) {
|
||||
if (mModel)
|
||||
mModel->RemoveFormControl(this);
|
||||
}
|
||||
|
||||
MaybeRemoveFromModel(aName, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsOutputElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::ref ||
|
||||
aName == nsXFormsAtoms::model ||
|
||||
aName == nsXFormsAtoms::value) {
|
||||
Bind();
|
||||
Refresh();
|
||||
}
|
||||
MaybeBindAndRefresh(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsOutputElement::WillRemoveAttribute(nsIAtom *aName)
|
||||
{
|
||||
MaybeRemoveFromModel(aName, EmptyString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsOutputElement::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
MaybeBindAndRefresh(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -270,6 +275,37 @@ nsXFormsOutputElement::Refresh()
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsOutputElement::MaybeBindAndRefresh(nsIAtom *aName)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::value ||
|
||||
aName == nsXFormsAtoms::ref ||
|
||||
aName == nsXFormsAtoms::model) {
|
||||
|
||||
Bind();
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsOutputElement::MaybeRemoveFromModel(nsIAtom *aName,
|
||||
const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::ref ||
|
||||
aName == nsXFormsAtoms::model ||
|
||||
aName == nsXFormsAtoms::value) {
|
||||
if (mModel)
|
||||
mModel->RemoveFormControl(this);
|
||||
|
||||
if (aName != nsXFormsAtoms::model) {
|
||||
AddRemoveSNBAttr(aName, aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsOutputElement(nsIXTFElement **aResult)
|
||||
|
|
|
@ -277,6 +277,19 @@ protected:
|
|||
*/
|
||||
nsresult CloneNode(nsIDOMNode *aSrc, nsIDOMNode **aTarget);
|
||||
|
||||
/**
|
||||
* If this attribute name is bind, model or nodeset, then remove the repeat
|
||||
* control from the list of controls that the model keeps.
|
||||
*/
|
||||
void MaybeRemoveFromModel(nsIAtom *aName);
|
||||
|
||||
/**
|
||||
* If this attribute name is bind, model or nodeset, then try to Bind and
|
||||
* Refresh to keep the repeat element current
|
||||
*/
|
||||
void MaybeBindAndRefresh(nsIAtom *aName);
|
||||
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
|
@ -290,6 +303,8 @@ public:
|
|||
NS_IMETHOD OnDestroyed();
|
||||
NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue);
|
||||
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
|
||||
NS_IMETHOD WillRemoveAttribute(nsIAtom *aName);
|
||||
NS_IMETHOD AttributeRemoved(nsIAtom *aName);
|
||||
NS_IMETHOD BeginAddingChildren();
|
||||
NS_IMETHOD DoneAddingChildren();
|
||||
|
||||
|
@ -361,26 +376,28 @@ nsXFormsRepeatElement::OnDestroyed()
|
|||
NS_IMETHODIMP
|
||||
nsXFormsRepeatElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::nodeset ||
|
||||
aName == nsXFormsAtoms::model) {
|
||||
if (mModel) {
|
||||
mModel->RemoveFormControl(this);
|
||||
}
|
||||
}
|
||||
|
||||
MaybeRemoveFromModel(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsRepeatElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::nodeset ||
|
||||
aName == nsXFormsAtoms::model) {
|
||||
Bind();
|
||||
}
|
||||
MaybeBindAndRefresh(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsRepeatElement::WillRemoveAttribute(nsIAtom *aName)
|
||||
{
|
||||
MaybeRemoveFromModel(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsRepeatElement::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
MaybeBindAndRefresh(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -572,8 +589,6 @@ nsXFormsRepeatElement::Bind()
|
|||
|
||||
mModel = nsXFormsUtils::GetModel(mElement);
|
||||
|
||||
Refresh();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -960,6 +975,29 @@ nsXFormsRepeatElement::GetIntAttr(const nsAString &aName,
|
|||
return rv;
|
||||
}
|
||||
|
||||
void nsXFormsRepeatElement::MaybeBindAndRefresh(nsIAtom *aName)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::nodeset ||
|
||||
aName == nsXFormsAtoms::model) {
|
||||
|
||||
Bind();
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void nsXFormsRepeatElement::MaybeRemoveFromModel(nsIAtom *aName)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind ||
|
||||
aName == nsXFormsAtoms::nodeset ||
|
||||
aName == nsXFormsAtoms::model) {
|
||||
if (mModel) {
|
||||
mModel->RemoveFormControl(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Factory
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsRepeatElement(nsIXTFElement **aResult)
|
||||
|
|
Загрузка…
Ссылка в новой задаче