/* * Finds the first child of aNode after child N and returns it. If a * child is found, mCurrentNode is set to that child * @param aNode Node to search for children * @param childNum Child number to start search from. The child with * this number is not searched * @param aReversed Reverses search to find the last child instead * of first * @param aIndexPos Position of aNode in mPossibleIndexes * @param _retval Returned node. Null if no child is found * @returns Errorcode */ nsresult nsTreeWalker::ChildOf(nsINode* aNode, PRInt32 childNum, PRBool aReversed, PRInt32 aIndexPos, nsINode** _retval) { PRInt16 filtered; nsresult rv; PRInt32 dir = aReversed ? -1 : 1; // Step through all children PRInt32 i = childNum; while (1) { i += dir; nsCOMPtr<nsINode> child = aNode->GetChildAt(i); if (!child) { break; } rv = TestNode(child, &filtered); NS_ENSURE_SUCCESS(rv, rv); switch (filtered) { case nsIDOMNodeFilter::FILTER_ACCEPT: // Child found mCurrentNode = child; mPossibleIndexesPos = aIndexPos; *_retval = child; NS_ADDREF(*_retval); SetChildIndex(aIndexPos, i); return NS_OK; case nsIDOMNodeFilter::FILTER_SKIP: // Search children rv = FirstChildOf(child, aReversed, aIndexPos+1, _retval); NS_ENSURE_SUCCESS(rv, rv); if (*_retval) { SetChildIndex(aIndexPos, i); return NS_OK; } break; case nsIDOMNodeFilter::FILTER_REJECT: // Keep searching break; default: return NS_ERROR_UNEXPECTED; } } *_retval = nsnull; return NS_OK; }
NS_IMETHODIMP nsXFormsRepeatElement::Deselect(void) { if (!mCurrentIndex) return NS_OK; nsresult rv = SetChildIndex(mCurrentIndex, PR_FALSE); if (NS_SUCCEEDED(rv)) { mCurrentIndex = 0; } return rv; }
NS_IMETHODIMP nsXFormsRepeatElement::Refresh() { #ifdef DEBUG_XF_REPEAT printf("nsXFormsRepeatElement::Refresh()\n"); #endif if (mAddingChildren || mIsParent) return NS_OK; nsPostRefresh postRefresh = nsPostRefresh(); PRUint32 oldIndex = mCurrentIndex; /// @todo The spec says: "This node-set must consist of contiguous child /// element nodes, with the same local name and namespace name of a common /// parent node. The behavior of element repeat with respect to /// non-homogeneous node-sets is undefined." /// @see http://www.w3.org/TR/xforms/slice9.html#ui-repeat /// /// Can/should we check this somehow? (XXX) // Get the nodeset we are bound to nsresult rv; nsCOMPtr<nsIDOMXPathResult> result; rv = ProcessNodeBinding(NS_LITERAL_STRING("nodeset"), nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, getter_AddRefs(result)); NS_ENSURE_SUCCESS(rv, rv); // Unroll the repeat rows rv = UnrollRows(result); NS_ENSURE_SUCCESS(rv, rv); // Maintain the index if (mCurrentIndex || !mMaxIndex) { // Somebody might have been fooling around with our children since last // refresh (either using delete or through script). Or we might have an // empty nodeset. So fix the index value. SanitizeIndex(&mCurrentIndex); } else if (mMaxIndex) { // repeat-index has not been initialized, set it. if (!mParent) { GetStartingIndex(&mCurrentIndex); // Inform listeners of initial index value IndexHasChanged(); } else if (mLevel > 1) { // Set repeat-index for inner repeats. If parent <contextcontainer/> // element is selected then mCurrentIndex is setted on starting index. nsCOMPtr<nsIDOMNode> temp = mElement; nsCOMPtr<nsIDOMNode> parent; nsCOMPtr<nsIXFormsRepeatItemElement> context; while (!context) { rv = temp->GetParentNode(getter_AddRefs(parent)); NS_ENSURE_SUCCESS(rv, rv); if (!parent) break; context = do_QueryInterface(parent); temp.swap(parent); } if (context) { PRBool hasIndex = PR_FALSE; context->GetIndexState(&hasIndex); if (hasIndex) { PRUint32 index = 0; GetStartingIndex(&index); SetIndex(&index, PR_FALSE); } } return NS_OK; } } // If we have the repeat-index, set it. if (mCurrentIndex) { SetChildIndex(mCurrentIndex, PR_TRUE, PR_TRUE); } if (mCurrentIndex != oldIndex) { mParent ? mParent->IndexHasChanged() : IndexHasChanged(); } return NS_OK; }
NS_IMETHODIMP nsXFormsRepeatElement::SetIndex(PRUint32 *aIndex, PRBool aIsRefresh) { NS_ENSURE_ARG(aIndex); #ifdef DEBUG_XF_REPEAT printf("\tSetindex to %d (current: %d, max: %d), aIsRefresh=%d\n", *aIndex, mCurrentIndex, mMaxIndex, aIsRefresh); #endif nsresult rv; // Set repeat-index if (mIsParent) { NS_ASSERTION(mCurrentRepeat, "How can we be a repeat parent without a child?"); // We're the parent of nested repeats, set through the correct repeat return mCurrentRepeat->SetIndex(aIndex, aIsRefresh); } // Do nothing if we are not showing anything if (mMaxIndex == 0) { SanitizeIndex(aIndex, PR_TRUE); mCurrentIndex = *aIndex; return NS_OK; } if (aIsRefresh && !mCurrentIndex) { // If we are refreshing, get existing index value from parent NS_ASSERTION(mParent, "SetIndex with aIsRefresh == PR_TRUE for a non-nested repeat?!"); rv = mParent->GetIndex(aIndex); NS_ENSURE_SUCCESS(rv, rv); } // Check min. and max. value SanitizeIndex(aIndex, PR_TRUE); // Do nothing if setting to existing value if (!aIsRefresh && mCurrentIndex && *aIndex == mCurrentIndex) return NS_OK; #ifdef DEBUG_XF_REPEAT printf("\tWill set index to %d\n", *aIndex); #endif // Set the repeat-index rv = SetChildIndex(*aIndex, PR_TRUE, aIsRefresh); NS_ENSURE_SUCCESS(rv, rv); // Unset previous repeat-index if (mCurrentIndex) { // We had the previous selection, unset directly SetChildIndex(mCurrentIndex, PR_FALSE, aIsRefresh); } if (mParent) { // Selection is in another repeat, inform parent (it will inform the // previous owner of its new state) rv = mParent->SetCurrentRepeat(this, *aIndex); NS_ENSURE_SUCCESS(rv, rv); } // Set current index to new value mCurrentIndex = *aIndex; // Inform of index change mParent ? mParent->IndexHasChanged() : IndexHasChanged(); return NS_OK; }