|
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 nsCellMap_h__ |
|
6 #define nsCellMap_h__ |
|
7 |
|
8 #include "nscore.h" |
|
9 #include "celldata.h" |
|
10 #include "nsTArray.h" |
|
11 #include "nsTArray.h" |
|
12 #include "nsCOMPtr.h" |
|
13 #include "nsAlgorithm.h" |
|
14 #include "nsAutoPtr.h" |
|
15 #include <algorithm> |
|
16 |
|
17 #undef DEBUG_TABLE_CELLMAP |
|
18 |
|
19 class nsTableColFrame; |
|
20 class nsTableCellFrame; |
|
21 class nsTableRowFrame; |
|
22 class nsTableRowGroupFrame; |
|
23 class nsTableFrame; |
|
24 class nsCellMap; |
|
25 class nsPresContext; |
|
26 class nsCellMapColumnIterator; |
|
27 struct nsIntRect; |
|
28 |
|
29 struct nsColInfo |
|
30 { |
|
31 int32_t mNumCellsOrig; // number of cells originating in the col |
|
32 int32_t mNumCellsSpan; // number of cells spanning into the col via colspans (not rowspans) |
|
33 |
|
34 nsColInfo(); |
|
35 nsColInfo(int32_t aNumCellsOrig, |
|
36 int32_t aNumCellsSpan); |
|
37 }; |
|
38 |
|
39 enum Corner |
|
40 { |
|
41 eTopLeft = 0, |
|
42 eTopRight = 1, |
|
43 eBottomRight = 2, |
|
44 eBottomLeft = 3 |
|
45 }; |
|
46 |
|
47 struct BCInfo |
|
48 { |
|
49 nsTArray<BCData> mRightBorders; |
|
50 nsTArray<BCData> mBottomBorders; |
|
51 BCData mLowerRightCorner; |
|
52 }; |
|
53 |
|
54 class nsTableCellMap |
|
55 { |
|
56 public: |
|
57 nsTableCellMap(nsTableFrame& aTableFrame, |
|
58 bool aBorderCollapse); |
|
59 |
|
60 /** destructor |
|
61 * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED |
|
62 */ |
|
63 ~nsTableCellMap(); |
|
64 |
|
65 void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup); |
|
66 |
|
67 void InsertGroupCellMap(nsTableRowGroupFrame* aNewRowGroup, |
|
68 nsTableRowGroupFrame*& aPrevRowGroup); |
|
69 |
|
70 /** |
|
71 * Get the nsCellMap for the given row group. If aStartHint is non-null, |
|
72 * will start looking with that cellmap and only fall back to starting at the |
|
73 * beginning of the list if that doesn't find us the right nsCellMap. |
|
74 * Otherwise, just start at the beginning. |
|
75 * |
|
76 * aRowGroup must not be null. |
|
77 */ |
|
78 nsCellMap* GetMapFor(const nsTableRowGroupFrame* aRowGroup, |
|
79 nsCellMap* aStartHint) const; |
|
80 |
|
81 /** synchronize the cellmaps with the rowgroups again **/ |
|
82 void Synchronize(nsTableFrame* aTableFrame); |
|
83 |
|
84 nsTableCellFrame* GetCellFrame(int32_t aRowIndex, |
|
85 int32_t aColIndex, |
|
86 CellData& aData, |
|
87 bool aUseRowIfOverlap) const; |
|
88 |
|
89 /** return the CellData for the cell at (aRowIndex, aColIndex) */ |
|
90 CellData* GetDataAt(int32_t aRowIndex, |
|
91 int32_t aColIndex) const; |
|
92 |
|
93 // this function creates a col if needed |
|
94 nsColInfo* GetColInfoAt(int32_t aColIndex); |
|
95 |
|
96 /** append the cellFrame at the end of the row at aRowIndex and return the col index |
|
97 */ |
|
98 CellData* AppendCell(nsTableCellFrame& aCellFrame, |
|
99 int32_t aRowIndex, |
|
100 bool aRebuildIfNecessary, |
|
101 nsIntRect& aDamageArea); |
|
102 |
|
103 void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames, |
|
104 int32_t aRowIndex, |
|
105 int32_t aColIndexBefore, |
|
106 nsIntRect& aDamageArea); |
|
107 |
|
108 void RemoveCell(nsTableCellFrame* aCellFrame, |
|
109 int32_t aRowIndex, |
|
110 nsIntRect& aDamageArea); |
|
111 /** Remove the previously gathered column information */ |
|
112 void ClearCols(); |
|
113 void InsertRows(nsTableRowGroupFrame* aRowGroup, |
|
114 nsTArray<nsTableRowFrame*>& aRows, |
|
115 int32_t aFirstRowIndex, |
|
116 bool aConsiderSpans, |
|
117 nsIntRect& aDamageArea); |
|
118 |
|
119 void RemoveRows(int32_t aFirstRowIndex, |
|
120 int32_t aNumRowsToRemove, |
|
121 bool aConsiderSpans, |
|
122 nsIntRect& aDamageArea); |
|
123 |
|
124 int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const; |
|
125 int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const; |
|
126 |
|
127 /** indicate whether the row has more than one cell that either originates |
|
128 * or is spanned from the rows above |
|
129 */ |
|
130 bool HasMoreThanOneCell(int32_t aRowIndex) const; |
|
131 |
|
132 int32_t GetEffectiveRowSpan(int32_t aRowIndex, |
|
133 int32_t aColIndex) const; |
|
134 int32_t GetEffectiveColSpan(int32_t aRowIndex, |
|
135 int32_t aColIndex) const; |
|
136 |
|
137 /** return the total number of columns in the table represented by this CellMap */ |
|
138 int32_t GetColCount() const; |
|
139 |
|
140 /** return the actual number of rows in the table represented by this CellMap */ |
|
141 int32_t GetRowCount() const; |
|
142 |
|
143 nsTableCellFrame* GetCellInfoAt(int32_t aRowX, |
|
144 int32_t aColX, |
|
145 bool* aOriginates = nullptr, |
|
146 int32_t* aColSpan = nullptr) const; |
|
147 |
|
148 /** |
|
149 * Returns the index at the given row and column coordinates. |
|
150 * |
|
151 * @see nsITableLayout::GetIndexByRowAndColumn() |
|
152 * |
|
153 * @param aRow [in] the row coordinate |
|
154 * @param aColumn [in] the column coordinate |
|
155 * @returns the index for the cell |
|
156 */ |
|
157 int32_t GetIndexByRowAndColumn(int32_t aRow, int32_t aColumn) const; |
|
158 |
|
159 /** |
|
160 * Retrieves the row and column coordinates for the given index. |
|
161 * |
|
162 * @see nsITableLayout::GetRowAndColumnByIndex() |
|
163 * |
|
164 * @param aIndex [in] the index for which coordinates are to be retrieved |
|
165 * @param aRow [out] the row coordinate to be returned |
|
166 * @param aColumn [out] the column coordinate to be returned |
|
167 */ |
|
168 void GetRowAndColumnByIndex(int32_t aIndex, |
|
169 int32_t *aRow, int32_t *aColumn) const; |
|
170 |
|
171 void AddColsAtEnd(uint32_t aNumCols); |
|
172 void RemoveColsAtEnd(); |
|
173 |
|
174 bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols) const; |
|
175 bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols) const; |
|
176 void RebuildConsideringCells(nsCellMap* aCellMap, |
|
177 nsTArray<nsTableCellFrame*>* aCellFrames, |
|
178 int32_t aRowIndex, |
|
179 int32_t aColIndex, |
|
180 bool aInsert, |
|
181 nsIntRect& aDamageArea); |
|
182 |
|
183 protected: |
|
184 /** |
|
185 * Rebuild due to rows being inserted or deleted with cells spanning |
|
186 * into or out of the rows. This function can only handle insertion |
|
187 * or deletion but NOT both. So either aRowsToInsert must be null |
|
188 * or aNumRowsToRemove must be 0. |
|
189 * |
|
190 * // XXXbz are both allowed to happen? That'd be a no-op... |
|
191 */ |
|
192 void RebuildConsideringRows(nsCellMap* aCellMap, |
|
193 int32_t aStartRowIndex, |
|
194 nsTArray<nsTableRowFrame*>* aRowsToInsert, |
|
195 int32_t aNumRowsToRemove, |
|
196 nsIntRect& aDamageArea); |
|
197 |
|
198 public: |
|
199 void ExpandZeroColSpans(); |
|
200 |
|
201 void ResetTopStart(uint8_t aSide, |
|
202 nsCellMap& aCellMap, |
|
203 uint32_t aYPos, |
|
204 uint32_t aXPos, |
|
205 bool aIsLowerRight = false); |
|
206 |
|
207 void SetBCBorderEdge(mozilla::css::Side aEdge, |
|
208 nsCellMap& aCellMap, |
|
209 uint32_t aCellMapStart, |
|
210 uint32_t aYPos, |
|
211 uint32_t aXPos, |
|
212 uint32_t aLength, |
|
213 BCBorderOwner aOwner, |
|
214 nscoord aSize, |
|
215 bool aChanged); |
|
216 |
|
217 void SetBCBorderCorner(::Corner aCorner, |
|
218 nsCellMap& aCellMap, |
|
219 uint32_t aCellMapStart, |
|
220 uint32_t aYPos, |
|
221 uint32_t aXPos, |
|
222 mozilla::css::Side aOwner, |
|
223 nscoord aSubSize, |
|
224 bool aBevel, |
|
225 bool aIsBottomRight = false); |
|
226 |
|
227 /** dump a representation of the cell map to stdout for debugging */ |
|
228 #ifdef DEBUG |
|
229 void Dump(char* aString = nullptr) const; |
|
230 #endif |
|
231 |
|
232 protected: |
|
233 BCData* GetRightMostBorder(int32_t aRowIndex); |
|
234 BCData* GetBottomMostBorder(int32_t aColIndex); |
|
235 |
|
236 friend class nsCellMap; |
|
237 friend class BCMapCellIterator; |
|
238 friend class BCPaintBorderIterator; |
|
239 friend class nsCellMapColumnIterator; |
|
240 |
|
241 /** Insert a row group cellmap after aPrevMap, if aPrefMap is null insert it |
|
242 * at the beginning, the ordering of the cellmap corresponds to the ordering of |
|
243 * rowgroups once OrderRowGroups has been called |
|
244 */ |
|
245 void InsertGroupCellMap(nsCellMap* aPrevMap, |
|
246 nsCellMap& aNewMap); |
|
247 void DeleteRightBottomBorders(); |
|
248 |
|
249 nsTableFrame& mTableFrame; |
|
250 nsAutoTArray<nsColInfo, 8> mCols; |
|
251 nsCellMap* mFirstMap; |
|
252 // border collapsing info |
|
253 BCInfo* mBCInfo; |
|
254 }; |
|
255 |
|
256 /** nsCellMap is a support class for nsTablePart. |
|
257 * It maintains an Rows x Columns grid onto which the cells of the table are mapped. |
|
258 * This makes processing of rowspan and colspan attributes much easier. |
|
259 * Each cell is represented by a CellData object. |
|
260 * |
|
261 * @see CellData |
|
262 * @see nsTableFrame::AddCellToMap |
|
263 * @see nsTableFrame::GrowCellMap |
|
264 * @see nsTableFrame::BuildCellIntoMap |
|
265 * |
|
266 * mRows is an array of rows. Each row is an array of cells. a cell |
|
267 * can be null. |
|
268 */ |
|
269 class nsCellMap |
|
270 { |
|
271 public: |
|
272 /** constructor |
|
273 * @param aRowGroupFrame the row group frame this is a cellmap for |
|
274 * @param aIsBC whether the table is doing border-collapse |
|
275 */ |
|
276 nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, bool aIsBC); |
|
277 |
|
278 /** destructor |
|
279 * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED |
|
280 */ |
|
281 ~nsCellMap(); |
|
282 |
|
283 static void Init(); |
|
284 static void Shutdown(); |
|
285 |
|
286 nsCellMap* GetNextSibling() const; |
|
287 void SetNextSibling(nsCellMap* aSibling); |
|
288 |
|
289 nsTableRowGroupFrame* GetRowGroup() const; |
|
290 |
|
291 nsTableCellFrame* GetCellFrame(int32_t aRowIndex, |
|
292 int32_t aColIndex, |
|
293 CellData& aData, |
|
294 bool aUseRowSpanIfOverlap) const; |
|
295 |
|
296 /** |
|
297 * Returns highest cell index within the cell map. |
|
298 * |
|
299 * @param aColCount [in] the number of columns in the table |
|
300 */ |
|
301 int32_t GetHighestIndex(int32_t aColCount); |
|
302 |
|
303 /** |
|
304 * Returns the index of the given row and column coordinates. |
|
305 * |
|
306 * @see nsITableLayout::GetIndexByRowAndColumn() |
|
307 * |
|
308 * @param aColCount [in] the number of columns in the table |
|
309 * @param aRow [in] the row coordinate |
|
310 * @param aColumn [in] the column coordinate |
|
311 */ |
|
312 int32_t GetIndexByRowAndColumn(int32_t aColCount, |
|
313 int32_t aRow, int32_t aColumn) const; |
|
314 |
|
315 /** |
|
316 * Get the row and column coordinates at the given index. |
|
317 * |
|
318 * @see nsITableLayout::GetRowAndColumnByIndex() |
|
319 * |
|
320 * @param aColCount [in] the number of columns in the table |
|
321 * @param aIndex [in] the index for which coordinates are to be retrieved |
|
322 * @param aRow [out] the row coordinate to be returned |
|
323 * @param aColumn [out] the column coordinate to be returned |
|
324 */ |
|
325 void GetRowAndColumnByIndex(int32_t aColCount, int32_t aIndex, |
|
326 int32_t *aRow, int32_t *aColumn) const; |
|
327 |
|
328 /** append the cellFrame at an empty or dead cell or finally at the end of |
|
329 * the row at aRowIndex and return a pointer to the celldata entry in the |
|
330 * cellmap |
|
331 * |
|
332 * @param aMap - reference to the table cell map |
|
333 * @param aCellFrame - a pointer to the cellframe which will be appended |
|
334 * to the row |
|
335 * @param aRowIndex - to this row the celldata entry will be added |
|
336 * @param aRebuildIfNecessay - if a cell spans into a row below it might be |
|
337 * necesserary to rebuild the cellmap as this rowspan |
|
338 * might overlap another cell. |
|
339 * @param aDamageArea - area in cellmap coordinates which have been updated. |
|
340 * @param aColToBeginSearch - if not null contains the column number where |
|
341 * the search for a empty or dead cell in the |
|
342 * row should start |
|
343 * @return - a pointer to the celldata entry inserted into |
|
344 * the cellmap |
|
345 */ |
|
346 CellData* AppendCell(nsTableCellMap& aMap, |
|
347 nsTableCellFrame* aCellFrame, |
|
348 int32_t aRowIndex, |
|
349 bool aRebuildIfNecessary, |
|
350 int32_t aRgFirstRowIndex, |
|
351 nsIntRect& aDamageArea, |
|
352 int32_t* aBeginSearchAtCol = nullptr); |
|
353 |
|
354 /** Function to be called when a cell is added at a location which is spanned |
|
355 * to by a zero colspan. We handle this situation by collapsing the zero |
|
356 * colspan, since there is really no good way to deal with it (trying to |
|
357 * increase the number of columns to hold the new cell would just mean the |
|
358 * zero colspan needs to expand). |
|
359 |
|
360 * @param aMap - reference to the table cell map |
|
361 * @param aOrigData - zero colspanned cell that will be collapsed |
|
362 * @param aRowIndex - row where the first collision appears |
|
363 * @param aColIndex - column where the first collision appears |
|
364 **/ |
|
365 void CollapseZeroColSpan(nsTableCellMap& aMap, |
|
366 CellData* aOrigData, |
|
367 int32_t aRowIndex, |
|
368 int32_t aColIndex); |
|
369 |
|
370 void InsertCells(nsTableCellMap& aMap, |
|
371 nsTArray<nsTableCellFrame*>& aCellFrames, |
|
372 int32_t aRowIndex, |
|
373 int32_t aColIndexBefore, |
|
374 int32_t aRgFirstRowIndex, |
|
375 nsIntRect& aDamageArea); |
|
376 |
|
377 void RemoveCell(nsTableCellMap& aMap, |
|
378 nsTableCellFrame* aCellFrame, |
|
379 int32_t aRowIndex, |
|
380 int32_t aRgFirstRowIndex, |
|
381 nsIntRect& aDamageArea); |
|
382 |
|
383 void InsertRows(nsTableCellMap& aMap, |
|
384 nsTArray<nsTableRowFrame*>& aRows, |
|
385 int32_t aFirstRowIndex, |
|
386 bool aConsiderSpans, |
|
387 int32_t aRgFirstRowIndex, |
|
388 nsIntRect& aDamageArea); |
|
389 |
|
390 void RemoveRows(nsTableCellMap& aMap, |
|
391 int32_t aFirstRowIndex, |
|
392 int32_t aNumRowsToRemove, |
|
393 bool aConsiderSpans, |
|
394 int32_t aRgFirstRowIndex, |
|
395 nsIntRect& aDamageArea); |
|
396 |
|
397 int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const; |
|
398 int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const; |
|
399 |
|
400 /** return the number of rows in the table represented by this CellMap */ |
|
401 int32_t GetRowCount(bool aConsiderDeadRowSpanRows = false) const; |
|
402 |
|
403 nsTableCellFrame* GetCellInfoAt(const nsTableCellMap& aMap, |
|
404 int32_t aRowX, |
|
405 int32_t aColX, |
|
406 bool* aOriginates = nullptr, |
|
407 int32_t* aColSpan = nullptr) const; |
|
408 |
|
409 bool RowIsSpannedInto(int32_t aRowIndex, |
|
410 int32_t aNumEffCols) const; |
|
411 |
|
412 bool RowHasSpanningCells(int32_t aRowIndex, |
|
413 int32_t aNumEffCols) const; |
|
414 |
|
415 void ExpandZeroColSpans(nsTableCellMap& aMap); |
|
416 |
|
417 /** indicate whether the row has more than one cell that either originates |
|
418 * or is spanned from the rows above |
|
419 */ |
|
420 bool HasMoreThanOneCell(int32_t aRowIndex) const; |
|
421 |
|
422 /* Get the rowspan for a cell starting at aRowIndex and aColIndex. |
|
423 * If aGetEffective is true the size will not exceed the last content based |
|
424 * row. Cells can have a specified rowspan that extends below the last |
|
425 * content based row. This is legitimate considering incr. reflow where the |
|
426 * content rows will arive later. |
|
427 */ |
|
428 int32_t GetRowSpan(int32_t aRowIndex, |
|
429 int32_t aColIndex, |
|
430 bool aGetEffective) const; |
|
431 |
|
432 int32_t GetEffectiveColSpan(const nsTableCellMap& aMap, |
|
433 int32_t aRowIndex, |
|
434 int32_t aColIndex, |
|
435 bool& aIsZeroColSpan) const; |
|
436 |
|
437 typedef nsTArray<CellData*> CellDataArray; |
|
438 |
|
439 /** dump a representation of the cell map to stdout for debugging */ |
|
440 #ifdef DEBUG |
|
441 void Dump(bool aIsBorderCollapse) const; |
|
442 #endif |
|
443 |
|
444 protected: |
|
445 friend class nsTableCellMap; |
|
446 friend class BCMapCellIterator; |
|
447 friend class BCPaintBorderIterator; |
|
448 friend class nsTableFrame; |
|
449 friend class nsCellMapColumnIterator; |
|
450 |
|
451 /** |
|
452 * Increase the number of rows in this cellmap by aNumRows. Put the |
|
453 * new rows at aRowIndex. If aRowIndex is -1, put them at the end. |
|
454 */ |
|
455 bool Grow(nsTableCellMap& aMap, |
|
456 int32_t aNumRows, |
|
457 int32_t aRowIndex = -1); |
|
458 |
|
459 void GrowRow(CellDataArray& aRow, |
|
460 int32_t aNumCols); |
|
461 |
|
462 /** assign aCellData to the cell at (aRow,aColumn) */ |
|
463 void SetDataAt(nsTableCellMap& aMap, |
|
464 CellData& aCellData, |
|
465 int32_t aMapRowIndex, |
|
466 int32_t aColIndex); |
|
467 |
|
468 CellData* GetDataAt(int32_t aMapRowIndex, |
|
469 int32_t aColIndex) const; |
|
470 |
|
471 int32_t GetNumCellsIn(int32_t aColIndex) const; |
|
472 |
|
473 void ExpandWithRows(nsTableCellMap& aMap, |
|
474 nsTArray<nsTableRowFrame*>& aRowFrames, |
|
475 int32_t aStartRowIndex, |
|
476 int32_t aRgFirstRowIndex, |
|
477 nsIntRect& aDamageArea); |
|
478 |
|
479 void ExpandWithCells(nsTableCellMap& aMap, |
|
480 nsTArray<nsTableCellFrame*>& aCellFrames, |
|
481 int32_t aRowIndex, |
|
482 int32_t aColIndex, |
|
483 int32_t aRowSpan, |
|
484 bool aRowSpanIsZero, |
|
485 int32_t aRgFirstRowIndex, |
|
486 nsIntRect& aDamageArea); |
|
487 |
|
488 void ShrinkWithoutRows(nsTableCellMap& aMap, |
|
489 int32_t aFirstRowIndex, |
|
490 int32_t aNumRowsToRemove, |
|
491 int32_t aRgFirstRowIndex, |
|
492 nsIntRect& aDamageArea); |
|
493 |
|
494 void ShrinkWithoutCell(nsTableCellMap& aMap, |
|
495 nsTableCellFrame& aCellFrame, |
|
496 int32_t aRowIndex, |
|
497 int32_t aColIndex, |
|
498 int32_t aRgFirstRowIndex, |
|
499 nsIntRect& aDamageArea); |
|
500 |
|
501 /** |
|
502 * Rebuild due to rows being inserted or deleted with cells spanning |
|
503 * into or out of the rows. This function can only handle insertion |
|
504 * or deletion but NOT both. So either aRowsToInsert must be null |
|
505 * or aNumRowsToRemove must be 0. |
|
506 * |
|
507 * // XXXbz are both allowed to happen? That'd be a no-op... |
|
508 */ |
|
509 void RebuildConsideringRows(nsTableCellMap& aMap, |
|
510 int32_t aStartRowIndex, |
|
511 nsTArray<nsTableRowFrame*>* aRowsToInsert, |
|
512 int32_t aNumRowsToRemove); |
|
513 |
|
514 void RebuildConsideringCells(nsTableCellMap& aMap, |
|
515 int32_t aNumOrigCols, |
|
516 nsTArray<nsTableCellFrame*>* aCellFrames, |
|
517 int32_t aRowIndex, |
|
518 int32_t aColIndex, |
|
519 bool aInsert); |
|
520 |
|
521 bool CellsSpanOut(nsTArray<nsTableRowFrame*>& aNewRows) const; |
|
522 |
|
523 /** If a cell spans out of the area defined by aStartRowIndex, aEndRowIndex |
|
524 * and aStartColIndex, aEndColIndex the cellmap changes are more severe so |
|
525 * the corresponding routines needs to be called. This is also necessary if |
|
526 * cells outside spans into this region. |
|
527 * @aStartRowIndex - y start index |
|
528 * @aEndRowIndex - y end index |
|
529 * @param aStartColIndex - x start index |
|
530 * @param aEndColIndex - x end index |
|
531 * @return - true if a cell span crosses the border of the |
|
532 region |
|
533 */ |
|
534 bool CellsSpanInOrOut(int32_t aStartRowIndex, |
|
535 int32_t aEndRowIndex, |
|
536 int32_t aStartColIndex, |
|
537 int32_t aEndColIndex) const; |
|
538 |
|
539 void ExpandForZeroSpan(nsTableCellFrame* aCellFrame, |
|
540 int32_t aNumColsInTable); |
|
541 |
|
542 bool CreateEmptyRow(int32_t aRowIndex, |
|
543 int32_t aNumCols); |
|
544 |
|
545 int32_t GetRowSpanForNewCell(nsTableCellFrame* aCellFrameToAdd, |
|
546 int32_t aRowIndex, |
|
547 bool& aIsZeroRowSpan) const; |
|
548 |
|
549 int32_t GetColSpanForNewCell(nsTableCellFrame& aCellFrameToAdd, |
|
550 bool& aIsZeroColSpan) const; |
|
551 |
|
552 // Destroy a CellData struct. This will handle the case of aData |
|
553 // actually being a BCCellData properly. |
|
554 void DestroyCellData(CellData* aData); |
|
555 // Allocate a CellData struct. This will handle needing to create a |
|
556 // BCCellData properly. |
|
557 // @param aOrigCell the originating cell to pass to the celldata constructor |
|
558 CellData* AllocCellData(nsTableCellFrame* aOrigCell); |
|
559 |
|
560 /** an array containing, for each row, the CellDatas for the cells |
|
561 * in that row. It can be larger than mContentRowCount due to row spans |
|
562 * extending beyond the table */ |
|
563 // XXXbz once we have auto TArrays, we should probably use them here. |
|
564 nsTArray<CellDataArray> mRows; |
|
565 |
|
566 /** the number of rows in the table (content) which is not indentical to the |
|
567 * number of rows in the cell map due to row spans extending beyond the end |
|
568 * of thetable (dead rows) or empty tr tags |
|
569 */ |
|
570 int32_t mContentRowCount; |
|
571 |
|
572 // the row group that corresponds to this map |
|
573 nsTableRowGroupFrame* mRowGroupFrame; |
|
574 |
|
575 // the next row group cell map |
|
576 nsCellMap* mNextSibling; |
|
577 |
|
578 // Whether this is a BC cellmap or not |
|
579 bool mIsBC; |
|
580 |
|
581 // Prescontext to deallocate and allocate celldata |
|
582 nsRefPtr<nsPresContext> mPresContext; |
|
583 }; |
|
584 |
|
585 /** |
|
586 * A class for iterating the cells in a given column. Must be given a |
|
587 * non-null nsTableCellMap and a column number valid for that cellmap. |
|
588 */ |
|
589 class nsCellMapColumnIterator |
|
590 { |
|
591 public: |
|
592 nsCellMapColumnIterator(const nsTableCellMap* aMap, int32_t aCol) : |
|
593 mMap(aMap), mCurMap(aMap->mFirstMap), mCurMapStart(0), |
|
594 mCurMapRow(0), mCol(aCol), mFoundCells(0) |
|
595 { |
|
596 NS_PRECONDITION(aMap, "Must have map"); |
|
597 NS_PRECONDITION(mCol < aMap->GetColCount(), "Invalid column"); |
|
598 mOrigCells = aMap->GetNumCellsOriginatingInCol(mCol); |
|
599 if (mCurMap) { |
|
600 mCurMapContentRowCount = mCurMap->GetRowCount(); |
|
601 uint32_t rowArrayLength = mCurMap->mRows.Length(); |
|
602 mCurMapRelevantRowCount = std::min(mCurMapContentRowCount, rowArrayLength); |
|
603 if (mCurMapRelevantRowCount == 0 && mOrigCells > 0) { |
|
604 // This row group is useless; advance! |
|
605 AdvanceRowGroup(); |
|
606 } |
|
607 } |
|
608 #ifdef DEBUG |
|
609 else { |
|
610 NS_ASSERTION(mOrigCells == 0, "Why no rowgroups?"); |
|
611 } |
|
612 #endif |
|
613 } |
|
614 |
|
615 nsTableCellFrame* GetNextFrame(int32_t* aRow, int32_t* aColSpan); |
|
616 |
|
617 private: |
|
618 void AdvanceRowGroup(); |
|
619 |
|
620 // Advance the row; aIncrement is considered to be a cell's rowspan, |
|
621 // so if 0 is passed in we'll advance to the next rowgroup. |
|
622 void IncrementRow(int32_t aIncrement); |
|
623 |
|
624 const nsTableCellMap* mMap; |
|
625 const nsCellMap* mCurMap; |
|
626 |
|
627 // mCurMapStart is the row in the entire nsTableCellMap where |
|
628 // mCurMap starts. This is used to compute row indices to pass to |
|
629 // nsTableCellMap::GetDataAt, so must be a _content_ row index. |
|
630 uint32_t mCurMapStart; |
|
631 |
|
632 // In steady-state mCurMapRow is the row in our current nsCellMap |
|
633 // that we'll use the next time GetNextFrame() is called. Due to |
|
634 // the way we skip over rowspans, the entry in mCurMapRow and mCol |
|
635 // is either null, dead, originating, or a colspan. In particular, |
|
636 // it cannot be a rowspan or overlap entry. |
|
637 uint32_t mCurMapRow; |
|
638 const int32_t mCol; |
|
639 uint32_t mOrigCells; |
|
640 uint32_t mFoundCells; |
|
641 |
|
642 // The number of content rows in mCurMap. This may be bigger than the number |
|
643 // of "relevant" rows, or it might be smaller. |
|
644 uint32_t mCurMapContentRowCount; |
|
645 |
|
646 // The number of "relevant" rows in mCurMap. That is, the number of rows |
|
647 // which might have an originating cell in them. Once mCurMapRow reaches |
|
648 // mCurMapRelevantRowCount, we should move to the next map. |
|
649 uint32_t mCurMapRelevantRowCount; |
|
650 }; |
|
651 |
|
652 |
|
653 /* ----- inline methods ----- */ |
|
654 inline int32_t nsTableCellMap::GetColCount() const |
|
655 { |
|
656 return mCols.Length(); |
|
657 } |
|
658 |
|
659 inline nsCellMap* nsCellMap::GetNextSibling() const |
|
660 { |
|
661 return mNextSibling; |
|
662 } |
|
663 |
|
664 inline void nsCellMap::SetNextSibling(nsCellMap* aSibling) |
|
665 { |
|
666 mNextSibling = aSibling; |
|
667 } |
|
668 |
|
669 inline nsTableRowGroupFrame* nsCellMap::GetRowGroup() const |
|
670 { |
|
671 return mRowGroupFrame; |
|
672 } |
|
673 |
|
674 inline int32_t nsCellMap::GetRowCount(bool aConsiderDeadRowSpanRows) const |
|
675 { |
|
676 int32_t rowCount = (aConsiderDeadRowSpanRows) ? mRows.Length() : mContentRowCount; |
|
677 return rowCount; |
|
678 } |
|
679 |
|
680 // nsColInfo |
|
681 |
|
682 inline nsColInfo::nsColInfo() |
|
683 :mNumCellsOrig(0), mNumCellsSpan(0) |
|
684 {} |
|
685 |
|
686 inline nsColInfo::nsColInfo(int32_t aNumCellsOrig, |
|
687 int32_t aNumCellsSpan) |
|
688 :mNumCellsOrig(aNumCellsOrig), mNumCellsSpan(aNumCellsSpan) |
|
689 {} |
|
690 |
|
691 |
|
692 #endif |