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
4 : *
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/
9 : *
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.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
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.
21 : *
22 : * Contributor(s):
23 : *
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.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 : #ifndef nsTableFrame_h__
38 : #define nsTableFrame_h__
39 :
40 : #include "nscore.h"
41 : #include "nsContainerFrame.h"
42 : #include "nsStyleCoord.h"
43 : #include "nsStyleConsts.h"
44 : #include "nsITableLayout.h"
45 : #include "nsTableColFrame.h"
46 : #include "nsTableColGroupFrame.h"
47 : #include "nsCellMap.h"
48 : #include "nsGkAtoms.h"
49 : #include "nsDisplayList.h"
50 :
51 : class nsTableCellFrame;
52 : class nsTableColFrame;
53 : class nsTableRowGroupFrame;
54 : class nsTableRowFrame;
55 : class nsTableColGroupFrame;
56 : class nsITableLayoutStrategy;
57 : class nsStyleContext;
58 :
59 : struct nsTableReflowState;
60 : struct nsStylePosition;
61 : struct BCPropertyData;
62 :
63 0 : static inline bool IS_TABLE_CELL(nsIAtom* frameType) {
64 : return nsGkAtoms::tableCellFrame == frameType ||
65 0 : nsGkAtoms::bcTableCellFrame == frameType;
66 : }
67 :
68 : class nsDisplayTableItem : public nsDisplayItem
69 0 : {
70 : public:
71 0 : nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
72 : nsDisplayItem(aBuilder, aFrame),
73 0 : mPartHasFixedBackground(false) {}
74 :
75 : virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
76 : nsIFrame* aFrame);
77 : // With collapsed borders, parts of the collapsed border can extend outside
78 : // the table part frames, so allow this display element to blow out to our
79 : // overflow rect. This is also useful for row frames that have spanning
80 : // cells extending outside them.
81 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
82 :
83 : void UpdateForFrameBackground(nsIFrame* aFrame);
84 :
85 : private:
86 : bool mPartHasFixedBackground;
87 : };
88 :
89 : class nsAutoPushCurrentTableItem
90 : {
91 : public:
92 0 : nsAutoPushCurrentTableItem() : mBuilder(nsnull) {}
93 :
94 0 : void Push(nsDisplayListBuilder* aBuilder, nsDisplayTableItem* aPushItem)
95 : {
96 0 : mBuilder = aBuilder;
97 0 : mOldCurrentItem = aBuilder->GetCurrentTableItem();
98 0 : aBuilder->SetCurrentTableItem(aPushItem);
99 : #ifdef DEBUG
100 0 : mPushedItem = aPushItem;
101 : #endif
102 0 : }
103 0 : ~nsAutoPushCurrentTableItem() {
104 0 : if (!mBuilder)
105 0 : return;
106 : #ifdef DEBUG
107 0 : NS_ASSERTION(mBuilder->GetCurrentTableItem() == mPushedItem,
108 : "Someone messed with the current table item behind our back!");
109 : #endif
110 0 : mBuilder->SetCurrentTableItem(mOldCurrentItem);
111 0 : }
112 :
113 : private:
114 : nsDisplayListBuilder* mBuilder;
115 : nsDisplayTableItem* mOldCurrentItem;
116 : #ifdef DEBUG
117 : nsDisplayTableItem* mPushedItem;
118 : #endif
119 : };
120 :
121 : /* ============================================================================ */
122 :
123 : /**
124 : * nsTableFrame maps the inner portion of a table (everything except captions.)
125 : * Used as a pseudo-frame within nsTableOuterFrame, it may also be used
126 : * stand-alone as the top-level frame.
127 : *
128 : * The principal child list contains row group frames. There is also an
129 : * additional child list, kColGroupList, which contains the col group frames.
130 : */
131 : class nsTableFrame : public nsContainerFrame, public nsITableLayout
132 : {
133 : public:
134 : NS_DECL_QUERYFRAME
135 : NS_DECL_FRAMEARENA_HELPERS
136 :
137 : /** nsTableOuterFrame has intimate knowledge of the inner table frame */
138 : friend class nsTableOuterFrame;
139 :
140 : /** instantiate a new instance of nsTableRowFrame.
141 : * @param aPresShell the pres shell for this frame
142 : *
143 : * @return the frame that was created
144 : */
145 : friend nsIFrame* NS_NewTableFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
146 :
147 : /** sets defaults for table-specific style.
148 : * @see nsIFrame::Init
149 : */
150 : NS_IMETHOD Init(nsIContent* aContent,
151 : nsIFrame* aParent,
152 : nsIFrame* aPrevInFlow);
153 :
154 : static float GetTwipsToPixels(nsPresContext* aPresContext);
155 :
156 : // Return true if aParentReflowState.frame or any of its ancestors within
157 : // the containing table have non-auto height. (e.g. pct or fixed height)
158 : static bool AncestorsHaveStyleHeight(const nsHTMLReflowState& aParentReflowState);
159 :
160 : // See if a special height reflow will occur due to having a pct height when
161 : // the pct height basis may not yet be valid.
162 : static void CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState);
163 :
164 : // Notify the frame and its ancestors (up to the containing table) that a special
165 : // height reflow will occur.
166 : static void RequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState);
167 :
168 : static void RePositionViews(nsIFrame* aFrame);
169 :
170 : static bool PageBreakAfter(nsIFrame* aSourceFrame,
171 : nsIFrame* aNextFrame);
172 :
173 : nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const;
174 : /*
175 : * Notification that aAttribute has changed for content inside a table (cell, row, etc)
176 : */
177 : void AttributeChangedFor(nsIFrame* aFrame,
178 : nsIContent* aContent,
179 : nsIAtom* aAttribute);
180 :
181 : /** @see nsIFrame::DestroyFrom */
182 : virtual void DestroyFrom(nsIFrame* aDestructRoot);
183 :
184 : /** @see nsIFrame::DidSetStyleContext */
185 : virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
186 :
187 : NS_IMETHOD AppendFrames(ChildListID aListID,
188 : nsFrameList& aFrameList);
189 : NS_IMETHOD InsertFrames(ChildListID aListID,
190 : nsIFrame* aPrevFrame,
191 : nsFrameList& aFrameList);
192 : NS_IMETHOD RemoveFrame(ChildListID aListID,
193 : nsIFrame* aOldFrame);
194 :
195 : virtual nsMargin GetUsedBorder() const;
196 : virtual nsMargin GetUsedPadding() const;
197 : virtual nsMargin GetUsedMargin() const;
198 :
199 : // Get the offset from the border box to the area where the row groups fit
200 : nsMargin GetChildAreaOffset(const nsHTMLReflowState* aReflowState) const;
201 :
202 : /** helper method to find the table parent of any table frame object */
203 : static nsTableFrame* GetTableFrame(nsIFrame* aSourceFrame);
204 :
205 : typedef nsresult (* DisplayGenericTablePartTraversal)
206 : (nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
207 : const nsRect& aDirtyRect, const nsDisplayListSet& aLists);
208 : static nsresult GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
209 : const nsRect& aDirtyRect, const nsDisplayListSet& aLists);
210 :
211 : /**
212 : * Helper method to handle display common to table frames, rowgroup frames
213 : * and row frames. It creates a background display item for handling events
214 : * if necessary, an outline display item if necessary, and displays
215 : * all the the frame's children.
216 : * @param aDisplayItem the display item created for this part, or null
217 : * if this part's border/background painting is delegated to an ancestor
218 : * @param aTraversal a function that gets called to traverse the table
219 : * part's child frames and add their display list items to a
220 : * display list set.
221 : */
222 : static nsresult DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
223 : nsFrame* aFrame,
224 : const nsRect& aDirtyRect,
225 : const nsDisplayListSet& aLists,
226 : nsDisplayTableItem* aDisplayItem,
227 : DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
228 :
229 : // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
230 : // of type aChildType.
231 : static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
232 : nsIFrame* aPriorChildFrame,
233 : nsIAtom* aChildType);
234 : bool IsAutoHeight();
235 :
236 : /** @return true if aDisplayType represents a rowgroup of any sort
237 : * (header, footer, or body)
238 : */
239 : bool IsRowGroup(PRInt32 aDisplayType) const;
240 :
241 : /** Initialize the table frame with a set of children.
242 : * @see nsIFrame::SetInitialChildList
243 : */
244 : NS_IMETHOD SetInitialChildList(ChildListID aListID,
245 : nsFrameList& aChildList);
246 :
247 : virtual const nsFrameList& GetChildList(ChildListID aListID) const;
248 : virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
249 :
250 : NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
251 : const nsRect& aDirtyRect,
252 : const nsDisplayListSet& aLists);
253 :
254 : /**
255 : * Paint the background of the table and its parts (column groups,
256 : * columns, row groups, rows, and cells), and the table border, and all
257 : * internal borders if border-collapse is on.
258 : */
259 : void PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
260 : const nsRect& aDirtyRect,
261 : nsPoint aPt, PRUint32 aBGPaintFlags);
262 :
263 : /** Get the outer half (i.e., the part outside the height and width of
264 : * the table) of the largest segment (?) of border-collapsed border on
265 : * the table on each side, or 0 for non border-collapsed tables.
266 : */
267 : nsMargin GetOuterBCBorder() const;
268 :
269 : /** Same as above, but only if it's included from the border-box width
270 : * of the table.
271 : */
272 : nsMargin GetIncludedOuterBCBorder() const;
273 :
274 : /** Same as above, but only if it's excluded from the border-box width
275 : * of the table. This is the area that leaks out into the margin
276 : * (or potentially past it, if there is no margin).
277 : */
278 : nsMargin GetExcludedOuterBCBorder() const;
279 :
280 : /**
281 : * In quirks mode, the size of the table background is reduced
282 : * by the outer BC border. Compute the reduction needed.
283 : */
284 : nsMargin GetDeflationForBackground(nsPresContext* aPresContext) const;
285 :
286 : /** Get width of table + colgroup + col collapse: elements that
287 : * continue along the length of the whole left side.
288 : * see nsTablePainter about continuous borders
289 : */
290 : nscoord GetContinuousLeftBCBorderWidth() const;
291 : void SetContinuousLeftBCBorderWidth(nscoord aValue);
292 :
293 : friend class nsDelayedCalcBCBorders;
294 :
295 : void AddBCDamageArea(const nsIntRect& aValue);
296 : bool BCRecalcNeeded(nsStyleContext* aOldStyleContext,
297 : nsStyleContext* aNewStyleContext);
298 : void PaintBCBorders(nsRenderingContext& aRenderingContext,
299 : const nsRect& aDirtyRect);
300 :
301 : virtual void MarkIntrinsicWidthsDirty();
302 : // For border-collapse tables, the caller must not add padding and
303 : // border to the results of these functions.
304 : virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
305 : virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
306 : virtual IntrinsicWidthOffsetData
307 : IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext);
308 :
309 : virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
310 : nsSize aCBSize, nscoord aAvailableWidth,
311 : nsSize aMargin, nsSize aBorder, nsSize aPadding,
312 : bool aShrinkWrap);
313 : virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext,
314 : nsSize aCBSize, nscoord aAvailableWidth,
315 : nsSize aMargin, nsSize aBorder,
316 : nsSize aPadding, bool aShrinkWrap);
317 : /**
318 : * A copy of nsFrame::ShrinkWidthToFit that calls a different
319 : * GetPrefWidth, since tables have two different ones.
320 : */
321 : nscoord TableShrinkWidthToFit(nsRenderingContext *aRenderingContext,
322 : nscoord aWidthInCB);
323 :
324 : // XXXldb REWRITE THIS COMMENT!
325 : /** inner tables are reflowed in two steps.
326 : * <pre>
327 : * if mFirstPassValid is false, this is our first time through since content was last changed
328 : * set pass to 1
329 : * do pass 1
330 : * get min/max info for all cells in an infinite space
331 : * do column balancing
332 : * set mFirstPassValid to true
333 : * do pass 2
334 : * use column widths to Reflow cells
335 : * </pre>
336 : *
337 : * @see nsIFrame::Reflow
338 : */
339 : NS_IMETHOD Reflow(nsPresContext* aPresContext,
340 : nsHTMLReflowMetrics& aDesiredSize,
341 : const nsHTMLReflowState& aReflowState,
342 : nsReflowStatus& aStatus);
343 :
344 : nsresult ReflowTable(nsHTMLReflowMetrics& aDesiredSize,
345 : const nsHTMLReflowState& aReflowState,
346 : nscoord aAvailHeight,
347 : nsIFrame*& aLastChildReflowed,
348 : nsReflowStatus& aStatus);
349 :
350 : nsFrameList& GetColGroups();
351 :
352 : virtual nsIFrame* GetParentStyleContextFrame() const;
353 :
354 : /**
355 : * Get the "type" of the frame
356 : *
357 : * @see nsGkAtoms::tableFrame
358 : */
359 : virtual nsIAtom* GetType() const;
360 :
361 : #ifdef DEBUG
362 : /** @see nsIFrame::GetFrameName */
363 : NS_IMETHOD GetFrameName(nsAString& aResult) const;
364 : #endif
365 :
366 : /** return the width of the column at aColIndex */
367 : virtual PRInt32 GetColumnWidth(PRInt32 aColIndex);
368 :
369 : /** helper to get the cell spacing X style value */
370 : virtual nscoord GetCellSpacingX();
371 :
372 : /** helper to get the cell spacing Y style value */
373 : virtual nscoord GetCellSpacingY();
374 :
375 : virtual nscoord GetBaseline() const;
376 : /** return the row span of a cell, taking into account row span magic at the bottom
377 : * of a table. The row span equals the number of rows spanned by aCell starting at
378 : * aStartRowIndex, and can be smaller if aStartRowIndex is greater than the row
379 : * index in which aCell originates.
380 : *
381 : * @param aStartRowIndex the cell
382 : * @param aCell the cell
383 : *
384 : * @return the row span, correcting for row spans that extend beyond the bottom
385 : * of the table.
386 : */
387 : virtual PRInt32 GetEffectiveRowSpan(PRInt32 aStartRowIndex,
388 : const nsTableCellFrame& aCell) const;
389 : virtual PRInt32 GetEffectiveRowSpan(const nsTableCellFrame& aCell,
390 : nsCellMap* aCellMap = nsnull);
391 :
392 : /** return the col span of a cell, taking into account col span magic at the edge
393 : * of a table.
394 : *
395 : * @param aCell the cell
396 : *
397 : * @return the col span, correcting for col spans that extend beyond the edge
398 : * of the table.
399 : */
400 : virtual PRInt32 GetEffectiveColSpan(const nsTableCellFrame& aCell,
401 : nsCellMap* aCellMap = nsnull) const;
402 :
403 : /** indicate whether the row has more than one cell that either originates
404 : * or is spanned from the rows above
405 : */
406 : bool HasMoreThanOneCell(PRInt32 aRowIndex) const;
407 :
408 : /** return the column frame associated with aColIndex
409 : * returns nsnull if the col frame has not yet been allocated, or if
410 : * aColIndex is out of range
411 : */
412 : nsTableColFrame* GetColFrame(PRInt32 aColIndex) const;
413 :
414 : /** Insert a col frame reference into the colframe cache and adapt the cellmap
415 : * @param aColFrame - the column frame
416 : * @param aColIndex - index where the column should be inserted into the
417 : * colframe cache
418 : */
419 : void InsertCol(nsTableColFrame& aColFrame,
420 : PRInt32 aColIndex);
421 :
422 : nsTableColGroupFrame* CreateAnonymousColGroupFrame(nsTableColGroupType aType);
423 :
424 : PRInt32 DestroyAnonymousColFrames(PRInt32 aNumFrames);
425 :
426 : // Append aNumColsToAdd anonymous col frames of type eColAnonymousCell to our
427 : // last eColGroupAnonymousCell colgroup. If we have no such colgroup, then
428 : // create one.
429 : void AppendAnonymousColFrames(PRInt32 aNumColsToAdd);
430 :
431 : // Append aNumColsToAdd anonymous col frames of type aColType to
432 : // aColGroupFrame. If aAddToTable is true, also call AddColsToTable on the
433 : // new cols.
434 : void AppendAnonymousColFrames(nsTableColGroupFrame* aColGroupFrame,
435 : PRInt32 aNumColsToAdd,
436 : nsTableColType aColType,
437 : bool aAddToTable);
438 :
439 : void MatchCellMapToColCache(nsTableCellMap* aCellMap);
440 : /** empty the column frame cache */
441 : void ClearColCache();
442 :
443 : void DidResizeColumns();
444 :
445 : virtual void AppendCell(nsTableCellFrame& aCellFrame,
446 : PRInt32 aRowIndex);
447 :
448 : virtual void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
449 : PRInt32 aRowIndex,
450 : PRInt32 aColIndexBefore);
451 :
452 : virtual void RemoveCell(nsTableCellFrame* aCellFrame,
453 : PRInt32 aRowIndex);
454 :
455 : void AppendRows(nsTableRowGroupFrame* aRowGroupFrame,
456 : PRInt32 aRowIndex,
457 : nsTArray<nsTableRowFrame*>& aRowFrames);
458 :
459 : PRInt32 InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
460 : nsTArray<nsTableRowFrame*>& aFrames,
461 : PRInt32 aRowIndex,
462 : bool aConsiderSpans);
463 :
464 : virtual void RemoveRows(nsTableRowFrame& aFirstRowFrame,
465 : PRInt32 aNumRowsToRemove,
466 : bool aConsiderSpans);
467 :
468 : /** Insert multiple rowgroups into the table cellmap handling
469 : * @param aRowGroups - iterator that iterates over the rowgroups to insert
470 : */
471 : void InsertRowGroups(const nsFrameList::Slice& aRowGroups);
472 :
473 : void InsertColGroups(PRInt32 aStartColIndex,
474 : const nsFrameList::Slice& aColgroups);
475 :
476 : virtual void RemoveCol(nsTableColGroupFrame* aColGroupFrame,
477 : PRInt32 aColIndex,
478 : bool aRemoveFromCache,
479 : bool aRemoveFromCellMap);
480 :
481 : NS_IMETHOD GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex);
482 : NS_IMETHOD GetRowAndColumnByIndex(PRInt32 aIndex, PRInt32 *aRow, PRInt32 *aColumn);
483 :
484 : bool ColumnHasCellSpacingBefore(PRInt32 aColIndex) const;
485 :
486 : bool HasPctCol() const;
487 : void SetHasPctCol(bool aValue);
488 :
489 : bool HasCellSpanningPctCol() const;
490 : void SetHasCellSpanningPctCol(bool aValue);
491 :
492 : /**
493 : * To be called on a frame by its parent after setting its size/position and
494 : * calling DidReflow (possibly via FinishReflowChild()). This can also be
495 : * used for child frames which are not being reflowed but did have their size
496 : * or position changed.
497 : *
498 : * @param aFrame The frame to invalidate
499 : * @param aOrigRect The original rect of aFrame (before the change).
500 : * @param aOrigVisualOverflow The original overflow rect of aFrame.
501 : * @param aIsFirstReflow True if the size/position change is due to the
502 : * first reflow of aFrame.
503 : */
504 : static void InvalidateFrame(nsIFrame* aFrame,
505 : const nsRect& aOrigRect,
506 : const nsRect& aOrigVisualOverflow,
507 : bool aIsFirstReflow);
508 :
509 : virtual bool UpdateOverflow();
510 :
511 : protected:
512 :
513 : /** protected constructor.
514 : * @see NewFrame
515 : */
516 : nsTableFrame(nsStyleContext* aContext);
517 :
518 : /** destructor, responsible for mColumnLayoutData */
519 : virtual ~nsTableFrame();
520 :
521 : void InitChildReflowState(nsHTMLReflowState& aReflowState);
522 :
523 : /** implement abstract method on nsContainerFrame */
524 : virtual PRIntn GetSkipSides() const;
525 :
526 : public:
527 : bool IsRowInserted() const;
528 : void SetRowInserted(bool aValue);
529 :
530 : protected:
531 :
532 : // A helper function to reflow a header or footer with unconstrained height
533 : // to see if it should be made repeatable and also to determine its desired
534 : // height.
535 : nsresult SetupHeaderFooterChild(const nsTableReflowState& aReflowState,
536 : nsTableRowGroupFrame* aFrame,
537 : nscoord* aDesiredHeight);
538 :
539 : nsresult ReflowChildren(nsTableReflowState& aReflowState,
540 : nsReflowStatus& aStatus,
541 : nsIFrame*& aLastChildReflowed,
542 : nsOverflowAreas& aOverflowAreas);
543 :
544 : // This calls the col group and column reflow methods, which do two things:
545 : // (1) set all the dimensions to 0
546 : // (2) notify the table about colgroups or columns with hidden visibility
547 : void ReflowColGroups(nsRenderingContext* aRenderingContext);
548 :
549 : /** return the width of the table taking into account visibility collapse
550 : * on columns and colgroups
551 : * @param aBorderPadding the border and padding of the table
552 : */
553 : nscoord GetCollapsedWidth(nsMargin aBorderPadding);
554 :
555 :
556 : /** Adjust the table for visibility.collapse set on rowgroups, rows,
557 : * colgroups and cols
558 : * @param aDesiredSize the metrics of the table
559 : * @param aBorderPadding the border and padding of the table
560 : */
561 : void AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize,
562 : nsMargin aBorderPadding);
563 :
564 0 : nsITableLayoutStrategy* LayoutStrategy() const {
565 0 : return static_cast<nsTableFrame*>(GetFirstInFlow())->
566 0 : mTableLayoutStrategy;
567 : }
568 :
569 : private:
570 : /* Handle a row that got inserted during reflow. aNewHeight is the
571 : new height of the table after reflow. */
572 : void ProcessRowInserted(nscoord aNewHeight);
573 :
574 : // WIDTH AND HEIGHT CALCULATION
575 :
576 : public:
577 :
578 : // calculate the computed height of aFrame including its border and padding given
579 : // its reflow state.
580 : nscoord CalcBorderBoxHeight(const nsHTMLReflowState& aReflowState);
581 :
582 : protected:
583 :
584 : // update the desired height of this table taking into account the current
585 : // reflow state, the table attributes and the content driven rowgroup heights
586 : // this function can change the overflow area
587 : void CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize);
588 :
589 : // The following is a helper for CalcDesiredHeight
590 :
591 : void DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
592 : nscoord aAmount);
593 :
594 : void PlaceChild(nsTableReflowState& aReflowState,
595 : nsIFrame* aKidFrame,
596 : nsHTMLReflowMetrics& aKidDesiredSize,
597 : const nsRect& aOriginalKidRect,
598 : const nsRect& aOriginalKidVisualOverflow);
599 : void PlaceRepeatedFooter(nsTableReflowState& aReflowState,
600 : nsTableRowGroupFrame *aTfoot,
601 : nscoord aFooterHeight);
602 :
603 : nsIFrame* GetFirstBodyRowGroupFrame();
604 : public:
605 : typedef nsAutoTArray<nsTableRowGroupFrame*, 8> RowGroupArray;
606 : /**
607 : * Push all our child frames from the aRowGroups array, in order, starting
608 : * from the frame at aPushFrom to the end of the array. The frames are put on
609 : * our overflow list or moved directly to our next-in-flow if one exists.
610 : */
611 : protected:
612 : void PushChildren(const RowGroupArray& aRowGroups, PRInt32 aPushFrom);
613 :
614 : public:
615 : // put the children frames in the display order (e.g. thead before tbodies
616 : // before tfoot). This will handle calling GetRowGroupFrame() on the
617 : // children, and not append nulls, so the array is guaranteed to contain
618 : // nsTableRowGroupFrames. If there are multiple theads or tfoots, all but
619 : // the first one are treated as tbodies instead.
620 :
621 : void OrderRowGroups(RowGroupArray& aChildren,
622 : nsTableRowGroupFrame** aHead = nsnull,
623 : nsTableRowGroupFrame** aFoot = nsnull) const;
624 :
625 : // Return the thead, if any
626 : nsTableRowGroupFrame* GetTHead() const;
627 :
628 : // Return the tfoot, if any
629 : nsTableRowGroupFrame* GetTFoot() const;
630 :
631 : // Returns true if there are any cells above the row at
632 : // aRowIndex and spanning into the row at aRowIndex, the number of
633 : // effective columns limits the search up to that column
634 : bool RowIsSpannedInto(PRInt32 aRowIndex, PRInt32 aNumEffCols);
635 :
636 : // Returns true if there is a cell originating in aRowIndex
637 : // which spans into the next row, the number of effective
638 : // columns limits the search up to that column
639 : bool RowHasSpanningCells(PRInt32 aRowIndex, PRInt32 aNumEffCols);
640 :
641 : protected:
642 :
643 : bool HaveReflowedColGroups() const;
644 : void SetHaveReflowedColGroups(bool aValue);
645 :
646 : public:
647 : bool IsBorderCollapse() const;
648 :
649 : bool NeedToCalcBCBorders() const;
650 : void SetNeedToCalcBCBorders(bool aValue);
651 :
652 : bool NeedToCollapse() const;
653 : void SetNeedToCollapse(bool aValue);
654 :
655 : bool HasZeroColSpans() const;
656 : void SetHasZeroColSpans(bool aValue);
657 :
658 : bool NeedColSpanExpansion() const;
659 : void SetNeedColSpanExpansion(bool aValue);
660 :
661 : /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame
662 : * state bit, which implies that all descendants are dirty. The
663 : * GeometryDirty still implies that all the parts of the table are
664 : * dirty, but resizing optimizations should still apply to the
665 : * contents of the individual cells.
666 : */
667 0 : void SetGeometryDirty() { mBits.mGeometryDirty = true; }
668 0 : void ClearGeometryDirty() { mBits.mGeometryDirty = false; }
669 0 : bool IsGeometryDirty() const { return mBits.mGeometryDirty; }
670 :
671 : /** Get the cell map for this table frame. It is not always mCellMap.
672 : * Only the firstInFlow has a legit cell map
673 : */
674 : virtual nsTableCellMap* GetCellMap() const;
675 :
676 : /** Iterate over the row groups and adjust the row indices of all rows
677 : * whose index is >= aRowIndex.
678 : * @param aRowIndex - start adjusting with this index
679 : * @param aAdjustment - shift the row index by this amount
680 : */
681 : void AdjustRowIndices(PRInt32 aRowIndex,
682 : PRInt32 aAdjustment);
683 :
684 : /** Reset the rowindices of all rows as they might have changed due to
685 : * rowgroup reordering, exclude new row group frames that show in the
686 : * reordering but are not yet inserted into the cellmap
687 : * @param aRowGroupsToExclude - an iterator that will produce the row groups
688 : * to exclude.
689 : */
690 : void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude);
691 :
692 : nsTArray<nsTableColFrame*>& GetColCache();
693 :
694 :
695 : protected:
696 :
697 : void SetBorderCollapse(bool aValue);
698 :
699 : BCPropertyData* GetBCProperty(bool aCreateIfNecessary = false) const;
700 : void SetFullBCDamageArea();
701 : void CalcBCBorders();
702 :
703 : void ExpandBCDamageArea(nsIntRect& aRect) const;
704 :
705 : void SetColumnDimensions(nscoord aHeight,
706 : const nsMargin& aReflowState);
707 :
708 : PRInt32 CollectRows(nsIFrame* aFrame,
709 : nsTArray<nsTableRowFrame*>& aCollection);
710 :
711 : public: /* ----- Cell Map public methods ----- */
712 :
713 : PRInt32 GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame);
714 :
715 : /** returns the number of rows in this table.
716 : */
717 0 : PRInt32 GetRowCount () const
718 : {
719 0 : return GetCellMap()->GetRowCount();
720 : }
721 :
722 : /** returns the number of columns in this table after redundant columns have been removed
723 : */
724 : PRInt32 GetEffectiveColCount() const;
725 :
726 : /* return the col count including dead cols */
727 0 : PRInt32 GetColCount () const
728 : {
729 0 : return GetCellMap()->GetColCount();
730 : }
731 :
732 : // return the last col index which isn't of type eColAnonymousCell
733 : PRInt32 GetIndexOfLastRealCol();
734 :
735 : /** returns true if table-layout:auto */
736 : virtual bool IsAutoLayout();
737 :
738 : /*---------------- nsITableLayout methods ------------------------*/
739 :
740 : /** Get the cell and associated data for a table cell from the frame's cellmap */
741 : NS_IMETHOD GetCellDataAt(PRInt32 aRowIndex, PRInt32 aColIndex,
742 : nsIDOMElement* &aCell, //out params
743 : PRInt32& aStartRowIndex, PRInt32& aStartColIndex,
744 : PRInt32& aRowSpan, PRInt32& aColSpan,
745 : PRInt32& aActualRowSpan, PRInt32& aActualColSpan,
746 : bool& aIsSelected);
747 :
748 : /** Get the number of rows and column for a table from the frame's cellmap
749 : * Some rows may not have enough cells (the number returned is the maximum possible),
750 : * which displays as a ragged-right edge table
751 : */
752 : NS_IMETHOD GetTableSize(PRInt32& aRowCount, PRInt32& aColCount);
753 :
754 : /*------------end of nsITableLayout methods -----------------------*/
755 :
756 : public:
757 :
758 : #ifdef DEBUG
759 : void Dump(bool aDumpRows,
760 : bool aDumpCols,
761 : bool aDumpCellMap);
762 : #endif
763 :
764 : protected:
765 : #ifdef DEBUG
766 : void DumpRowGroup(nsIFrame* aChildFrame);
767 : #endif
768 : // DATA MEMBERS
769 : nsAutoTArray<nsTableColFrame*, 8> mColFrames;
770 :
771 : struct TableBits {
772 : PRUint32 mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow
773 : PRUint32 mHasPctCol:1; // does any cell or col have a pct width
774 : PRUint32 mCellSpansPctCol:1; // does any cell span a col with a pct width (or containing a cell with a pct width)
775 : PRUint32 mIsBorderCollapse:1; // border collapsing model vs. separate model
776 : PRUint32 mRowInserted:1;
777 : PRUint32 mNeedToCalcBCBorders:1;
778 : PRUint32 mGeometryDirty:1;
779 : PRUint32 mLeftContBCBorder:8;
780 : PRUint32 mNeedToCollapse:1; // rows, cols that have visibility:collapse need to be collapsed
781 : PRUint32 mHasZeroColSpans:1;
782 : PRUint32 mNeedColSpanExpansion:1;
783 : PRUint32 mResizedColumns:1; // have we resized columns since last reflow?
784 : } mBits;
785 :
786 : nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
787 : nsITableLayoutStrategy* mTableLayoutStrategy;// the layout strategy for this frame
788 : nsFrameList mColGroups; // the list of colgroup frames
789 : };
790 :
791 :
792 0 : inline bool nsTableFrame::IsRowGroup(PRInt32 aDisplayType) const
793 : {
794 : return bool((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == aDisplayType) ||
795 : (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == aDisplayType) ||
796 0 : (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == aDisplayType));
797 : }
798 :
799 0 : inline void nsTableFrame::SetHaveReflowedColGroups(bool aValue)
800 : {
801 0 : mBits.mHaveReflowedColGroups = aValue;
802 0 : }
803 :
804 0 : inline bool nsTableFrame::HaveReflowedColGroups() const
805 : {
806 0 : return (bool)mBits.mHaveReflowedColGroups;
807 : }
808 :
809 : inline bool nsTableFrame::HasPctCol() const
810 : {
811 : return (bool)mBits.mHasPctCol;
812 : }
813 :
814 : inline void nsTableFrame::SetHasPctCol(bool aValue)
815 : {
816 : mBits.mHasPctCol = (unsigned)aValue;
817 : }
818 :
819 : inline bool nsTableFrame::HasCellSpanningPctCol() const
820 : {
821 : return (bool)mBits.mCellSpansPctCol;
822 : }
823 :
824 : inline void nsTableFrame::SetHasCellSpanningPctCol(bool aValue)
825 : {
826 : mBits.mCellSpansPctCol = (unsigned)aValue;
827 : }
828 :
829 0 : inline bool nsTableFrame::IsRowInserted() const
830 : {
831 0 : return (bool)mBits.mRowInserted;
832 : }
833 :
834 0 : inline void nsTableFrame::SetRowInserted(bool aValue)
835 : {
836 0 : mBits.mRowInserted = (unsigned)aValue;
837 0 : }
838 :
839 0 : inline void nsTableFrame::SetNeedToCollapse(bool aValue)
840 : {
841 0 : static_cast<nsTableFrame*>(GetFirstInFlow())->mBits.mNeedToCollapse = (unsigned)aValue;
842 0 : }
843 :
844 0 : inline bool nsTableFrame::NeedToCollapse() const
845 : {
846 0 : return (bool) static_cast<nsTableFrame*>(GetFirstInFlow())->mBits.mNeedToCollapse;
847 : }
848 :
849 0 : inline void nsTableFrame::SetHasZeroColSpans(bool aValue)
850 : {
851 0 : mBits.mHasZeroColSpans = (unsigned)aValue;
852 0 : }
853 :
854 0 : inline bool nsTableFrame::HasZeroColSpans() const
855 : {
856 0 : return (bool)mBits.mHasZeroColSpans;
857 : }
858 :
859 0 : inline void nsTableFrame::SetNeedColSpanExpansion(bool aValue)
860 : {
861 0 : mBits.mNeedColSpanExpansion = (unsigned)aValue;
862 0 : }
863 :
864 0 : inline bool nsTableFrame::NeedColSpanExpansion() const
865 : {
866 0 : return (bool)mBits.mNeedColSpanExpansion;
867 : }
868 :
869 :
870 0 : inline nsFrameList& nsTableFrame::GetColGroups()
871 : {
872 0 : return static_cast<nsTableFrame*>(GetFirstInFlow())->mColGroups;
873 : }
874 :
875 0 : inline nsTArray<nsTableColFrame*>& nsTableFrame::GetColCache()
876 : {
877 0 : return mColFrames;
878 : }
879 :
880 0 : inline bool nsTableFrame::IsBorderCollapse() const
881 : {
882 0 : return (bool)mBits.mIsBorderCollapse;
883 : }
884 :
885 0 : inline void nsTableFrame::SetBorderCollapse(bool aValue)
886 : {
887 0 : mBits.mIsBorderCollapse = aValue;
888 0 : }
889 :
890 0 : inline bool nsTableFrame::NeedToCalcBCBorders() const
891 : {
892 0 : return (bool)mBits.mNeedToCalcBCBorders;
893 : }
894 :
895 0 : inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue)
896 : {
897 0 : mBits.mNeedToCalcBCBorders = (unsigned)aValue;
898 0 : }
899 :
900 : inline nscoord
901 0 : nsTableFrame::GetContinuousLeftBCBorderWidth() const
902 : {
903 0 : PRInt32 aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
904 0 : return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mBits.mLeftContBCBorder);
905 : }
906 :
907 0 : inline void nsTableFrame::SetContinuousLeftBCBorderWidth(nscoord aValue)
908 : {
909 0 : mBits.mLeftContBCBorder = (unsigned) aValue;
910 0 : }
911 :
912 : class nsTableIterator
913 : {
914 : public:
915 : nsTableIterator(nsIFrame& aSource);
916 : nsTableIterator(nsFrameList& aSource);
917 : nsIFrame* First();
918 : nsIFrame* Next();
919 : bool IsLeftToRight();
920 : PRInt32 Count();
921 :
922 : protected:
923 : void Init(nsIFrame* aFirstChild);
924 : bool mLeftToRight;
925 : nsIFrame* mFirstListChild;
926 : nsIFrame* mFirstChild;
927 : nsIFrame* mCurrentChild;
928 : PRInt32 mCount;
929 : };
930 :
931 : #define ABORT0() \
932 : {NS_ASSERTION(false, "CellIterator program error"); \
933 : return;}
934 :
935 : #define ABORT1(aReturn) \
936 : {NS_ASSERTION(false, "CellIterator program error"); \
937 : return aReturn;}
938 :
939 : #endif
|