content/base/src/ChildIterator.h

changeset 0
6474c204b198
     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

mercurial