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
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.
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__
41 #include "nsHTMLContainerFrame.h"
43 #include "nsILineIterator.h"
44 #include "nsTablePainter.h"
46 #include "nsCSSAnonBoxes.h"
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)
63 nsRowGroupReflowState(const nsHTMLReflowState
& aReflowState
,
64 nsTableFrame
* aTableFrame
)
65 :reflowState(aReflowState
), tableFrame(aTableFrame
)
67 availSize
.width
= reflowState
.availableWidth
;
68 availSize
.height
= reflowState
.availableHeight
;
72 ~nsRowGroupReflowState() {}
75 #define NS_ITABLEROWGROUPFRAME_IID \
76 { 0xe940e7bc, 0xb534, 0x11d2, \
77 { 0x95, 0xa2, 0x0, 0x60, 0xb0, 0xc3, 0x44, 0x14 } }
79 // use the following bits from nsFrame's frame state
81 // thead or tfoot should be repeated on every printed page
82 #define NS_ROWGROUP_REPEATABLE 0x80000000
83 #define NS_ROWGROUP_HAS_STYLE_HEIGHT 0x40000000
84 // the next is also used on rows (see nsTableRowGroupFrame::InitRepeatedFrame)
85 #define NS_REPEATED_ROW_OR_ROWGROUP 0x10000000
86 #define NS_ROWGROUP_HAS_ROW_CURSOR 0x08000000
88 #define MIN_ROWS_NEEDING_CURSOR 20
91 * nsTableRowGroupFrame is the frame that maps row groups
92 * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
93 * outside of an nsTableFrame. It assumes that its parent is an nsTableFrame, and
94 * its children are nsTableRowFrames.
97 * @see nsTableRowFrame
99 class nsTableRowGroupFrame
100 : public nsHTMLContainerFrame
101 , public nsILineIterator
104 NS_IMETHOD
QueryInterface(const nsIID
&aIID
, void **aInstancePtr
);
106 /** instantiate a new instance of nsTableRowFrame.
107 * @param aPresShell the pres shell for this frame
109 * @return the frame that was created
111 friend nsIFrame
* NS_NewTableRowGroupFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
);
112 virtual ~nsTableRowGroupFrame();
113 /** @see nsIFrame::DidSetStyleContext */
114 virtual void DidSetStyleContext(nsStyleContext
* aOldStyleContext
);
116 NS_IMETHOD
AppendFrames(nsIAtom
* aListName
,
117 nsIFrame
* aFrameList
);
119 NS_IMETHOD
InsertFrames(nsIAtom
* aListName
,
120 nsIFrame
* aPrevFrame
,
121 nsIFrame
* aFrameList
);
123 NS_IMETHOD
RemoveFrame(nsIAtom
* aListName
,
124 nsIFrame
* aOldFrame
);
126 virtual nsMargin
GetUsedMargin() const;
127 virtual nsMargin
GetUsedBorder() const;
128 virtual nsMargin
GetUsedPadding() const;
130 NS_IMETHOD
BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
131 const nsRect
& aDirtyRect
,
132 const nsDisplayListSet
& aLists
);
134 /** calls Reflow for all of its child rows.
135 * Rows are all set to the same width and stacked vertically.
136 * <P> rows are not split unless absolutely necessary.
138 * @param aDesiredSize width set to width of rows, height set to
139 * sum of height of rows that fit in aMaxSize.height.
141 * @see nsIFrame::Reflow
143 NS_IMETHOD
Reflow(nsPresContext
* aPresContext
,
144 nsHTMLReflowMetrics
& aDesiredSize
,
145 const nsHTMLReflowState
& aReflowState
,
146 nsReflowStatus
& aStatus
);
148 virtual PRBool
IsFrameOfType(PRUint32 aFlags
) const
150 return nsHTMLContainerFrame::IsFrameOfType(aFlags
&
151 ~nsIFrame::eExcludesIgnorableWhitespace
);
155 * Get the "type" of the frame
157 * @see nsGkAtoms::tableRowGroupFrame
159 virtual nsIAtom
* GetType() const;
161 virtual PRBool
IsContainingBlock() const;
163 nsTableRowFrame
* GetFirstRow();
166 NS_IMETHOD
GetFrameName(nsAString
& aResult
) const;
169 /** return the number of child rows (not necessarily == number of child frames) */
170 PRInt32
GetRowCount();
172 /** return the table-relative row index of the first row in this rowgroup.
173 * if there are no rows, -1 is returned.
175 PRInt32
GetStartRowIndex();
177 /** Adjust the row indices of all rows whose index is >= aRowIndex.
178 * @param aRowIndex - start adjusting with this index
179 * @param aAdjustment - shift the row index by this amount
181 void AdjustRowIndices(PRInt32 aRowIndex
,
182 PRInt32 anAdjustment
);
185 * Used for header and footer row group frames that are repeated when
186 * splitting a table frame.
188 * Performs any table specific initialization
190 * @param aHeaderFooterFrame the original header or footer row group frame
193 nsresult
InitRepeatedFrame(nsPresContext
* aPresContext
,
194 nsTableRowGroupFrame
* aHeaderFooterFrame
);
198 * Get the total height of all the row rects
200 nscoord
GetHeightBasis(const nsHTMLReflowState
& aReflowState
);
202 nsMargin
* GetBCBorderWidth(nsMargin
& aBorder
);
205 * Gets inner border widths before collapsing with cell borders
206 * Caller must get top border from previous row group or from table
207 * GetContinuousBCBorderWidth will not overwrite aBorder.top
208 * see nsTablePainter about continuous borders
210 void GetContinuousBCBorderWidth(nsMargin
& aBorder
);
212 * Sets full border widths before collapsing with cell borders
213 * @param aForSide - side to set; only right, left, and bottom valid
215 void SetContinuousBCBorderWidth(PRUint8 aForSide
,
216 BCPixelSize aPixelValue
);
218 * Adjust to the effect of visibibility:collapse on the row group and
220 * @return additional shift upward that should be applied to
221 * subsequent rowgroups due to rows and this rowgroup
223 * @param aYTotalOffset the total amount that the rowgroup is shifted up
224 * @param aWidth new width of the rowgroup
226 nscoord
CollapseRowGroupIfNecessary(nscoord aYTotalOffset
,
229 // nsILineIterator methods
231 virtual void DisposeLineIterator() { }
233 // The table row is the equivalent to a line in block layout.
234 // The nsILineIterator assumes that a line resides in a block, this role is
235 // fullfilled by the row group. Rows in table are counted relative to the
236 // table. The row index of row corresponds to the cellmap coordinates. The
237 // line index with respect to a row group can be computed by substracting the
238 // row index of the first row in the row group.
240 /** Get the number of rows in a row group
241 * @return the number of lines in a row group
243 virtual PRInt32
GetNumLines();
245 /** @see nsILineIterator.h GetDirection
246 * @return true if the table is rtl
248 virtual PRBool
GetDirection();
250 /** Return structural information about a line.
251 * @param aLineNumber - the index of the row relative to the row group
252 * If the line-number is invalid then
253 * aFirstFrameOnLine will be nsnull and
254 * aNumFramesOnLine will be zero.
255 * @param aFirstFrameOnLine - the first cell frame that originates in row
256 * with a rowindex that matches a line number
257 * @param aNumFramesOnLine - return the numbers of cells originating in
259 * @param aLineBounds - rect of the row
260 * @param aLineFlags - unused set to 0
262 NS_IMETHOD
GetLine(PRInt32 aLineNumber
,
263 nsIFrame
** aFirstFrameOnLine
,
264 PRInt32
* aNumFramesOnLine
,
266 PRUint32
* aLineFlags
);
268 /** Given a frame that's a child of the rowgroup, find which line its on.
269 * @param aFrame - frame, should be a row
270 * @return row index relative to the row group if this a row
271 * frame. -1 if the frame cannot be found.
273 virtual PRInt32
FindLineContaining(nsIFrame
* aFrame
);
276 * the function is also not called in our tree
278 virtual PRInt32
FindLineAt(nscoord aY
);
280 /** Find the orginating cell frame on a row that is the nearest to the
282 * @param aLineNumber - the index of the row relative to the row group
283 * @param aX - X coordinate in twips relative to the
284 * origin of the row group
285 * @param aFrameFound - pointer to the cellframe
286 * @param aXIsBeforeFirstFrame - the point is before the first originating
288 * @param aXIsAfterLastFrame - the point is after the last originating
291 NS_IMETHOD
FindFrameAt(PRInt32 aLineNumber
,
293 nsIFrame
** aFrameFound
,
294 PRBool
* aXIsBeforeFirstFrame
,
295 PRBool
* aXIsAfterLastFrame
);
298 /** Check whether visual and logical order of cell frames within a line are
299 * identical. As the layout will reorder them this is always the case
300 * @param aLine - the index of the row relative to the table
301 * @param aIsReordered - returns false
302 * @param aFirstVisual - if the table is rtl first originating cell frame
303 * @param aLastVisual - if the table is rtl last originating cell frame
306 NS_IMETHOD
CheckLineOrder(PRInt32 aLine
,
307 PRBool
*aIsReordered
,
308 nsIFrame
**aFirstVisual
,
309 nsIFrame
**aLastVisual
);
312 /** Find the next originating cell frame that originates in the row.
313 * @param aFrame - cell frame to start with, will return the next cell
314 * originating in a row
315 * @param aLineNumber - the index of the row relative to the table
317 NS_IMETHOD
GetNextSiblingOnLine(nsIFrame
*& aFrame
, PRInt32 aLineNumber
);
319 // row cursor methods to speed up searching for the row(s)
320 // containing a point. The basic idea is that we set the cursor
321 // property if the rows' y and yMosts are non-decreasing (considering only
322 // rows with nonempty overflowAreas --- empty overflowAreas never participate
323 // in event handling or painting), and the rowgroup has sufficient number of
324 // rows. The cursor property points to a "recently used" row. If we get a
325 // series of requests that work on rows "near" the cursor, then we can find
326 // those nearby rows quickly by starting our search at the cursor.
327 // This code is based on the line cursor code in nsBlockFrame. It's more general
328 // though, and could be extracted and used elsewhere.
329 struct FrameCursorData
{
330 nsTArray
<nsIFrame
*> mFrames
;
331 PRUint32 mCursorIndex
;
332 nscoord mOverflowAbove
;
333 nscoord mOverflowBelow
;
336 : mFrames(MIN_ROWS_NEEDING_CURSOR
), mCursorIndex(0), mOverflowAbove(0),
339 PRBool
AppendFrame(nsIFrame
* aFrame
);
341 void FinishBuildingCursor() {
346 // Clear out row cursor because we're disturbing the rows (e.g., Reflow)
347 void ClearRowCursor();
350 * Get the first row that might contain y-coord 'aY', or nsnull if you must search
352 * The actual row returned might not contain 'aY', but if not, it is guaranteed
353 * to be before any row which does contain 'aY'.
354 * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y.
355 * To find all rows that intersect the vertical interval aY/aYMost, call
356 * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all
357 * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost.
358 * That row and all subsequent rows cannot intersect the interval.
360 nsIFrame
* GetFirstRowContaining(nscoord aY
, nscoord
* aOverflowAbove
);
363 * Set up the row cursor. After this, call AppendFrame for every
364 * child frame in sibling order. Ensure that the child frame y and YMost values
365 * form non-decreasing sequences (should always be true for table rows);
366 * if this is violated, call ClearRowCursor(). If we return nsnull, then we
367 * decided not to use a cursor or we already have one set up.
369 FrameCursorData
* SetupRowCursor();
371 PRBool
IsScrolled() {
372 // Note that if mOverflowY is CLIP, so is mOverflowX, and we need to clip the background
373 // as if the rowgroup is scrollable.
374 return GetStyleContext()->GetPseudoType() == nsCSSAnonBoxes::scrolledContent
||
375 GetStyleDisplay()->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
;
378 virtual nsILineIterator
* GetLineIterator() { return this; }
381 nsTableRowGroupFrame(nsStyleContext
* aContext
);
383 void InitChildReflowState(nsPresContext
& aPresContext
,
384 PRBool aBorderCollapse
,
385 nsHTMLReflowState
& aReflowState
);
387 /** implement abstract method on nsHTMLContainerFrame */
388 virtual PRIntn
GetSkipSides() const;
390 void PlaceChild(nsPresContext
* aPresContext
,
391 nsRowGroupReflowState
& aReflowState
,
393 nsHTMLReflowMetrics
& aDesiredSize
,
394 const nsRect
& aOriginalKidRect
,
395 const nsRect
& aOriginalKidOverflowRect
);
397 void CalculateRowHeights(nsPresContext
* aPresContext
,
398 nsHTMLReflowMetrics
& aDesiredSize
,
399 const nsHTMLReflowState
& aReflowState
);
401 void DidResizeRows(nsHTMLReflowMetrics
& aDesiredSize
);
403 void SlideChild(nsRowGroupReflowState
& aReflowState
,
404 nsIFrame
* aKidFrame
);
407 * Reflow the frames we've already created
409 * @param aPresContext presentation context to use
410 * @param aReflowState current inline state
411 * @return true if we successfully reflowed all the mapped children and false
412 * otherwise, e.g. we pushed children to the next in flow
414 NS_METHOD
ReflowChildren(nsPresContext
* aPresContext
,
415 nsHTMLReflowMetrics
& aDesiredSize
,
416 nsRowGroupReflowState
& aReflowState
,
417 nsReflowStatus
& aStatus
,
418 PRBool
* aPageBreakBeforeEnd
= nsnull
);
420 nsresult
SplitRowGroup(nsPresContext
* aPresContext
,
421 nsHTMLReflowMetrics
& aDesiredSize
,
422 const nsHTMLReflowState
& aReflowState
,
423 nsTableFrame
* aTableFrame
,
424 nsReflowStatus
& aStatus
);
426 void SplitSpanningCells(nsPresContext
& aPresContext
,
427 const nsHTMLReflowState
& aReflowState
,
428 nsTableFrame
& aTableFrame
,
429 nsTableRowFrame
& aFirstRow
,
430 nsTableRowFrame
& aLastRow
,
431 PRBool aFirstRowIsTopOfPage
,
432 nscoord aSpanningRowBottom
,
433 nsTableRowFrame
*& aContRowFrame
,
434 nsTableRowFrame
*& aFirstTruncatedRow
,
435 nscoord
& aDesiredHeight
);
437 void CreateContinuingRowFrame(nsPresContext
& aPresContext
,
439 nsIFrame
** aContRowFrame
);
441 PRBool
IsSimpleRowFrame(nsTableFrame
* aTableFrame
,
444 void GetNextRowSibling(nsIFrame
** aRowFrame
);
446 void UndoContinuedRow(nsPresContext
* aPresContext
,
447 nsTableRowFrame
* aRow
);
450 // border widths in pixels in the collapsing border model
451 BCPixelSize mRightContBorderWidth
;
452 BCPixelSize mBottomContBorderWidth
;
453 BCPixelSize mLeftContBorderWidth
;
456 virtual nsIFrame
* GetFirstFrame() { return mFrames
.FirstChild(); }
457 virtual nsIFrame
* GetLastFrame() { return mFrames
.LastChild(); }
458 virtual void GetNextFrame(nsIFrame
* aFrame
,
459 nsIFrame
** aResult
) { *aResult
= aFrame
->GetNextSibling(); }
460 PRBool
IsRepeatable() const;
461 void SetRepeatable(PRBool aRepeatable
);
462 PRBool
HasStyleHeight() const;
463 void SetHasStyleHeight(PRBool aValue
);
467 inline PRBool
nsTableRowGroupFrame::IsRepeatable() const
469 return (mState
& NS_ROWGROUP_REPEATABLE
) == NS_ROWGROUP_REPEATABLE
;
472 inline void nsTableRowGroupFrame::SetRepeatable(PRBool aRepeatable
)
475 mState
|= NS_ROWGROUP_REPEATABLE
;
477 mState
&= ~NS_ROWGROUP_REPEATABLE
;
481 inline PRBool
nsTableRowGroupFrame::HasStyleHeight() const
483 return (mState
& NS_ROWGROUP_HAS_STYLE_HEIGHT
) == NS_ROWGROUP_HAS_STYLE_HEIGHT
;
486 inline void nsTableRowGroupFrame::SetHasStyleHeight(PRBool aValue
)
489 mState
|= NS_ROWGROUP_HAS_STYLE_HEIGHT
;
491 mState
&= ~NS_ROWGROUP_HAS_STYLE_HEIGHT
;
496 nsTableRowGroupFrame::GetContinuousBCBorderWidth(nsMargin
& aBorder
)
498 PRInt32 aPixelsToTwips
= nsPresContext::AppUnitsPerCSSPixel();
499 aBorder
.right
= BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips
,
500 mRightContBorderWidth
);
501 aBorder
.bottom
= BC_BORDER_TOP_HALF_COORD(aPixelsToTwips
,
502 mBottomContBorderWidth
);
503 aBorder
.left
= BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips
,
504 mLeftContBorderWidth
);