Bug 1550519 - Show a translucent parent highlight when a subgrid is highlighted....
[gecko.git] / dom / base / ContentIterator.h
blobfe92e03ec7fc183cf7739231373074415a707be3
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_ContentIterator_h
8 #define mozilla_ContentIterator_h
10 #include "mozilla/RangeBoundary.h"
11 #include "nsCOMPtr.h"
12 #include "nsCycleCollectionParticipant.h"
13 #include "nsIContent.h"
14 #include "nsRange.h"
15 #include "nsTArray.h"
17 namespace mozilla {
19 /**
20 * ContentIteratorBase is a base class of PostContentIterator,
21 * PreContentIterator and ContentSubtreeIterator. Making each concrete
22 * classes "final", compiler can avoid virtual calls if they are treated
23 * by the users directly.
25 class ContentIteratorBase {
26 public:
27 ContentIteratorBase() = delete;
28 ContentIteratorBase(const ContentIteratorBase&) = delete;
29 ContentIteratorBase& operator=(const ContentIteratorBase&) = delete;
30 virtual ~ContentIteratorBase() = default;
32 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ContentIteratorBase)
34 virtual nsresult Init(nsINode* aRoot);
35 virtual nsresult Init(nsRange* aRange);
36 virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
37 nsINode* aEndContainer, uint32_t aEndOffset);
38 virtual nsresult Init(const RawRangeBoundary& aStart,
39 const RawRangeBoundary& aEnd);
41 virtual void First();
42 virtual void Last();
43 virtual void Next();
44 virtual void Prev();
46 virtual nsINode* GetCurrentNode();
48 virtual bool IsDone();
50 virtual nsresult PositionAt(nsINode* aCurNode);
52 protected:
53 explicit ContentIteratorBase(bool aPre);
55 /**
56 * Callers must guarantee that:
57 * - Neither aStartContainer nor aEndContainer is nullptr.
58 * - aStartOffset and aEndOffset are valid for its container.
59 * - The start point and the end point are in document order.
61 nsresult InitInternal(const RawRangeBoundary& aStart,
62 const RawRangeBoundary& aEnd);
64 // Recursively get the deepest first/last child of aRoot. This will return
65 // aRoot itself if it has no children.
66 nsINode* GetDeepFirstChild(nsINode* aRoot);
67 nsIContent* GetDeepFirstChild(nsIContent* aRoot);
68 nsINode* GetDeepLastChild(nsINode* aRoot);
69 nsIContent* GetDeepLastChild(nsIContent* aRoot);
71 // Get the next/previous sibling of aNode, or its parent's, or grandparent's,
72 // etc. Returns null if aNode and all its ancestors have no next/previous
73 // sibling.
74 nsIContent* GetNextSibling(nsINode* aNode);
75 nsIContent* GetPrevSibling(nsINode* aNode);
77 nsINode* NextNode(nsINode* aNode);
78 nsINode* PrevNode(nsINode* aNode);
80 void MakeEmpty();
82 nsCOMPtr<nsINode> mCurNode;
83 nsCOMPtr<nsINode> mFirst;
84 nsCOMPtr<nsINode> mLast;
85 nsCOMPtr<nsINode> mCommonParent;
87 bool mIsDone;
88 bool mPre;
89 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
90 ContentIteratorBase&, const char*,
91 uint32_t);
92 friend void ImplCycleCollectionUnlink(ContentIteratorBase&);
95 // Each concreate class of ContentIteratorBase may be owned by another class
96 // which may be owned by JS. Therefore, all of them should be in the cycle
97 // collection. However, we cannot make non-refcountable classes only with the
98 // macros. So, we need to make them cycle collectable without the macros.
99 inline void ImplCycleCollectionTraverse(
100 nsCycleCollectionTraversalCallback& aCallback, ContentIteratorBase& aField,
101 const char* aName, uint32_t aFlags = 0) {
102 ImplCycleCollectionTraverse(aCallback, aField.mCurNode, aName, aFlags);
103 ImplCycleCollectionTraverse(aCallback, aField.mFirst, aName, aFlags);
104 ImplCycleCollectionTraverse(aCallback, aField.mLast, aName, aFlags);
105 ImplCycleCollectionTraverse(aCallback, aField.mCommonParent, aName, aFlags);
108 inline void ImplCycleCollectionUnlink(ContentIteratorBase& aField) {
109 ImplCycleCollectionUnlink(aField.mCurNode);
110 ImplCycleCollectionUnlink(aField.mFirst);
111 ImplCycleCollectionUnlink(aField.mLast);
112 ImplCycleCollectionUnlink(aField.mCommonParent);
116 * A simple iterator class for traversing the content in "close tag" order.
118 class PostContentIterator final : public ContentIteratorBase {
119 public:
120 PostContentIterator() : ContentIteratorBase(false) {}
121 PostContentIterator(const PostContentIterator&) = delete;
122 PostContentIterator& operator=(const PostContentIterator&) = delete;
123 virtual ~PostContentIterator() = default;
124 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
125 PostContentIterator&, const char*,
126 uint32_t);
127 friend void ImplCycleCollectionUnlink(PostContentIterator&);
130 inline void ImplCycleCollectionTraverse(
131 nsCycleCollectionTraversalCallback& aCallback, PostContentIterator& aField,
132 const char* aName, uint32_t aFlags = 0) {
133 ImplCycleCollectionTraverse(
134 aCallback, static_cast<ContentIteratorBase&>(aField), aName, aFlags);
137 inline void ImplCycleCollectionUnlink(PostContentIterator& aField) {
138 ImplCycleCollectionUnlink(static_cast<ContentIteratorBase&>(aField));
142 * A simple iterator class for traversing the content in "start tag" order.
144 class PreContentIterator final : public ContentIteratorBase {
145 public:
146 PreContentIterator() : ContentIteratorBase(true) {}
147 PreContentIterator(const PreContentIterator&) = delete;
148 PreContentIterator& operator=(const PreContentIterator&) = delete;
149 virtual ~PreContentIterator() = default;
150 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
151 PreContentIterator&, const char*,
152 uint32_t);
153 friend void ImplCycleCollectionUnlink(PreContentIterator&);
156 inline void ImplCycleCollectionTraverse(
157 nsCycleCollectionTraversalCallback& aCallback, PreContentIterator& aField,
158 const char* aName, uint32_t aFlags = 0) {
159 ImplCycleCollectionTraverse(
160 aCallback, static_cast<ContentIteratorBase&>(aField), aName, aFlags);
163 inline void ImplCycleCollectionUnlink(PreContentIterator& aField) {
164 ImplCycleCollectionUnlink(static_cast<ContentIteratorBase&>(aField));
168 * A simple iterator class for traversing the content in "top subtree" order.
170 class ContentSubtreeIterator final : public ContentIteratorBase {
171 public:
172 ContentSubtreeIterator() : ContentIteratorBase(true) {}
173 ContentSubtreeIterator(const ContentSubtreeIterator&) = delete;
174 ContentSubtreeIterator& operator=(const ContentSubtreeIterator&) = delete;
175 virtual ~ContentSubtreeIterator() = default;
177 virtual nsresult Init(nsINode* aRoot) override;
178 virtual nsresult Init(nsRange* aRange) override;
179 virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
180 nsINode* aEndContainer, uint32_t aEndOffset) override;
181 virtual nsresult Init(const RawRangeBoundary& aStart,
182 const RawRangeBoundary& aEnd) override;
184 virtual void Next() override;
185 virtual void Prev() override;
186 // Must override these because we don't do PositionAt
187 virtual void First() override;
188 // Must override these because we don't do PositionAt
189 virtual void Last() override;
191 virtual nsresult PositionAt(nsINode* aCurNode) override;
193 friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
194 ContentSubtreeIterator&, const char*,
195 uint32_t);
196 friend void ImplCycleCollectionUnlink(ContentSubtreeIterator&);
198 protected:
200 * Callers must guarantee that mRange isn't nullptr and is positioned.
202 nsresult InitWithRange();
204 // Returns the highest inclusive ancestor of aNode that's in the range
205 // (possibly aNode itself). Returns null if aNode is null, or is not itself
206 // in the range. A node is in the range if (node, 0) comes strictly after
207 // the range endpoint, and (node, node.length) comes strictly before it, so
208 // the range's start and end nodes will never be considered "in" it.
209 nsIContent* GetTopAncestorInRange(nsINode* aNode);
211 RefPtr<nsRange> mRange;
213 AutoTArray<nsIContent*, 8> mEndNodes;
216 inline void ImplCycleCollectionTraverse(
217 nsCycleCollectionTraversalCallback& aCallback,
218 ContentSubtreeIterator& aField, const char* aName, uint32_t aFlags = 0) {
219 ImplCycleCollectionTraverse(aCallback, aField.mRange, aName, aFlags);
220 ImplCycleCollectionTraverse(
221 aCallback, static_cast<ContentIteratorBase&>(aField), aName, aFlags);
224 inline void ImplCycleCollectionUnlink(ContentSubtreeIterator& aField) {
225 ImplCycleCollectionUnlink(aField.mRange);
226 ImplCycleCollectionUnlink(static_cast<ContentIteratorBase&>(aField));
229 } // namespace mozilla
231 #endif // #ifndef mozilla_ContentIterator_h