nsITreeBoxObject* nsTreeBoxObject::GetTreeBody() { if (mTreeBody) { return mTreeBody; } nsIFrame* frame = GetFrame(); if (!frame) return nsnull; // Iterate over our content model children looking for the body. nsCOMPtr<nsIContent> content; FindBodyElement(frame->GetContent(), getter_AddRefs(content)); nsCOMPtr<nsIPresShell> shell = GetPresShell(); if (!shell) { return nsnull; } shell->GetPrimaryFrameFor(content, &frame); if (!frame) return nsnull; // It's a frame. Refcounts are irrelevant. CallQueryInterface(frame, &mTreeBody); return mTreeBody; }
nsTreeBodyFrame* nsTreeBoxObject::GetTreeBody(bool aFlushLayout) { // Make sure our frames are up to date, and layout as needed. We // have to do this before checking for our cached mTreeBody, since // it might go away on style flush, and in any case if aFlushLayout // is true we need to make sure to flush no matter what. // XXXbz except that flushing style when we were not asked to flush // layout here breaks things. See bug 585123. nsIFrame* frame; if (aFlushLayout) { frame = GetFrame(aFlushLayout); if (!frame) return nsnull; } if (mTreeBody) { // Have one cached already. return mTreeBody; } if (!aFlushLayout) { frame = GetFrame(aFlushLayout); if (!frame) return nsnull; } // Iterate over our content model children looking for the body. nsCOMPtr<nsIContent> content; FindBodyElement(frame->GetContent(), getter_AddRefs(content)); if (!content) return nsnull; frame = content->GetPrimaryFrame(); if (!frame) return nsnull; // Make sure that the treebodyframe has a pointer to |this|. nsTreeBodyFrame *treeBody = do_QueryFrame(frame); NS_ENSURE_TRUE(treeBody && treeBody->GetTreeBoxObject() == this, nsnull); mTreeBody = treeBody; return mTreeBody; }
static nsIContent* FindBodyElement(nsIContent* aParent) { mozilla::dom::FlattenedChildIterator iter(aParent); for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) { nsINodeInfo *ni = content->NodeInfo(); if (ni->Equals(nsGkAtoms::treechildren, kNameSpaceID_XUL)) { return content; } else if (ni->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) { // There are nesting tree elements. Only the innermost should // find the treechilren. return nullptr; } else if (content->IsElement() && !ni->Equals(nsGkAtoms::_template, kNameSpaceID_XUL)) { nsIContent* result = FindBodyElement(content); if (result) return result; } } return nullptr; }
static void FindBodyElement(nsIContent* aParent, nsIContent** aResult) { *aResult = nsnull; ChildIterator iter, last; for (ChildIterator::Init(aParent, &iter, &last); iter != last; ++iter) { nsCOMPtr<nsIContent> content = *iter; nsINodeInfo *ni = content->GetNodeInfo(); if (ni && ni->Equals(nsXULAtoms::treechildren, kNameSpaceID_XUL)) { *aResult = content; NS_ADDREF(*aResult); break; } else if (ni && ni->Equals(nsXULAtoms::tree, kNameSpaceID_XUL)) { // There are nesting tree elements. Only the innermost should // find the treechilren. break; } else if (ni && !ni->Equals(nsXULAtoms::templateAtom, kNameSpaceID_XUL)) { FindBodyElement(content, aResult); if (*aResult) break; } } }