Backed out changeset 8366e5cc9f57 (bug 125282) because of four windows unit test...
[mozilla-central.git] / layout / tables / nsTableRowGroupFrame.h
blob96eb0b32a7e5d9cb3bb01cef6948089e6b526308
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.org 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 ***** */
37 #ifndef nsTableRowGroupFrame_h__
38 #define nsTableRowGroupFrame_h__
40 #include "nscore.h"
41 #include "nsHTMLContainerFrame.h"
42 #include "nsIAtom.h"
43 #include "nsILineIterator.h"
44 #include "nsTablePainter.h"
45 #include "nsTArray.h"
46 #include "nsCSSAnonBoxes.h"
48 class nsTableFrame;
49 class nsTableRowFrame;
50 class nsTableCellFrame;
52 struct nsRowGroupReflowState {
53 const nsHTMLReflowState& reflowState; // Our reflow state
55 nsTableFrame* tableFrame;
57 // The available size (computed from the parent)
58 nsSize availSize;
60 // Running y-offset
61 nscoord y;
63 nsRowGroupReflowState(const nsHTMLReflowState& aReflowState,
64 nsTableFrame* aTableFrame)
65 :reflowState(aReflowState), tableFrame(aTableFrame)
67 availSize.width = reflowState.availableWidth;
68 availSize.height = reflowState.availableHeight;
69 y = 0;
72 ~nsRowGroupReflowState() {}
75 // use the following bits from nsFrame's frame state
77 // thead or tfoot should be repeated on every printed page
78 #define NS_ROWGROUP_REPEATABLE 0x80000000
79 #define NS_ROWGROUP_HAS_STYLE_HEIGHT 0x40000000
80 // the next is also used on rows (see nsTableRowGroupFrame::InitRepeatedFrame)
81 #define NS_REPEATED_ROW_OR_ROWGROUP 0x10000000
82 #define NS_ROWGROUP_HAS_ROW_CURSOR 0x08000000
84 #define MIN_ROWS_NEEDING_CURSOR 20
86 /**
87 * nsTableRowGroupFrame is the frame that maps row groups
88 * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
89 * outside of an nsTableFrame. It assumes that its parent is an nsTableFrame, and
90 * its children are nsTableRowFrames.
92 * @see nsTableFrame
93 * @see nsTableRowFrame
95 class nsTableRowGroupFrame
96 : public nsHTMLContainerFrame
97 , public nsILineIterator
99 public:
100 NS_DECLARE_FRAME_ACCESSOR(nsTableRowGroupFrame)
101 NS_DECL_QUERYFRAME
103 /** instantiate a new instance of nsTableRowFrame.
104 * @param aPresShell the pres shell for this frame
106 * @return the frame that was created
108 friend nsIFrame* NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
109 virtual ~nsTableRowGroupFrame();
110 /** @see nsIFrame::DidSetStyleContext */
111 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
113 NS_IMETHOD AppendFrames(nsIAtom* aListName,
114 nsFrameList& aFrameList);
116 NS_IMETHOD InsertFrames(nsIAtom* aListName,
117 nsIFrame* aPrevFrame,
118 nsFrameList& aFrameList);
120 NS_IMETHOD RemoveFrame(nsIAtom* aListName,
121 nsIFrame* aOldFrame);
123 virtual nsMargin GetUsedMargin() const;
124 virtual nsMargin GetUsedBorder() const;
125 virtual nsMargin GetUsedPadding() const;
127 NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
128 const nsRect& aDirtyRect,
129 const nsDisplayListSet& aLists);
131 /** calls Reflow for all of its child rows.
132 * Rows are all set to the same width and stacked vertically.
133 * <P> rows are not split unless absolutely necessary.
135 * @param aDesiredSize width set to width of rows, height set to
136 * sum of height of rows that fit in aMaxSize.height.
138 * @see nsIFrame::Reflow
140 NS_IMETHOD Reflow(nsPresContext* aPresContext,
141 nsHTMLReflowMetrics& aDesiredSize,
142 const nsHTMLReflowState& aReflowState,
143 nsReflowStatus& aStatus);
146 * Get the "type" of the frame
148 * @see nsGkAtoms::tableRowGroupFrame
150 virtual nsIAtom* GetType() const;
152 virtual PRBool IsContainingBlock() const;
154 nsTableRowFrame* GetFirstRow();
156 #ifdef DEBUG
157 NS_IMETHOD GetFrameName(nsAString& aResult) const;
158 #endif
160 /** return the number of child rows (not necessarily == number of child frames) */
161 PRInt32 GetRowCount();
163 /** return the table-relative row index of the first row in this rowgroup.
164 * if there are no rows, -1 is returned.
166 PRInt32 GetStartRowIndex();
168 /** Adjust the row indices of all rows whose index is >= aRowIndex.
169 * @param aRowIndex - start adjusting with this index
170 * @param aAdjustment - shift the row index by this amount
172 void AdjustRowIndices(PRInt32 aRowIndex,
173 PRInt32 anAdjustment);
176 * Used for header and footer row group frames that are repeated when
177 * splitting a table frame.
179 * Performs any table specific initialization
181 * @param aHeaderFooterFrame the original header or footer row group frame
182 * that was repeated
184 nsresult InitRepeatedFrame(nsPresContext* aPresContext,
185 nsTableRowGroupFrame* aHeaderFooterFrame);
189 * Get the total height of all the row rects
191 nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState);
193 nsMargin* GetBCBorderWidth(nsMargin& aBorder);
196 * Gets inner border widths before collapsing with cell borders
197 * Caller must get top border from previous row group or from table
198 * GetContinuousBCBorderWidth will not overwrite aBorder.top
199 * see nsTablePainter about continuous borders
201 void GetContinuousBCBorderWidth(nsMargin& aBorder);
203 * Sets full border widths before collapsing with cell borders
204 * @param aForSide - side to set; only right, left, and bottom valid
206 void SetContinuousBCBorderWidth(PRUint8 aForSide,
207 BCPixelSize aPixelValue);
209 * Adjust to the effect of visibibility:collapse on the row group and
210 * its children
211 * @return additional shift upward that should be applied to
212 * subsequent rowgroups due to rows and this rowgroup
213 * being collapsed
214 * @param aYTotalOffset the total amount that the rowgroup is shifted up
215 * @param aWidth new width of the rowgroup
217 nscoord CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
218 nscoord aWidth);
220 // nsILineIterator methods
221 public:
222 virtual void DisposeLineIterator() { }
224 // The table row is the equivalent to a line in block layout.
225 // The nsILineIterator assumes that a line resides in a block, this role is
226 // fullfilled by the row group. Rows in table are counted relative to the
227 // table. The row index of row corresponds to the cellmap coordinates. The
228 // line index with respect to a row group can be computed by substracting the
229 // row index of the first row in the row group.
231 /** Get the number of rows in a row group
232 * @return the number of lines in a row group
234 virtual PRInt32 GetNumLines();
236 /** @see nsILineIterator.h GetDirection
237 * @return true if the table is rtl
239 virtual PRBool GetDirection();
241 /** Return structural information about a line.
242 * @param aLineNumber - the index of the row relative to the row group
243 * If the line-number is invalid then
244 * aFirstFrameOnLine will be nsnull and
245 * aNumFramesOnLine will be zero.
246 * @param aFirstFrameOnLine - the first cell frame that originates in row
247 * with a rowindex that matches a line number
248 * @param aNumFramesOnLine - return the numbers of cells originating in
249 * this row
250 * @param aLineBounds - rect of the row
251 * @param aLineFlags - unused set to 0
253 NS_IMETHOD GetLine(PRInt32 aLineNumber,
254 nsIFrame** aFirstFrameOnLine,
255 PRInt32* aNumFramesOnLine,
256 nsRect& aLineBounds,
257 PRUint32* aLineFlags);
259 /** Given a frame that's a child of the rowgroup, find which line its on.
260 * @param aFrame - frame, should be a row
261 * @return row index relative to the row group if this a row
262 * frame. -1 if the frame cannot be found.
264 virtual PRInt32 FindLineContaining(nsIFrame* aFrame);
266 /** not implemented
267 * the function is also not called in our tree
269 virtual PRInt32 FindLineAt(nscoord aY);
271 /** Find the orginating cell frame on a row that is the nearest to the
272 * coordinate X.
273 * @param aLineNumber - the index of the row relative to the row group
274 * @param aX - X coordinate in twips relative to the
275 * origin of the row group
276 * @param aFrameFound - pointer to the cellframe
277 * @param aXIsBeforeFirstFrame - the point is before the first originating
278 * cellframe
279 * @param aXIsAfterLastFrame - the point is after the last originating
280 * cellframe
282 NS_IMETHOD FindFrameAt(PRInt32 aLineNumber,
283 nscoord aX,
284 nsIFrame** aFrameFound,
285 PRBool* aXIsBeforeFirstFrame,
286 PRBool* aXIsAfterLastFrame);
288 #ifdef IBMBIDI
289 /** Check whether visual and logical order of cell frames within a line are
290 * identical. As the layout will reorder them this is always the case
291 * @param aLine - the index of the row relative to the table
292 * @param aIsReordered - returns false
293 * @param aFirstVisual - if the table is rtl first originating cell frame
294 * @param aLastVisual - if the table is rtl last originating cell frame
297 NS_IMETHOD CheckLineOrder(PRInt32 aLine,
298 PRBool *aIsReordered,
299 nsIFrame **aFirstVisual,
300 nsIFrame **aLastVisual);
301 #endif
303 /** Find the next originating cell frame that originates in the row.
304 * @param aFrame - cell frame to start with, will return the next cell
305 * originating in a row
306 * @param aLineNumber - the index of the row relative to the table
308 NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, PRInt32 aLineNumber);
310 // row cursor methods to speed up searching for the row(s)
311 // containing a point. The basic idea is that we set the cursor
312 // property if the rows' y and yMosts are non-decreasing (considering only
313 // rows with nonempty overflowAreas --- empty overflowAreas never participate
314 // in event handling or painting), and the rowgroup has sufficient number of
315 // rows. The cursor property points to a "recently used" row. If we get a
316 // series of requests that work on rows "near" the cursor, then we can find
317 // those nearby rows quickly by starting our search at the cursor.
318 // This code is based on the line cursor code in nsBlockFrame. It's more general
319 // though, and could be extracted and used elsewhere.
320 struct FrameCursorData {
321 nsTArray<nsIFrame*> mFrames;
322 PRUint32 mCursorIndex;
323 nscoord mOverflowAbove;
324 nscoord mOverflowBelow;
326 FrameCursorData()
327 : mFrames(MIN_ROWS_NEEDING_CURSOR), mCursorIndex(0), mOverflowAbove(0),
328 mOverflowBelow(0) {}
330 PRBool AppendFrame(nsIFrame* aFrame);
332 void FinishBuildingCursor() {
333 mFrames.Compact();
337 // Clear out row cursor because we're disturbing the rows (e.g., Reflow)
338 void ClearRowCursor();
341 * Get the first row that might contain y-coord 'aY', or nsnull if you must search
342 * all rows.
343 * The actual row returned might not contain 'aY', but if not, it is guaranteed
344 * to be before any row which does contain 'aY'.
345 * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y.
346 * To find all rows that intersect the vertical interval aY/aYMost, call
347 * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all
348 * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost.
349 * That row and all subsequent rows cannot intersect the interval.
351 nsIFrame* GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove);
354 * Set up the row cursor. After this, call AppendFrame for every
355 * child frame in sibling order. Ensure that the child frame y and YMost values
356 * form non-decreasing sequences (should always be true for table rows);
357 * if this is violated, call ClearRowCursor(). If we return nsnull, then we
358 * decided not to use a cursor or we already have one set up.
360 FrameCursorData* SetupRowCursor();
362 PRBool IsScrolled() {
363 // Note that if mOverflowY is CLIP, so is mOverflowX, and we need to clip the background
364 // as if the rowgroup is scrollable.
365 return GetStyleContext()->GetPseudoType() == nsCSSAnonBoxes::scrolledContent ||
366 GetStyleDisplay()->mOverflowY == NS_STYLE_OVERFLOW_CLIP;
369 virtual nsILineIterator* GetLineIterator() { return this; }
371 protected:
372 nsTableRowGroupFrame(nsStyleContext* aContext);
374 void InitChildReflowState(nsPresContext& aPresContext,
375 PRBool aBorderCollapse,
376 nsHTMLReflowState& aReflowState);
378 /** implement abstract method on nsHTMLContainerFrame */
379 virtual PRIntn GetSkipSides() const;
381 void PlaceChild(nsPresContext* aPresContext,
382 nsRowGroupReflowState& aReflowState,
383 nsIFrame* aKidFrame,
384 nsHTMLReflowMetrics& aDesiredSize,
385 const nsRect& aOriginalKidRect,
386 const nsRect& aOriginalKidOverflowRect);
388 void CalculateRowHeights(nsPresContext* aPresContext,
389 nsHTMLReflowMetrics& aDesiredSize,
390 const nsHTMLReflowState& aReflowState);
392 void DidResizeRows(nsHTMLReflowMetrics& aDesiredSize);
394 void SlideChild(nsRowGroupReflowState& aReflowState,
395 nsIFrame* aKidFrame);
398 * Reflow the frames we've already created
400 * @param aPresContext presentation context to use
401 * @param aReflowState current inline state
402 * @return true if we successfully reflowed all the mapped children and false
403 * otherwise, e.g. we pushed children to the next in flow
405 NS_METHOD ReflowChildren(nsPresContext* aPresContext,
406 nsHTMLReflowMetrics& aDesiredSize,
407 nsRowGroupReflowState& aReflowState,
408 nsReflowStatus& aStatus,
409 PRBool* aPageBreakBeforeEnd = nsnull);
411 nsresult SplitRowGroup(nsPresContext* aPresContext,
412 nsHTMLReflowMetrics& aDesiredSize,
413 const nsHTMLReflowState& aReflowState,
414 nsTableFrame* aTableFrame,
415 nsReflowStatus& aStatus);
417 void SplitSpanningCells(nsPresContext& aPresContext,
418 const nsHTMLReflowState& aReflowState,
419 nsTableFrame& aTableFrame,
420 nsTableRowFrame& aFirstRow,
421 nsTableRowFrame& aLastRow,
422 PRBool aFirstRowIsTopOfPage,
423 nscoord aSpanningRowBottom,
424 nsTableRowFrame*& aContRowFrame,
425 nsTableRowFrame*& aFirstTruncatedRow,
426 nscoord& aDesiredHeight);
428 void CreateContinuingRowFrame(nsPresContext& aPresContext,
429 nsIFrame& aRowFrame,
430 nsIFrame** aContRowFrame);
432 PRBool IsSimpleRowFrame(nsTableFrame* aTableFrame,
433 nsIFrame* aFrame);
435 void GetNextRowSibling(nsIFrame** aRowFrame);
437 void UndoContinuedRow(nsPresContext* aPresContext,
438 nsTableRowFrame* aRow);
440 private:
441 // border widths in pixels in the collapsing border model
442 BCPixelSize mRightContBorderWidth;
443 BCPixelSize mBottomContBorderWidth;
444 BCPixelSize mLeftContBorderWidth;
446 public:
447 virtual nsIFrame* GetFirstFrame() { return mFrames.FirstChild(); }
448 virtual nsIFrame* GetLastFrame() { return mFrames.LastChild(); }
449 virtual void GetNextFrame(nsIFrame* aFrame,
450 nsIFrame** aResult) { *aResult = aFrame->GetNextSibling(); }
451 PRBool IsRepeatable() const;
452 void SetRepeatable(PRBool aRepeatable);
453 PRBool HasStyleHeight() const;
454 void SetHasStyleHeight(PRBool aValue);
458 inline PRBool nsTableRowGroupFrame::IsRepeatable() const
460 return (mState & NS_ROWGROUP_REPEATABLE) == NS_ROWGROUP_REPEATABLE;
463 inline void nsTableRowGroupFrame::SetRepeatable(PRBool aRepeatable)
465 if (aRepeatable) {
466 mState |= NS_ROWGROUP_REPEATABLE;
467 } else {
468 mState &= ~NS_ROWGROUP_REPEATABLE;
472 inline PRBool nsTableRowGroupFrame::HasStyleHeight() const
474 return (mState & NS_ROWGROUP_HAS_STYLE_HEIGHT) == NS_ROWGROUP_HAS_STYLE_HEIGHT;
477 inline void nsTableRowGroupFrame::SetHasStyleHeight(PRBool aValue)
479 if (aValue) {
480 mState |= NS_ROWGROUP_HAS_STYLE_HEIGHT;
481 } else {
482 mState &= ~NS_ROWGROUP_HAS_STYLE_HEIGHT;
486 inline void
487 nsTableRowGroupFrame::GetContinuousBCBorderWidth(nsMargin& aBorder)
489 PRInt32 aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
490 aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
491 mRightContBorderWidth);
492 aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
493 mBottomContBorderWidth);
494 aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips,
495 mLeftContBorderWidth);
496 return;
498 #endif