nsFrameTraversal.h (3869B)
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/. */ 6 7 #ifndef NSFRAMETRAVERSAL_H 8 #define NSFRAMETRAVERSAL_H 9 10 #include <cstdint> 11 12 #include "mozilla/Attributes.h" 13 14 class nsIFrame; 15 class nsPresContext; 16 17 namespace mozilla::dom { 18 class Element; 19 } // namespace mozilla::dom 20 21 class MOZ_STACK_CLASS nsFrameIterator final { 22 public: 23 using Element = mozilla::dom::Element; 24 25 void First(); 26 void Next(); 27 nsIFrame* CurrentItem(); 28 bool IsDone(); 29 30 void Last(); 31 void Prev(); 32 33 inline nsIFrame* Traverse(bool aForward) { 34 if (aForward) { 35 Next(); 36 } else { 37 Prev(); 38 } 39 return CurrentItem(); 40 }; 41 42 enum class Type : uint8_t { 43 // only leaf nodes 44 Leaf, 45 // "open tag" order 46 PreOrder, 47 // "close tag" order 48 PostOrder, 49 }; 50 nsFrameIterator(nsPresContext* aPresContext, nsIFrame* aStart, Type aType, 51 bool aVisual, bool aLockInScrollView, bool aFollowOOFs, 52 bool aSkipPopupChecks, const Element* aLimiter = nullptr); 53 ~nsFrameIterator() = default; 54 55 protected: 56 void SetCurrent(nsIFrame* aFrame) { mCurrent = aFrame; } 57 nsIFrame* GetCurrent() { return mCurrent; } 58 nsIFrame* GetStart() { return mStart; } 59 nsIFrame* GetLast() { return mLast; } 60 void SetLast(nsIFrame* aFrame) { mLast = aFrame; } 61 int8_t GetOffEdge() { return mOffEdge; } 62 void SetOffEdge(int8_t aOffEdge) { mOffEdge = aOffEdge; } 63 64 /* 65 Our own versions of the standard frame tree navigation 66 methods, which, if the iterator is following out-of-flows, 67 apply the following rules for placeholder frames: 68 69 - If a frame HAS a placeholder frame, getting its parent 70 gets the placeholder's parent. 71 72 - If a frame's first child or next/prev sibling IS a 73 placeholder frame, then we instead return the real frame. 74 75 - If a frame HAS a placeholder frame, getting its next/prev 76 sibling gets the placeholder frame's next/prev sibling. 77 78 These are all applied recursively to support multiple levels of 79 placeholders. 80 */ 81 82 nsIFrame* GetParentFrameInLimiter(nsIFrame* aFrame) { 83 return GetParentFrame(aFrame, mLimiter); 84 } 85 nsIFrame* GetParentFrame(nsIFrame* aFrame, const Element* aAncestorLimiter); 86 87 // like GetParentFrame but returns null once a popup frame is reached 88 nsIFrame* GetParentFrameNotPopup(nsIFrame* aFrame); 89 90 nsIFrame* GetFirstChild(nsIFrame* aFrame); 91 nsIFrame* GetLastChild(nsIFrame* aFrame); 92 93 nsIFrame* GetNextSibling(nsIFrame* aFrame); 94 nsIFrame* GetPrevSibling(nsIFrame* aFrame); 95 96 /* 97 These methods are overridden by the bidi visual iterator to have the 98 semantics of "get first child in visual order", "get last child in visual 99 order", "get next sibling in visual order" and "get previous sibling in 100 visual order". 101 */ 102 103 nsIFrame* GetFirstChildInner(nsIFrame* aFrame); 104 nsIFrame* GetLastChildInner(nsIFrame* aFrame); 105 106 nsIFrame* GetNextSiblingInner(nsIFrame* aFrame); 107 nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame); 108 109 /** 110 * Return the placeholder frame for aFrame if it has one, otherwise return 111 * aFrame itself. 112 */ 113 nsIFrame* GetPlaceholderFrame(nsIFrame* aFrame); 114 bool IsPopupFrame(nsIFrame* aFrame); 115 116 bool IsInvokerOpenPopoverFrame(nsIFrame* aFrame); 117 118 nsPresContext* const mPresContext; 119 const bool mLockScroll; 120 const bool mFollowOOFs; 121 const bool mSkipPopupChecks; 122 const bool mVisual; 123 const Type mType; 124 125 private: 126 nsIFrame* const mStart; 127 nsIFrame* mCurrent; 128 nsIFrame* mLast; // the last one that was in current; 129 const Element* const mLimiter; 130 int8_t mOffEdge; // 0= no -1 to far prev, 1 to far next; 131 }; 132 133 #endif // NSFRAMETRAVERSAL_H