Fix nsXFormsModelElement::Rebuild() to work correctly. Patch by aaronr@us.ibm.com, r=allan@beaufour.dk, sr=me.

This commit is contained in:
bryner%brianryner.com 2005-01-31 23:41:00 +00:00
Родитель f1e0087257
Коммит 8ef2852244
17 изменённых файлов: 139 добавлений и 147 удалений

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

@ -138,4 +138,6 @@ CPPSRCS = \
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)
PREF_JS_EXPORTS = $(srcdir)/xforms.js
include $(topsrcdir)/config/rules.mk

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

@ -89,6 +89,7 @@ public:
NS_IMETHOD CloneState(nsIDOMElement *aElement);
// nsIXFormsControl
NS_IMETHOD Bind();
NS_IMETHOD Refresh();
// nsIXFormsContextControl
@ -214,6 +215,13 @@ nsXFormsContextContainer::GetContext(nsAString &aModelID,
}
// nsIXFormsControl
NS_IMETHODIMP
nsXFormsContextContainer::Bind()
{
return NS_OK;
}
nsresult
nsXFormsContextContainer::Refresh()
{

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

@ -100,6 +100,30 @@ nsXFormsControlStub::GetElement(nsIDOMElement **aElement)
return NS_OK;
}
NS_IMETHODIMP
nsXFormsControlStub::ResetBoundNode()
{
mBoundNode = nsnull;
nsCOMPtr<nsIModelElementPrivate> modelNode;
nsCOMPtr<nsIDOMXPathResult> result;
nsresult rv =
ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result),
getter_AddRefs(modelNode));
NS_ENSURE_SUCCESS(rv, rv);
if (!result) {
return NS_OK;
}
// Get context node, if any
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
return NS_OK;
}
/**
* @note Refresh() is always called after a Bind(), so if a control decides to
* do all the work in Refresh() this function implements a NOP Bind().
@ -107,7 +131,7 @@ nsXFormsControlStub::GetElement(nsIDOMElement **aElement)
NS_IMETHODIMP
nsXFormsControlStub::Bind()
{
return NS_OK;
return ResetBoundNode();
}
NS_IMETHODIMP

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

@ -83,6 +83,7 @@ public:
NS_IMETHOD GetBoundNode(nsIDOMNode **aBoundNode);
NS_IMETHOD GetDependencies(nsIArray **aDependencies);
NS_IMETHOD GetElement(nsIDOMElement **aElement);
NS_IMETHOD ResetBoundNode();
NS_IMETHOD Bind();
NS_IMETHOD TryFocus(PRBool* aOK);

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

@ -106,6 +106,7 @@ public:
NS_IMETHOD OnDestroyed();
// nsIXFormsControl
NS_IMETHOD Bind();
NS_IMETHOD Refresh();
NS_IMETHOD TryFocus(PRBool* aOK);
@ -181,6 +182,22 @@ nsXFormsGroupElement::OnDestroyed()
// nsIXFormsControl
NS_IMETHODIMP
nsXFormsGroupElement::Bind()
{
mModelID.Truncate();
// Re-evaluate what instance node this element is bound to.
ResetBoundNode();
// Get model ID
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(mModel);
NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE);
modelElement->GetAttribute(NS_LITERAL_STRING("id"), mModelID);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsGroupElement::Refresh()
{
@ -188,34 +205,6 @@ nsXFormsGroupElement::Refresh()
printf("nsXFormsGroupElement::Refresh()\n");
#endif
if (!mHTMLElement)
return NS_OK;
mModelID.Truncate();
nsCOMPtr<nsIModelElementPrivate> modelNode;
nsCOMPtr<nsIDOMXPathResult> result;
nsresult rv =
ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result),
getter_AddRefs(modelNode));
NS_ENSURE_SUCCESS(rv, rv);
if (!result) {
return NS_OK;
}
// Get model ID
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(modelNode);
NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE);
modelElement->GetAttribute(NS_LITERAL_STRING("id"), mModelID);
// Get context node, if any
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
NS_ENSURE_STATE(mBoundNode);
return NS_OK;
}

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

@ -77,7 +77,6 @@ public:
NS_IMETHOD OnDestroyed();
// nsIXFormsControl
NS_IMETHOD Bind();
NS_IMETHOD Refresh();
NS_IMETHOD TryFocus(PRBool* aOK);
@ -268,28 +267,6 @@ nsXFormsInputElement::Blur(nsIDOMEvent *aEvent)
// nsIXFormsControl
NS_IMETHODIMP
nsXFormsInputElement::Bind()
{
if (!mControl)
return NS_OK;
mBoundNode = nsnull;
nsCOMPtr<nsIDOMXPathResult> result;
nsresult rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
if (result) {
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputElement::Refresh()
{

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

@ -168,22 +168,12 @@ nsXFormsLabelElement::RefreshLabel()
// or linking attributes are present, we don't want to show the inline text
// at all.
nsCOMPtr<nsIDOMXPathResult> result;
nsresult rv =
ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result));
nsAutoString labelValue;
PRBool foundValue = PR_FALSE;
if (NS_SUCCEEDED(rv) && result) {
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
if (mBoundNode) {
nsXFormsUtils::GetNodeValue(mBoundNode, labelValue);
foundValue = PR_TRUE;
}
if (mBoundNode) {
nsXFormsUtils::GetNodeValue(mBoundNode, labelValue);
foundValue = PR_TRUE;
}
// if (!foundValue) {

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

@ -423,11 +423,39 @@ nsXFormsModelElement::Rebuild()
// TODO: Clear graph and re-attach elements
// 1 . Clear graph
// mMDG.Clear();
mMDG.Clear();
// 2. Re-attach all elements
// Copy the form control list as it stands right now.
nsVoidArray *oldFormList = new nsVoidArray();
*oldFormList = mFormControls;
// Clear out mFormControls so that we can rebuild the list. We'll go control
// by control over the old list and rebind the controls.
mFormControls.Clear();
PRInt32 controlCount = oldFormList->Count();
for (PRInt32 i = 0; i < controlCount; ++i) {
nsIXFormsControl* control = NS_STATIC_CAST(nsIXFormsControl*,
(*oldFormList)[i]);
/// @todo If a control is removed because of previous control has been
/// refreshed, we do, obviously, not need to refresh it. So mFormControls
/// should have weak bindings to the controls I guess? (XXX)
///
/// This could happen for \<repeatitem\>s for example.
if (!control) {
continue;
}
// run bind to reset mBoundNode for all of these controls and also, in the
// process, they will be added to the model that they should be bound to.
control->Bind();
}
// 3. Rebuild graph
ProcessBindElements();
return mMDG.Rebuild();
}
@ -948,14 +976,13 @@ nsXFormsModelElement::FindInstanceDocument(const nsAString &aID)
}
nsresult
nsXFormsModelElement::FinishConstruction()
nsXFormsModelElement::ProcessBindElements()
{
// 3. if applicable, initialize P3P
// 4. construct instance data from initial instance data. apply all
// <bind> elements in document order.
// we get the instance data from our instance child nodes
// ProcessBindElements() will go through each xforms:bind element in
// document order and apply all of the Model Item Properties to the
// instance items in the nodeset. This information will also be entered
// in the Master Dependency Graph. Most of this work is done in the
// ProcessBind() method.
nsCOMPtr<nsIDOMDocument> firstInstanceDoc =
FindInstanceDocument(EmptyString());
@ -996,6 +1023,21 @@ nsXFormsModelElement::FinishConstruction()
}
}
return NS_OK;
}
nsresult
nsXFormsModelElement::FinishConstruction()
{
// 3. if applicable, initialize P3P
// 4. construct instance data from initial instance data. apply all
// <bind> elements in document order.
// we get the instance data from our instance child nodes
ProcessBindElements();
// 5. dispatch xforms-rebuild, xforms-recalculate, xforms-revalidate
nsXFormsUtils::DispatchEvent(mElement, eEvent_Rebuild);

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

@ -101,6 +101,7 @@ private:
NS_HIDDEN_(already_AddRefed<nsIDOMDocument>)
FindInstanceDocument(const nsAString &aID);
NS_HIDDEN_(nsresult) ProcessBindElements();
NS_HIDDEN_(nsresult) FinishConstruction();
NS_HIDDEN_(void) MaybeNotifyCompletion();

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

@ -159,6 +159,7 @@ public:
NS_IMETHOD DoneAddingChildren();
// nsIXFormsControl
NS_IMETHOD Bind();
NS_IMETHOD Refresh();
NS_IMETHOD TryFocus(PRBool* aOK);
@ -280,6 +281,12 @@ nsXFormsRepeatElement::DoneAddingChildren()
// nsXFormsControl
NS_IMETHODIMP
nsXFormsRepeatElement::Bind()
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsRepeatElement::Refresh()
{

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

@ -297,17 +297,11 @@ nsXFormsSelectElement::Refresh()
mSelect->SetSelectedIndex(-1);
}
nsCOMPtr<nsIDOMXPathResult> result;
rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
if (result)
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
if (!mBoundNode)
// since single node binding is optional, we won't send an error code. But
// there is no point continuing below without mBoundNode.
if(!mBoundNode) {
return NS_OK;
}
nsCOMPtr<nsIDOMNodeList> children;
mBoundNode->GetChildNodes(getter_AddRefs(children));

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

@ -88,6 +88,7 @@ public:
NS_DECL_NSIXFORMSSWITCHELEMENT
// nsIXFormsControl
NS_IMETHOD Bind();
NS_IMETHOD Refresh();
NS_DECL_NSIXFORMSCONTEXTCONTROL
@ -117,8 +118,6 @@ private:
*/
void SetFocus(nsIDOMElement* aDeselected, nsIDOMElement* aSelected);
nsresult Process();
nsCOMPtr<nsIDOMElement> mVisual;
nsCOMPtr<nsIDOMElement> mSelected;
PRBool mDoneAddingChildren;
@ -227,47 +226,29 @@ nsXFormsSwitchElement::DoneAddingChildren()
// nsIXFormsControl
NS_IMETHODIMP
nsXFormsSwitchElement::Refresh()
{
nsresult rv = NS_OK;
if (mDoneAddingChildren) {
rv = Process();
}
return rv;
}
// nsXFormsSwitchElement
nsresult
nsXFormsSwitchElement::Process()
nsXFormsSwitchElement::Bind()
{
mModelID.Truncate();
nsCOMPtr<nsIModelElementPrivate> modelNode;
nsCOMPtr<nsIDOMXPathResult> result;
nsresult rv =
ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result),
getter_AddRefs(modelNode));
NS_ENSURE_SUCCESS(rv, rv);
if (!result) {
return NS_OK;
}
// Re-evaluate what instance node this element is bound to.
ResetBoundNode();
// Get model ID
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(modelNode);
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(mModel);
NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE);
modelElement->GetAttribute(NS_LITERAL_STRING("id"), mModelID);
// Get context node, if any
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSwitchElement::Refresh()
{
return NS_OK;
}
// nsXFormsSwitchElement
NS_IMETHODIMP
nsXFormsSwitchElement::SetContextNode(nsIDOMNode *aContextNode)
{

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

@ -122,20 +122,6 @@ nsXFormsTriggerElement::GetInsertionPoint(nsIDOMElement **aElement)
NS_IMETHODIMP
nsXFormsTriggerElement::Refresh()
{
nsCOMPtr<nsIDOMXPathResult> result;
nsresult rv =
ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
if (!result) {
return NS_OK;
}
// Get context node, if any
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
return NS_OK;
}

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

@ -248,22 +248,6 @@ nsXFormsUploadElement::Refresh()
if (!mInput)
return NS_OK;
mBoundNode = nsnull;
nsCOMPtr<nsIDOMXPathResult> result;
nsresult rv =
ProcessNodeBinding(NS_LITERAL_STRING("ref"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
if (result)
result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
if (!mBoundNode)
return NS_OK;
nsCOMPtr<nsIContent> content = do_QueryInterface(mBoundNode);
NS_ENSURE_STATE(content);

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

@ -63,9 +63,11 @@ PACKAGE_VERSION = 0.1
xpi:
@echo Copying files to staging area...
rm -rf stage
$(NSINSTALL) -D stage
$(INSTALL) -D stage
$(PERL) $(topsrcdir)/xpinstall/packager/pkgcp.pl -o $(PKGCP_PLATFORM) -s $(DIST)/bin -d stage -f $(srcdir)/$(PACKAGE_FILE) -v
$(NSINSTALL) $(srcdir)/install.rdf stage/xforms
$(INSTALL) $(srcdir)/install.rdf stage/xforms
$(INSTALL) -D stage/xforms/defaults/preferences
$(INSTALL) $(srcdir)/../xforms.js stage/xforms/defaults/preferences
@echo Creating install.js...
rm -f xforms.js
$(PERL) $(topsrcdir)/toolkit/mozapps/installer/makejs.pl $(srcdir)/xforms.jst $(PACKAGE_VERSION) stage/xforms

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

@ -11,6 +11,9 @@ if (verifyDiskSpace(fProgram, srChrome + srComponents))
logComment("addDirectory components: " + err);
err = addDirectory("", "0.1", "chrome", fProgram, "chrome", true);
logComment("addDirectory chrome: " + err);
err = addFile("", "0.1", "defaults/preferences/xforms.js", fProgram,
"defaults/pref/xforms.js", true);
logComment("addFile xforms.js: " + err);
registerChrome(PACKAGE | DELAYED_CHROME, getFolder("Chrome", "xforms.jar"),
"content/xforms/");

1
extensions/xforms/xforms.js Executable file
Просмотреть файл

@ -0,0 +1 @@
pref("general.useragent.productComment", "xforms/1.0");