1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/ChildIterator.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,123 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef ChildIterator_h 1.11 +#define ChildIterator_h 1.12 + 1.13 +/** 1.14 + * Iterates over the children on a node. If a child is an insertion point, 1.15 + * iterates over the children inserted there instead, or the default content 1.16 + * if no children are inserted there. 1.17 + * 1.18 + * The FlattenedChildIterator expands any anonymous content bound from an XBL 1.19 + * binding's <xbl:content> element. 1.20 + */ 1.21 + 1.22 +#include "nsIContent.h" 1.23 + 1.24 +namespace mozilla { 1.25 +namespace dom { 1.26 + 1.27 +// This class iterates normal DOM child nodes of a given DOM node with 1.28 +// <xbl:children> nodes replaced by the elements that have been filtered into that 1.29 +// insertion point. Any bindings on the given element are ignored for purposes 1.30 +// of determining which insertion point children are filtered into. The iterator 1.31 +// can be initialized to start at the end by providing false for aStartAtBeginning 1.32 +// in order to start iterating in reverse from the last child. 1.33 +class ExplicitChildIterator 1.34 +{ 1.35 +public: 1.36 + ExplicitChildIterator(nsIContent* aParent, bool aStartAtBeginning = true) 1.37 + : mParent(aParent), 1.38 + mChild(nullptr), 1.39 + mDefaultChild(nullptr), 1.40 + mIndexInInserted(0), 1.41 + mIsFirst(aStartAtBeginning) 1.42 + { 1.43 + } 1.44 + 1.45 + nsIContent* GetNextChild(); 1.46 + 1.47 + // Looks for aChildToFind respecting insertion points until aChildToFind 1.48 + // or aBound is found. If aBound is nullptr then the seek is unbounded. Returns 1.49 + // whether aChildToFind was found as an explicit child prior to encountering 1.50 + // aBound. 1.51 + bool Seek(nsIContent* aChildToFind, nsIContent* aBound = nullptr) 1.52 + { 1.53 + // It would be nice to assert that we find aChildToFind, but bz thinks that 1.54 + // we might not find aChildToFind when called from ContentInserted 1.55 + // if first-letter frames are about. 1.56 + 1.57 + nsIContent* child; 1.58 + do { 1.59 + child = GetNextChild(); 1.60 + } while (child && child != aChildToFind && child != aBound); 1.61 + 1.62 + return child == aChildToFind; 1.63 + } 1.64 + 1.65 + // Returns the current target of this iterator (which might be an explicit 1.66 + // child of the node, fallback content of an insertion point or 1.67 + // a node distributed to an insertion point. 1.68 + nsIContent* Get(); 1.69 + 1.70 + // The inverse of GetNextChild. Properly steps in and out of insertion 1.71 + // points. 1.72 + nsIContent* GetPreviousChild(); 1.73 + 1.74 +protected: 1.75 + // The parent of the children being iterated. For the FlattenedChildIterator, 1.76 + // if there is a binding attached to the original parent, mParent points to 1.77 + // the <xbl:content> element for the binding. 1.78 + nsIContent* mParent; 1.79 + 1.80 + // The current child. When we encounter an insertion point, 1.81 + // mChild remains as the insertion point whose content we're iterating (and 1.82 + // our state is controled by mDefaultChild or mIndexInInserted depending on 1.83 + // whether the insertion point expands to its default content or not). 1.84 + nsIContent* mChild; 1.85 + 1.86 + // If non-null, this points to the current default content for the current 1.87 + // insertion point that we're iterating (i.e. mChild, which must be an 1.88 + // nsXBLChildrenElement or HTMLContentElement). Once this transitions back 1.89 + // to null, we continue iterating at mChild's next sibling. 1.90 + nsIContent* mDefaultChild; 1.91 + 1.92 + // If non-null, this points to an iterator of the explicit children of 1.93 + // the ShadowRoot projected by the current shadow element that we're 1.94 + // iterating. 1.95 + nsAutoPtr<ExplicitChildIterator> mShadowIterator; 1.96 + 1.97 + // If not zero, we're iterating inserted children for an insertion point. This 1.98 + // is an index into mChild's inserted children array (mChild must be an 1.99 + // nsXBLChildrenElement). The index is one past the "current" child (as 1.100 + // opposed to mChild which represents the "current" child). 1.101 + uint32_t mIndexInInserted; 1.102 + 1.103 + // A flag to let us know that we haven't started iterating yet. 1.104 + bool mIsFirst; 1.105 +}; 1.106 + 1.107 +// Iterates over the flattened children of a node, which accounts for anonymous 1.108 +// children and nodes moved by insertion points. If a node has anonymous 1.109 +// children, those are iterated over. 1.110 +class FlattenedChildIterator : public ExplicitChildIterator 1.111 +{ 1.112 +public: 1.113 + FlattenedChildIterator(nsIContent* aParent); 1.114 + 1.115 + bool XBLInvolved() { return mXBLInvolved; } 1.116 + 1.117 +private: 1.118 + // For certain optimizations, nsCSSFrameConstructor needs to know if the 1.119 + // child list of the element that we're iterating matches its .childNodes. 1.120 + bool mXBLInvolved; 1.121 +}; 1.122 + 1.123 +} // namespace dom 1.124 +} // namespace mozilla 1.125 + 1.126 +#endif