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