From b42f9acfb956b516ecc18348f677d3d59051da9c Mon Sep 17 00:00:00 2001 From: "allan%beaufour.dk" Date: Mon, 11 Apr 2005 08:04:51 +0000 Subject: [PATCH] Patch that fixes the ugly refresh-all hack in nsXFormsModelElement.cpp. Should speed up things considerably, but is also a potential form-breaker. Bug 278368, r=aaronr+smaug, a=mkaply --- extensions/xforms/nsIXFormsControl.idl | 2 - extensions/xforms/nsXFormsMDGEngine.h | 2 - extensions/xforms/nsXFormsModelElement.cpp | 76 ++++++++++++--------- extensions/xforms/nsXFormsOutputElement.cpp | 2 - extensions/xforms/nsXFormsUtils.cpp | 2 +- extensions/xforms/nsXFormsXPathAnalyzer.cpp | 4 +- 6 files changed, 45 insertions(+), 43 deletions(-) diff --git a/extensions/xforms/nsIXFormsControl.idl b/extensions/xforms/nsIXFormsControl.idl index 9bc5ba2e2a8e..4c6ae0982e36 100644 --- a/extensions/xforms/nsIXFormsControl.idl +++ b/extensions/xforms/nsIXFormsControl.idl @@ -81,8 +81,6 @@ interface nsIXFormsControl : nsIXFormsContextControl * the control is bound to (mBoundNode). For example: * If a node has @ref="/share[@owner = /me]", it depends on all /share * nodes, all @owned attributes on /share nodes, and all /me nodes. - * - * @note The array MUST be sorted, pointer-order, ascending. */ readonly attribute nsCOMArrayPtr dependencies; diff --git a/extensions/xforms/nsXFormsMDGEngine.h b/extensions/xforms/nsXFormsMDGEngine.h index 87501cb6bc49..6b01d48d7892 100644 --- a/extensions/xforms/nsXFormsMDGEngine.h +++ b/extensions/xforms/nsXFormsMDGEngine.h @@ -367,8 +367,6 @@ public: * Recalculate the MDG. * * @param aChangedNodes Returns the nodes that was changed during recalculation. - * - * @note aChangedNodes are unique and sorted in pointer-order, ascending. */ nsresult Recalculate(nsCOMArray *aChangedNodes); diff --git a/extensions/xforms/nsXFormsModelElement.cpp b/extensions/xforms/nsXFormsModelElement.cpp index 12482cd92914..3abd3b1ea14b 100644 --- a/extensions/xforms/nsXFormsModelElement.cpp +++ b/extensions/xforms/nsXFormsModelElement.cpp @@ -544,16 +544,15 @@ nsXFormsModelElement::Revalidate() printf("nsXFormsModelElement::Revalidate()\n"); #endif - /// @note Prerequisite: Both changed nodes and dependencies are sorted in - /// ascending order! - #ifdef DEBUG_MODEL - printf("Changed nodes:\n"); + printf("[%s] Changed nodes:\n", __TIME__); for (PRInt32 j = 0; j < mChangedNodes.Count(); ++j) { - nsCOMPtr node = mChangedNodes.GetNode(j); + nsCOMPtr node = mChangedNodes[j]; nsAutoString name; node->GetNodeName(name); - printf("\t%s\n", NS_ConvertUCS2toUTF8(name).get()); + printf("\t%s [%p]\n", + NS_ConvertUCS2toUTF8(name).get(), + (void*) node); } #endif @@ -580,52 +579,63 @@ nsXFormsModelElement::Revalidate() // Get dependencies nsCOMArray *deps = nsnull; control->GetDependencies(&deps); - PRUint32 depCount = deps ? deps->Count() : 0; #ifdef DEBUG_MODEL + PRUint32 depCount = deps ? deps->Count() : 0; nsCOMPtr controlElement; control->GetElement(getter_AddRefs(controlElement)); if (controlElement) { printf("Checking control: "); - //DBG_TAGINFO(controlElement); + // DBG_TAGINFO(controlElement); nsAutoString boundName; if (boundNode) boundNode->GetNodeName(boundName); - printf("\tBound to: '%s', dependencies: %d\n", + printf("\tDependencies: %d, Bound to: '%s' [%p]\n", + depCount, NS_ConvertUCS2toUTF8(boundName).get(), - depCount); + (void*) boundNode); + + nsAutoString depNodeName; + for (PRUint32 t = 0; t < depCount; ++t) { + nsCOMPtr tmpdep = deps->ObjectAt(t); + if (tmpdep) { + tmpdep->GetNodeName(depNodeName); + printf("\t\t%s [%p]\n", + NS_ConvertUCS2toUTF8(depNodeName).get(), + (void*) tmpdep); + } + } } #endif - nsCOMPtr curDep, curChanged; - PRUint32 depPos = 0; - /// @bug This should be set to PR_FALSE! (XXX) - /// Setting it to PR_TRUE rebinds all controls all the time - /// @see https://bugzilla.mozilla.org/show_bug.cgi?id=278368 - PRBool rebind = PR_TRUE; + nsCOMPtr curChanged; + PRBool rebind = PR_FALSE; PRBool refresh = PR_FALSE; for (PRInt32 j = 0; j < mChangedNodes.Count(); ++j) { - curChanged = mChangedNodes[j]; + curChanged = do_QueryInterface(mChangedNodes[j]); - if (curChanged == boundNode) { - refresh = PR_TRUE; - // We cannot break here, as we need to to check for any changed - // dependencies + // Check whether the bound node is dirty. If so, we need to refresh the + // control (get updated node value from the bound node) + if (!refresh && boundNode) { + curChanged->IsSameNode(boundNode, &refresh); + + if (refresh) + // We need to refresh the control. We cannot break out of the loop + // as we need to check dependencies + continue; } - if (depPos == depCount) { - continue; - } - - while (depPos < depCount && (void*) curChanged > (void*) curDep) { - curDep = deps->ObjectAt(depPos); - ++depPos; - } - - if (curDep == curChanged) { - rebind = PR_TRUE; - break; + // Check whether any dependencies are dirty. If so, we need to rebind + // the control (re-evaluate it's binding expression) + for (PRInt32 k = 0; k < deps->Count(); ++k) { + /// @note beaufour: I'm not to happy about this ... + /// O(mChangedNodes.Count() * deps->Count()), but using the pointers + /// for sorting and comparing does not work... + curChanged->IsSameNode(deps->ObjectAt(k), &rebind); + if (rebind) + // We need to rebind the control, no need to check any more + break; } } diff --git a/extensions/xforms/nsXFormsOutputElement.cpp b/extensions/xforms/nsXFormsOutputElement.cpp index 7e18cd80f6da..bdd2f7071837 100755 --- a/extensions/xforms/nsXFormsOutputElement.cpp +++ b/extensions/xforms/nsXFormsOutputElement.cpp @@ -250,8 +250,6 @@ nsXFormsOutputElement::Refresh() nsXFormsUtils::GetNodeValue(mBoundNode, text); } } else { - /// - /// @todo Update mBoundNode? (XXX) nsCOMPtr result; rv = ProcessNodeBinding(NS_LITERAL_STRING("value"), nsIDOMXPathResult::STRING_TYPE, diff --git a/extensions/xforms/nsXFormsUtils.cpp b/extensions/xforms/nsXFormsUtils.cpp index 3dd42043ba23..fe13f69b5025 100644 --- a/extensions/xforms/nsXFormsUtils.cpp +++ b/extensions/xforms/nsXFormsUtils.cpp @@ -971,7 +971,7 @@ nsXFormsUtils::FocusControl(nsIDOMElement *aElement) int sortFunc(nsIDOMNode *aNode1, nsIDOMNode *aNode2, void *aArg) { - return (void*) aNode1 < (void*) aNode2; + return (void*) aNode1 > (void*) aNode2; } /* static */ void diff --git a/extensions/xforms/nsXFormsXPathAnalyzer.cpp b/extensions/xforms/nsXFormsXPathAnalyzer.cpp index c8cc4006e2fd..2a3465d66d10 100644 --- a/extensions/xforms/nsXFormsXPathAnalyzer.cpp +++ b/extensions/xforms/nsXFormsXPathAnalyzer.cpp @@ -121,9 +121,7 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, printf("\tCon: %d, Predicate: %d, Literal: %d\n", aNode->mCon, aNode->mPredicate, aNode->mLiteral); #endif - if ( aNode->mEndIndex < 0 - || aNode->mStartIndex >= aNode->mEndIndex - || ((PRUint32) aNode->mEndIndex == mCurExprString->Length() && aNode->mStartIndex == 0)) { + if (aNode->mEndIndex < 0 || aNode->mStartIndex >= aNode->mEndIndex) { continue; }