Fix timing issues wrt. model placement. Bug 283737, r=smaug+me, a=mkaply, patch by aaronr@us.ibm.com, NPOTB
git-svn-id: svn://10.0.0.236/trunk@173506 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -59,6 +59,8 @@ nsIAtom *nsXFormsAtoms::selected;
|
||||
nsIAtom *nsXFormsAtoms::appearance;
|
||||
nsIAtom *nsXFormsAtoms::incremental;
|
||||
nsIAtom *nsXFormsAtoms::clazz;
|
||||
nsIAtom *nsXFormsAtoms::deferredBindListProperty;
|
||||
nsIAtom *nsXFormsAtoms::readyForBindProperty;
|
||||
|
||||
const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
|
||||
{ "src", &nsXFormsAtoms::src },
|
||||
@@ -80,7 +82,9 @@ const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
|
||||
{ "selected", &nsXFormsAtoms::selected },
|
||||
{ "appearance", &nsXFormsAtoms::appearance },
|
||||
{ "incremental", &nsXFormsAtoms::incremental },
|
||||
{ "class", &nsXFormsAtoms::clazz }
|
||||
{ "class", &nsXFormsAtoms::clazz },
|
||||
{ "DeferredBindListProperty", &nsXFormsAtoms::deferredBindListProperty },
|
||||
{ "ReadyForBindProperty", &nsXFormsAtoms::readyForBindProperty }
|
||||
};
|
||||
|
||||
void
|
||||
|
||||
@@ -64,6 +64,8 @@ class nsXFormsAtoms
|
||||
static NS_HIDDEN_(nsIAtom *) incremental;
|
||||
static NS_HIDDEN_(nsIAtom *) value;
|
||||
static NS_HIDDEN_(nsIAtom *) clazz;
|
||||
static NS_HIDDEN_(nsIAtom *) deferredBindListProperty;
|
||||
static NS_HIDDEN_(nsIAtom *) readyForBindProperty;
|
||||
|
||||
static NS_HIDDEN_(void) InitAtoms();
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMXPathResult.h"
|
||||
#include "nsIXTFXMLVisualWrapper.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsXFormsModelElement.h"
|
||||
|
||||
/** This class is used to generate xforms-hint and xforms-help events.*/
|
||||
class nsXFormsHintHelpListener : public nsIDOMEventListener {
|
||||
@@ -187,6 +189,25 @@ nsXFormsControlStub::ProcessNodeBinding(const nsString &aBindingAttr,
|
||||
{
|
||||
nsStringArray indexesUsed;
|
||||
|
||||
// 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
|
||||
// to return NS_OK so that we don't start complaining about binding
|
||||
// failures in this situation.
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
if (!doc) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsIDocument *test = NS_STATIC_CAST(nsIDocument *,
|
||||
doc->GetProperty(nsXFormsAtoms::readyForBindProperty));
|
||||
if (!test) {
|
||||
nsXFormsModelElement::DeferElementBind(domDoc, this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
rv = nsXFormsUtils::EvaluateNodeBinding(mElement,
|
||||
kElementFlags,
|
||||
@@ -205,14 +226,11 @@ nsXFormsControlStub::ProcessNodeBinding(const nsString &aBindingAttr,
|
||||
|
||||
if (NS_SUCCEEDED(rv) && indexesUsed.Count()) {
|
||||
// add index listeners on repeat elements
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
mElement->GetOwnerDocument(getter_AddRefs(doc));
|
||||
NS_ENSURE_STATE(doc);
|
||||
|
||||
for (PRInt32 i = 0; i < indexesUsed.Count(); ++i) {
|
||||
// Find the repeat element and add |this| as a listener
|
||||
nsCOMPtr<nsIDOMElement> repElem;
|
||||
doc->GetElementById(*(indexesUsed[i]), getter_AddRefs(repElem));
|
||||
domDoc->GetElementById(*(indexesUsed[i]), getter_AddRefs(repElem));
|
||||
nsCOMPtr<nsIXFormsRepeatElement> rep(do_QueryInterface(repElem));
|
||||
if (!rep)
|
||||
continue;
|
||||
|
||||
@@ -1273,6 +1273,8 @@ nsXFormsModelElement::MaybeNotifyCompletion()
|
||||
NS_STATIC_CAST(nsXFormsModelElement *, models->ElementAt(i));
|
||||
nsXFormsUtils::DispatchEvent(model->mElement, eEvent_ModelConstructDone);
|
||||
}
|
||||
|
||||
nsXFormsModelElement::ProcessDeferredBinds(domDoc);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@@ -1497,6 +1499,74 @@ nsXFormsModelElement::Startup()
|
||||
sModelPropsList[eModel_p3ptype] = nsXFormsAtoms::p3ptype;
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteBindList(void *aObject,
|
||||
nsIAtom *aPropertyName,
|
||||
void *aPropertyValue,
|
||||
void *aData)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsCOMArray<nsIXFormsControl> *, aPropertyValue);
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsXFormsModelElement::DeferElementBind(nsIDOMDocument *aDoc,
|
||||
nsIXFormsControl *aControl)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
||||
|
||||
if (!doc || !aControl) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMArray<nsIXFormsControl> *deferredBindList =
|
||||
NS_STATIC_CAST(nsCOMArray<nsIXFormsControl> *,
|
||||
doc->GetProperty(nsXFormsAtoms::deferredBindListProperty));
|
||||
|
||||
if (!deferredBindList) {
|
||||
deferredBindList = new nsCOMArray<nsIXFormsControl>(16);
|
||||
NS_ENSURE_TRUE(deferredBindList, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
doc->SetProperty(nsXFormsAtoms::deferredBindListProperty, deferredBindList,
|
||||
DeleteBindList);
|
||||
}
|
||||
|
||||
// always append to the end of the list. We need to keep the elements in
|
||||
// document order when we process the binds later. Otherwise we have trouble
|
||||
// when an element is trying to bind and should use its parent as a context
|
||||
// for the xpath evaluation but the parent isn't bound yet.
|
||||
deferredBindList->AppendObject(aControl);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsXFormsModelElement::ProcessDeferredBinds(nsIDOMDocument *aDoc)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
||||
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc->SetProperty(nsXFormsAtoms::readyForBindProperty, doc);
|
||||
|
||||
nsCOMArray<nsIXFormsControl> *deferredBindList =
|
||||
NS_STATIC_CAST(nsCOMArray<nsIXFormsControl> *,
|
||||
doc->GetProperty(nsXFormsAtoms::deferredBindListProperty));
|
||||
|
||||
if (deferredBindList) {
|
||||
for (int i = 0; i < deferredBindList->Count(); ++i) {
|
||||
nsIXFormsControl *control = deferredBindList->ObjectAt(i);
|
||||
if (control) {
|
||||
control->Bind();
|
||||
control->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
doc->DeleteProperty(nsXFormsAtoms::deferredBindListProperty);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewXFormsModelElement(nsIXTFElement **aResult)
|
||||
{
|
||||
|
||||
@@ -94,6 +94,17 @@ public:
|
||||
// Called after nsXFormsAtoms is registered
|
||||
static NS_HIDDEN_(void) Startup();
|
||||
|
||||
/**
|
||||
* The models are not ready for binding, so defer the binding of the control
|
||||
* by storing it as a property on the document. The models will run through
|
||||
* this list when they are ready for binding.
|
||||
*
|
||||
* @param aDoc Document that contains aElement
|
||||
* @param aControl XForms control waiting to be bound
|
||||
*/
|
||||
static NS_HIDDEN_(nsresult) DeferElementBind(nsIDOMDocument *aDoc,
|
||||
nsIXFormsControl *aControl);
|
||||
|
||||
private:
|
||||
|
||||
NS_HIDDEN_(already_AddRefed<nsIDOMDocument>)
|
||||
@@ -147,6 +158,14 @@ private:
|
||||
nsXFormsEvent aOnEvent,
|
||||
PRUint32 aAttributePos);
|
||||
|
||||
/**
|
||||
* Call the Bind() and Refresh() on controls which was deferred because
|
||||
* the model was not ready.
|
||||
*
|
||||
* @param aDoc Document that contains the XForms control
|
||||
*/
|
||||
static NS_HIDDEN_(void) ProcessDeferredBinds(nsIDOMDocument *aDoc);
|
||||
|
||||
// Returns true when all external documents have been loaded
|
||||
PRBool IsComplete() const { return (mSchemaTotal == mSchemaCount
|
||||
&& mPendingInstanceCount == 0); }
|
||||
|
||||
Reference in New Issue
Block a user