XForms bug 284469 - Calling ProcessNodeBind unnecessarily. Patch by aaronr, r=beaufour,me, a=mkaply

This commit is contained in:
doronr%us.ibm.com 2005-04-11 16:33:31 +00:00
Родитель 34e5bd90c5
Коммит 3bbabc8a29
5 изменённых файлов: 268 добавлений и 45 удалений

Просмотреть файл

@ -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)