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:
allan%beaufour.dk
2005-05-17 11:30:43 +00:00
parent 9edef9e18b
commit 89c8cacb04
5 changed files with 118 additions and 5 deletions

View File

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

View File

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

View File

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

View File

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

View File

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