(no bug) fix end-of-line whitespace so I can add a changeset with an a=bustage annotation
[mozilla-central.git] / layout / generic / nsFrameList.h
blob7cb750dd97ca3d4fad3c9f3874c140dbe3395d2d
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef nsFrameList_h___
39 #define nsFrameList_h___
41 #include "nscore.h"
42 #include "nsTraceRefcnt.h"
43 #include <stdio.h> /* for FILE* */
44 #include "nsDebug.h"
46 class nsIFrame;
48 // Uncomment this to enable expensive frame-list integrity checking
49 // #define DEBUG_FRAME_LIST
51 /**
52 * A class for managing a list of frames.
54 class nsFrameList {
55 public:
56 nsFrameList() :
57 mFirstChild(nsnull), mLastChild(nsnull)
59 MOZ_COUNT_CTOR(nsFrameList);
62 nsFrameList(nsIFrame* aFirstFrame, nsIFrame* aLastFrame) :
63 mFirstChild(aFirstFrame), mLastChild(aLastFrame)
65 MOZ_COUNT_CTOR(nsFrameList);
66 VerifyList();
69 nsFrameList(const nsFrameList& aOther) :
70 mFirstChild(aOther.mFirstChild), mLastChild(aOther.mLastChild)
72 MOZ_COUNT_CTOR(nsFrameList);
75 ~nsFrameList() {
76 MOZ_COUNT_DTOR(nsFrameList);
77 // Don't destroy our frames here, so that we can have temporary nsFrameLists
80 /**
81 * For each frame in this list: remove it from the list then call
82 * Destroy() on it.
84 void DestroyFrames();
86 /**
87 * For each frame in this list: remove it from the list then call
88 * DestroyFrom() on it.
90 void DestroyFramesFrom(nsIFrame* aDestructRoot);
92 /**
93 * For each frame in this list: remove it from the list then call
94 * Destroy() on it. Finally <code>delete this</code>.
97 void Destroy();
99 /**
100 * For each frame in this list: remove it from the list then call
101 * DestroyFrom() on it. Finally <code>delete this</code>.
104 void DestroyFrom(nsIFrame* aDestructRoot);
106 void Clear() { mFirstChild = mLastChild = nsnull; }
108 void SetFrames(nsIFrame* aFrameList);
110 void SetFrames(nsFrameList& aFrameList) {
111 NS_PRECONDITION(!mFirstChild, "Losing frames");
113 mFirstChild = aFrameList.FirstChild();
114 mLastChild = aFrameList.LastChild();
115 aFrameList.Clear();
118 class Slice;
121 * Append aFrameList to this list. If aParent is not null,
122 * reparents the newly added frames. Clears out aFrameList and
123 * returns a list slice represening the newly-appended frames.
125 Slice AppendFrames(nsIFrame* aParent, nsFrameList& aFrameList) {
126 return InsertFrames(aParent, LastChild(), aFrameList);
131 * Append aFrame to this list. If aParent is not null,
132 * reparents the newly added frame.
134 void AppendFrame(nsIFrame* aParent, nsIFrame* aFrame) {
135 nsFrameList temp(aFrame, aFrame);
136 AppendFrames(aParent, temp);
140 * Take aFrame out of the frame list. This also disconnects aFrame
141 * from the sibling list. The frame must be non-null and present on
142 * this list.
144 void RemoveFrame(nsIFrame* aFrame);
147 * Take aFrame out of the frame list, if present. This also disconnects
148 * aFrame from the sibling list. aFrame must be non-null but is not
149 * required to be on the list.
150 * @return PR_TRUE if aFrame was removed
152 PRBool RemoveFrameIfPresent(nsIFrame* aFrame);
155 * Take the frames after aAfterFrame out of the frame list. If
156 * aAfterFrame is null, removes the entire list.
157 * @param aAfterFrame a frame in this list, or null
158 * @return the removed frames, if any
160 nsFrameList RemoveFramesAfter(nsIFrame* aAfterFrame);
163 * Take the first frame (if any) out of the frame list.
164 * @return the first child, or nsnull if the list is empty
166 nsIFrame* RemoveFirstChild();
169 * Take aFrame out of the frame list and then destroy it.
170 * The frame must be non-null and present on this list.
172 void DestroyFrame(nsIFrame* aFrame);
175 * If aFrame is present on this list then take it out of the list and
176 * then destroy it. The frame must be non-null.
177 * @return PR_TRUE if the frame was found
179 PRBool DestroyFrameIfPresent(nsIFrame* aFrame);
182 * Insert aFrame right after aPrevSibling, or prepend it to this
183 * list if aPrevSibling is null. If aParent is not null, also
184 * reparents newly-added frame. Note that this method always
185 * sets the frame's nextSibling pointer.
187 void InsertFrame(nsIFrame* aParent, nsIFrame* aPrevSibling,
188 nsIFrame* aFrame) {
189 nsFrameList temp(aFrame, aFrame);
190 InsertFrames(aParent, aPrevSibling, temp);
195 * Inserts aFrameList into this list after aPrevSibling (at the beginning if
196 * aPrevSibling is null). If aParent is not null, reparents the newly added
197 * frames. Clears out aFrameList and returns a list slice representing the
198 * newly-inserted frames.
200 Slice InsertFrames(nsIFrame* aParent, nsIFrame* aPrevSibling,
201 nsFrameList& aFrameList);
203 class FrameLinkEnumerator;
206 * Split this frame list such that all the frames before the link pointed to
207 * by aLink end up in the returned list, while the remaining frames stay in
208 * this list. After this call, aLink points to the beginning of this list.
210 nsFrameList ExtractHead(FrameLinkEnumerator& aLink);
213 * Split this frame list such that all the frames coming after the link
214 * pointed to by aLink end up in the returned list, while the frames before
215 * that link stay in this list. After this call, aLink is at end.
217 nsFrameList ExtractTail(FrameLinkEnumerator& aLink);
219 nsIFrame* FirstChild() const {
220 return mFirstChild;
223 nsIFrame* LastChild() const {
224 return mLastChild;
227 nsIFrame* FrameAt(PRInt32 aIndex) const;
228 PRInt32 IndexOf(nsIFrame* aFrame) const;
230 PRBool IsEmpty() const {
231 return nsnull == mFirstChild;
234 PRBool NotEmpty() const {
235 return nsnull != mFirstChild;
238 PRBool ContainsFrame(const nsIFrame* aFrame) const;
240 PRInt32 GetLength() const;
243 * If this frame list has only one frame, return that frame.
244 * Otherwise, return null.
246 nsIFrame* OnlyChild() const {
247 if (FirstChild() == LastChild()) {
248 return FirstChild();
250 return nsnull;
254 * Call SetParent(aParent) for each frame in this list.
255 * @param aParent the new parent frame, must be non-null
257 void ApplySetParent(nsIFrame* aParent) const;
259 #ifdef IBMBIDI
261 * Return the frame before this frame in visual order (after Bidi reordering).
262 * If aFrame is null, return the last frame in visual order.
264 nsIFrame* GetPrevVisualFor(nsIFrame* aFrame) const;
267 * Return the frame after this frame in visual order (after Bidi reordering).
268 * If aFrame is null, return the first frame in visual order.
270 nsIFrame* GetNextVisualFor(nsIFrame* aFrame) const;
271 #endif // IBMBIDI
273 #ifdef DEBUG
274 void List(FILE* out) const;
275 #endif
277 static nsresult Init();
278 static void Shutdown() { delete sEmptyList; }
279 static const nsFrameList& EmptyList() { return *sEmptyList; }
281 class Enumerator;
284 * A class representing a slice of a frame list.
286 class Slice {
287 friend class Enumerator;
289 public:
290 // Implicit on purpose, so that we can easily create enumerators from
291 // nsFrameList via this impicit constructor.
292 Slice(const nsFrameList& aList) :
293 #ifdef DEBUG
294 mList(aList),
295 #endif
296 mStart(aList.FirstChild()),
297 mEnd(nsnull)
300 Slice(const nsFrameList& aList, nsIFrame* aStart, nsIFrame* aEnd) :
301 #ifdef DEBUG
302 mList(aList),
303 #endif
304 mStart(aStart),
305 mEnd(aEnd)
308 Slice(const Slice& aOther) :
309 #ifdef DEBUG
310 mList(aOther.mList),
311 #endif
312 mStart(aOther.mStart),
313 mEnd(aOther.mEnd)
316 private:
317 #ifdef DEBUG
318 const nsFrameList& mList;
319 #endif
320 nsIFrame* const mStart; // our starting frame
321 const nsIFrame* const mEnd; // The first frame that is NOT in the slice.
322 // May be null.
325 class Enumerator {
326 public:
327 Enumerator(const Slice& aSlice) :
328 #ifdef DEBUG
329 mSlice(aSlice),
330 #endif
331 mFrame(aSlice.mStart),
332 mEnd(aSlice.mEnd)
335 Enumerator(const Enumerator& aOther) :
336 #ifdef DEBUG
337 mSlice(aOther.mSlice),
338 #endif
339 mFrame(aOther.mFrame),
340 mEnd(aOther.mEnd)
343 PRBool AtEnd() const {
344 // Can't just check mEnd, because some table code goes and destroys the
345 // tail of the frame list (including mEnd!) while iterating over the
346 // frame list.
347 return !mFrame || mFrame == mEnd;
350 /* Next() needs to know about nsIFrame, and nsIFrame will need to
351 know about nsFrameList methods, so in order to inline this put
352 the implementation in nsIFrame.h */
353 inline void Next();
356 * Get the current frame we're pointing to. Do not call this on an
357 * iterator that is at end!
359 nsIFrame* get() const {
360 NS_PRECONDITION(!AtEnd(), "Enumerator is at end");
361 return mFrame;
365 * Get an enumerator that is just like this one, but not limited in terms of
366 * the part of the list it will traverse.
368 Enumerator GetUnlimitedEnumerator() const {
369 return Enumerator(*this, nsnull);
372 #ifdef DEBUG
373 const nsFrameList& List() const { return mSlice.mList; }
374 #endif
376 protected:
377 Enumerator(const Enumerator& aOther, const nsIFrame* const aNewEnd):
378 #ifdef DEBUG
379 mSlice(aOther.mSlice),
380 #endif
381 mFrame(aOther.mFrame),
382 mEnd(aNewEnd)
385 #ifdef DEBUG
386 /* Has to be an object, not a reference, since the slice could
387 well be a temporary constructed from an nsFrameList */
388 const Slice mSlice;
389 #endif
390 nsIFrame* mFrame; // our current frame.
391 const nsIFrame* const mEnd; // The first frame we should NOT enumerate.
392 // May be null.
396 * A class that can be used to enumerate links between frames. When created
397 * from an nsFrameList, it points to the "link" immediately before the first
398 * frame. It can then be advanced until it points to the "link" immediately
399 * after the last frame. At any position, PrevFrame() and NextFrame() are
400 * the frames before and after the given link. This means PrevFrame() is
401 * null when the enumerator is at the beginning of the list and NextFrame()
402 * is null when it's AtEnd().
404 class FrameLinkEnumerator : private Enumerator {
405 public:
406 friend class nsFrameList;
408 FrameLinkEnumerator(const nsFrameList& aList) :
409 Enumerator(aList),
410 mPrev(nsnull)
413 FrameLinkEnumerator(const FrameLinkEnumerator& aOther) :
414 Enumerator(aOther),
415 mPrev(aOther.mPrev)
418 /* This constructor needs to know about nsIFrame, and nsIFrame will need to
419 know about nsFrameList methods, so in order to inline this put
420 the implementation in nsIFrame.h */
421 inline FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame);
423 void operator=(const FrameLinkEnumerator& aOther) {
424 NS_PRECONDITION(&List() == &aOther.List(), "Different lists?");
425 mFrame = aOther.mFrame;
426 mPrev = aOther.mPrev;
429 void Next() {
430 mPrev = mFrame;
431 Enumerator::Next();
434 PRBool AtEnd() const { return Enumerator::AtEnd(); }
436 nsIFrame* PrevFrame() const { return mPrev; }
437 nsIFrame* NextFrame() const { return mFrame; }
439 protected:
440 nsIFrame* mPrev;
443 private:
444 #ifdef DEBUG_FRAME_LIST
445 void VerifyList() const;
446 #else
447 void VerifyList() const {}
448 #endif
450 static const nsFrameList* sEmptyList;
452 protected:
453 nsIFrame* mFirstChild;
454 nsIFrame* mLastChild;
457 #endif /* nsFrameList_h___ */