1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/grid/nsGrid.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1299 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// 1.10 +// Eric Vaughan 1.11 +// Netscape Communications 1.12 +// 1.13 +// See documentation in associated header file 1.14 +// 1.15 + 1.16 +#include "nsGrid.h" 1.17 +#include "nsGridRowGroupLayout.h" 1.18 +#include "nsBox.h" 1.19 +#include "nsIScrollableFrame.h" 1.20 +#include "nsSprocketLayout.h" 1.21 +#include "nsGridLayout2.h" 1.22 +#include "nsGridRow.h" 1.23 +#include "nsGridCell.h" 1.24 +#include "nsHTMLReflowState.h" 1.25 + 1.26 +/* 1.27 +The grid control expands the idea of boxes from 1 dimension to 2 dimensions. 1.28 +It works by allowing the XUL to define a collection of rows and columns and then 1.29 +stacking them on top of each other. Here is and example. 1.30 + 1.31 +Example 1: 1.32 + 1.33 +<grid> 1.34 + <columns> 1.35 + <column/> 1.36 + <column/> 1.37 + </columns> 1.38 + 1.39 + <rows> 1.40 + <row/> 1.41 + <row/> 1.42 + </rows> 1.43 +</grid> 1.44 + 1.45 +example 2: 1.46 + 1.47 +<grid> 1.48 + <columns> 1.49 + <column flex="1"/> 1.50 + <column flex="1"/> 1.51 + </columns> 1.52 + 1.53 + <rows> 1.54 + <row> 1.55 + <text value="hello"/> 1.56 + <text value="there"/> 1.57 + </row> 1.58 + </rows> 1.59 +</grid> 1.60 + 1.61 +example 3: 1.62 + 1.63 +<grid> 1.64 + 1.65 +<rows> 1.66 + <row> 1.67 + <text value="hello"/> 1.68 + <text value="there"/> 1.69 + </row> 1.70 + </rows> 1.71 + 1.72 + <columns> 1.73 + <column> 1.74 + <text value="Hey I'm in the column and I'm on top!"/> 1.75 + </column> 1.76 + <column/> 1.77 + </columns> 1.78 + 1.79 +</grid> 1.80 + 1.81 +Usually the columns are first and the rows are second, so the rows will be drawn on top of the columns. 1.82 +You can reverse this by defining the rows first. 1.83 +Other tags are then placed in the <row> or <column> tags causing the grid to accommodate everyone. 1.84 +It does this by creating 3 things: A cellmap, a row list, and a column list. The cellmap is a 2 1.85 +dimensional array of nsGridCells. Each cell contains 2 boxes. One cell from the column list 1.86 +and one from the row list. When a cell is asked for its size it returns that smallest size it can 1.87 +be to accommodate the 2 cells. Row lists and Column lists use the same data structure: nsGridRow. 1.88 +Essentially a row and column are the same except a row goes alone the x axis and a column the y. 1.89 +To make things easier and save code everything is written in terms of the x dimension. A flag is 1.90 +passed in called "isHorizontal" that can flip the calculations to the y axis. 1.91 + 1.92 +Usually the number of cells in a row match the number of columns, but not always. 1.93 +It is possible to define 5 columns for a grid but have 10 cells in one of the rows. 1.94 +In this case 5 extra columns will be added to the column list to handle the situation. 1.95 +These are called extraColumns/Rows. 1.96 +*/ 1.97 + 1.98 +nsGrid::nsGrid():mBox(nullptr), 1.99 + mRows(nullptr), 1.100 + mColumns(nullptr), 1.101 + mRowsBox(nullptr), 1.102 + mColumnsBox(nullptr), 1.103 + mNeedsRebuild(true), 1.104 + mRowCount(0), 1.105 + mColumnCount(0), 1.106 + mExtraRowCount(0), 1.107 + mExtraColumnCount(0), 1.108 + mCellMap(nullptr), 1.109 + mMarkingDirty(false) 1.110 +{ 1.111 + MOZ_COUNT_CTOR(nsGrid); 1.112 +} 1.113 + 1.114 +nsGrid::~nsGrid() 1.115 +{ 1.116 + FreeMap(); 1.117 + MOZ_COUNT_DTOR(nsGrid); 1.118 +} 1.119 + 1.120 +/* 1.121 + * This is called whenever something major happens in the grid. And example 1.122 + * might be when many cells or row are added. It sets a flag signaling that 1.123 + * all the grids caches information should be recalculated. 1.124 + */ 1.125 +void 1.126 +nsGrid::NeedsRebuild(nsBoxLayoutState& aState) 1.127 +{ 1.128 + if (mNeedsRebuild) 1.129 + return; 1.130 + 1.131 + // iterate through columns and rows and dirty them 1.132 + mNeedsRebuild = true; 1.133 + 1.134 + // find the new row and column box. They could have 1.135 + // been changed. 1.136 + mRowsBox = nullptr; 1.137 + mColumnsBox = nullptr; 1.138 + FindRowsAndColumns(&mRowsBox, &mColumnsBox); 1.139 + 1.140 + // tell all the rows and columns they are dirty 1.141 + DirtyRows(mRowsBox, aState); 1.142 + DirtyRows(mColumnsBox, aState); 1.143 +} 1.144 + 1.145 + 1.146 + 1.147 +/** 1.148 + * If we are marked for rebuild. Then build everything 1.149 + */ 1.150 +void 1.151 +nsGrid::RebuildIfNeeded() 1.152 +{ 1.153 + if (!mNeedsRebuild) 1.154 + return; 1.155 + 1.156 + mNeedsRebuild = false; 1.157 + 1.158 + // find the row and columns frames 1.159 + FindRowsAndColumns(&mRowsBox, &mColumnsBox); 1.160 + 1.161 + // count the rows and columns 1.162 + int32_t computedRowCount = 0; 1.163 + int32_t computedColumnCount = 0; 1.164 + int32_t rowCount = 0; 1.165 + int32_t columnCount = 0; 1.166 + 1.167 + CountRowsColumns(mRowsBox, rowCount, computedColumnCount); 1.168 + CountRowsColumns(mColumnsBox, columnCount, computedRowCount); 1.169 + 1.170 + // computedRowCount are the actual number of rows as determined by the 1.171 + // columns children. 1.172 + // computedColumnCount are the number of columns as determined by the number 1.173 + // of rows children. 1.174 + // We can use this information to see how many extra columns or rows we need. 1.175 + // This can happen if there are are more children in a row that number of columns 1.176 + // defined. Example: 1.177 + // 1.178 + // <columns> 1.179 + // <column/> 1.180 + // </columns> 1.181 + // 1.182 + // <rows> 1.183 + // <row> 1.184 + // <button/><button/> 1.185 + // </row> 1.186 + // </rows> 1.187 + // 1.188 + // computedColumnCount = 2 // for the 2 buttons in the row tag 1.189 + // computedRowCount = 0 // there is nothing in the column tag 1.190 + // mColumnCount = 1 // one column defined 1.191 + // mRowCount = 1 // one row defined 1.192 + // 1.193 + // So in this case we need to make 1 extra column. 1.194 + // 1.195 + 1.196 + // Make sure to update mExtraColumnCount no matter what, since it might 1.197 + // happen that we now have as many columns as are defined, and we wouldn't 1.198 + // want to have a positive mExtraColumnCount hanging about in that case! 1.199 + mExtraColumnCount = computedColumnCount - columnCount; 1.200 + if (computedColumnCount > columnCount) { 1.201 + columnCount = computedColumnCount; 1.202 + } 1.203 + 1.204 + // Same for rows. 1.205 + mExtraRowCount = computedRowCount - rowCount; 1.206 + if (computedRowCount > rowCount) { 1.207 + rowCount = computedRowCount; 1.208 + } 1.209 + 1.210 + // build and poplulate row and columns arrays 1.211 + BuildRows(mRowsBox, rowCount, &mRows, true); 1.212 + BuildRows(mColumnsBox, columnCount, &mColumns, false); 1.213 + 1.214 + // build and populate the cell map 1.215 + mCellMap = BuildCellMap(rowCount, columnCount); 1.216 + 1.217 + mRowCount = rowCount; 1.218 + mColumnCount = columnCount; 1.219 + 1.220 + // populate the cell map from column and row children 1.221 + PopulateCellMap(mRows, mColumns, mRowCount, mColumnCount, true); 1.222 + PopulateCellMap(mColumns, mRows, mColumnCount, mRowCount, false); 1.223 +} 1.224 + 1.225 +void 1.226 +nsGrid::FreeMap() 1.227 +{ 1.228 + if (mRows) 1.229 + delete[] mRows; 1.230 + 1.231 + if (mColumns) 1.232 + delete[] mColumns; 1.233 + 1.234 + if (mCellMap) 1.235 + delete[] mCellMap; 1.236 + 1.237 + mRows = nullptr; 1.238 + mColumns = nullptr; 1.239 + mCellMap = nullptr; 1.240 + mColumnCount = 0; 1.241 + mRowCount = 0; 1.242 + mExtraColumnCount = 0; 1.243 + mExtraRowCount = 0; 1.244 + mRowsBox = nullptr; 1.245 + mColumnsBox = nullptr; 1.246 +} 1.247 + 1.248 +/** 1.249 + * finds the first <rows> and <columns> tags in the <grid> tag 1.250 + */ 1.251 +void 1.252 +nsGrid::FindRowsAndColumns(nsIFrame** aRows, nsIFrame** aColumns) 1.253 +{ 1.254 + *aRows = nullptr; 1.255 + *aColumns = nullptr; 1.256 + 1.257 + // find the boxes that contain our rows and columns 1.258 + nsIFrame* child = nullptr; 1.259 + // if we have <grid></grid> then mBox will be null (bug 125689) 1.260 + if (mBox) 1.261 + child = mBox->GetChildBox(); 1.262 + 1.263 + while(child) 1.264 + { 1.265 + nsIFrame* oldBox = child; 1.266 + nsIScrollableFrame *scrollFrame = do_QueryFrame(child); 1.267 + if (scrollFrame) { 1.268 + nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame(); 1.269 + NS_ASSERTION(scrolledFrame,"Error no scroll frame!!"); 1.270 + child = do_QueryFrame(scrolledFrame); 1.271 + } 1.272 + 1.273 + nsCOMPtr<nsIGridPart> monument = GetPartFromBox(child); 1.274 + if (monument) 1.275 + { 1.276 + nsGridRowGroupLayout* rowGroup = monument->CastToRowGroupLayout(); 1.277 + if (rowGroup) { 1.278 + bool isHorizontal = !nsSprocketLayout::IsHorizontal(child); 1.279 + if (isHorizontal) 1.280 + *aRows = child; 1.281 + else 1.282 + *aColumns = child; 1.283 + 1.284 + if (*aRows && *aColumns) 1.285 + return; 1.286 + } 1.287 + } 1.288 + 1.289 + if (scrollFrame) { 1.290 + child = oldBox; 1.291 + } 1.292 + 1.293 + child = child->GetNextBox(); 1.294 + } 1.295 +} 1.296 + 1.297 +/** 1.298 + * Count the number of rows and columns in the given box. aRowCount well become the actual number 1.299 + * rows defined in the xul. aComputedColumnCount will become the number of columns by counting the number 1.300 + * of cells in each row. 1.301 + */ 1.302 +void 1.303 +nsGrid::CountRowsColumns(nsIFrame* aRowBox, int32_t& aRowCount, int32_t& aComputedColumnCount) 1.304 +{ 1.305 + aRowCount = 0; 1.306 + aComputedColumnCount = 0; 1.307 + // get the rowboxes layout manager. Then ask it to do the work for us 1.308 + if (aRowBox) { 1.309 + nsCOMPtr<nsIGridPart> monument = GetPartFromBox(aRowBox); 1.310 + if (monument) 1.311 + monument->CountRowsColumns(aRowBox, aRowCount, aComputedColumnCount); 1.312 + } 1.313 +} 1.314 + 1.315 + 1.316 +/** 1.317 + * Given the number of rows create nsGridRow objects for them and full them out. 1.318 + */ 1.319 +void 1.320 +nsGrid::BuildRows(nsIFrame* aBox, int32_t aRowCount, nsGridRow** aRows, bool aIsHorizontal) 1.321 +{ 1.322 + // if no rows then return null 1.323 + if (aRowCount == 0) { 1.324 + 1.325 + // make sure we free up the memory. 1.326 + if (*aRows) 1.327 + delete[] (*aRows); 1.328 + 1.329 + *aRows = nullptr; 1.330 + return; 1.331 + } 1.332 + 1.333 + // create the array 1.334 + nsGridRow* row; 1.335 + 1.336 + // only create new rows if we have to. Reuse old rows. 1.337 + if (aIsHorizontal) 1.338 + { 1.339 + if (aRowCount > mRowCount) { 1.340 + delete[] mRows; 1.341 + row = new nsGridRow[aRowCount]; 1.342 + } else { 1.343 + for (int32_t i=0; i < mRowCount; i++) 1.344 + mRows[i].Init(nullptr, false); 1.345 + 1.346 + row = mRows; 1.347 + } 1.348 + } else { 1.349 + if (aRowCount > mColumnCount) { 1.350 + delete[] mColumns; 1.351 + row = new nsGridRow[aRowCount]; 1.352 + } else { 1.353 + for (int32_t i=0; i < mColumnCount; i++) 1.354 + mColumns[i].Init(nullptr, false); 1.355 + 1.356 + row = mColumns; 1.357 + } 1.358 + } 1.359 + 1.360 + // populate it if we can. If not it will contain only dynamic columns 1.361 + if (aBox) 1.362 + { 1.363 + nsCOMPtr<nsIGridPart> monument = GetPartFromBox(aBox); 1.364 + if (monument) { 1.365 + monument->BuildRows(aBox, row); 1.366 + } 1.367 + } 1.368 + 1.369 + *aRows = row; 1.370 +} 1.371 + 1.372 + 1.373 +/** 1.374 + * Given the number of rows and columns. Build a cellmap 1.375 + */ 1.376 +nsGridCell* 1.377 +nsGrid::BuildCellMap(int32_t aRows, int32_t aColumns) 1.378 +{ 1.379 + int32_t size = aRows*aColumns; 1.380 + int32_t oldsize = mRowCount*mColumnCount; 1.381 + if (size == 0) { 1.382 + delete[] mCellMap; 1.383 + } 1.384 + else { 1.385 + if (size > oldsize) { 1.386 + delete[] mCellMap; 1.387 + return new nsGridCell[size]; 1.388 + } else { 1.389 + // clear out cellmap 1.390 + for (int32_t i=0; i < oldsize; i++) 1.391 + { 1.392 + mCellMap[i].SetBoxInRow(nullptr); 1.393 + mCellMap[i].SetBoxInColumn(nullptr); 1.394 + } 1.395 + return mCellMap; 1.396 + } 1.397 + } 1.398 + return nullptr; 1.399 +} 1.400 + 1.401 +/** 1.402 + * Run through all the cells in the rows and columns and populate then with 2 cells. One from the row and one 1.403 + * from the column 1.404 + */ 1.405 +void 1.406 +nsGrid::PopulateCellMap(nsGridRow* aRows, nsGridRow* aColumns, int32_t aRowCount, int32_t aColumnCount, bool aIsHorizontal) 1.407 +{ 1.408 + if (!aRows) 1.409 + return; 1.410 + 1.411 + // look through the columns 1.412 + int32_t j = 0; 1.413 + 1.414 + for(int32_t i=0; i < aRowCount; i++) 1.415 + { 1.416 + nsIFrame* child = nullptr; 1.417 + nsGridRow* row = &aRows[i]; 1.418 + 1.419 + // skip bogus rows. They have no cells 1.420 + if (row->mIsBogus) 1.421 + continue; 1.422 + 1.423 + child = row->mBox; 1.424 + if (child) { 1.425 + child = child->GetChildBox(); 1.426 + 1.427 + j = 0; 1.428 + 1.429 + while(child && j < aColumnCount) 1.430 + { 1.431 + // skip bogus column. They have no cells 1.432 + nsGridRow* column = &aColumns[j]; 1.433 + if (column->mIsBogus) 1.434 + { 1.435 + j++; 1.436 + continue; 1.437 + } 1.438 + 1.439 + if (aIsHorizontal) 1.440 + GetCellAt(j,i)->SetBoxInRow(child); 1.441 + else 1.442 + GetCellAt(i,j)->SetBoxInColumn(child); 1.443 + 1.444 + child = child->GetNextBox(); 1.445 + 1.446 + j++; 1.447 + } 1.448 + } 1.449 + } 1.450 +} 1.451 + 1.452 +/** 1.453 + * Run through the rows in the given box and mark them dirty so they 1.454 + * will get recalculated and get a layout. 1.455 + */ 1.456 +void 1.457 +nsGrid::DirtyRows(nsIFrame* aRowBox, nsBoxLayoutState& aState) 1.458 +{ 1.459 + // make sure we prevent others from dirtying things. 1.460 + mMarkingDirty = true; 1.461 + 1.462 + // if the box is a grid part have it recursively hand it. 1.463 + if (aRowBox) { 1.464 + nsCOMPtr<nsIGridPart> part = GetPartFromBox(aRowBox); 1.465 + if (part) 1.466 + part->DirtyRows(aRowBox, aState); 1.467 + } 1.468 + 1.469 + mMarkingDirty = false; 1.470 +} 1.471 + 1.472 +nsGridRow* 1.473 +nsGrid::GetColumnAt(int32_t aIndex, bool aIsHorizontal) 1.474 +{ 1.475 + return GetRowAt(aIndex, !aIsHorizontal); 1.476 +} 1.477 + 1.478 +nsGridRow* 1.479 +nsGrid::GetRowAt(int32_t aIndex, bool aIsHorizontal) 1.480 +{ 1.481 + RebuildIfNeeded(); 1.482 + 1.483 + if (aIsHorizontal) { 1.484 + NS_ASSERTION(aIndex < mRowCount && aIndex >= 0, "Index out of range"); 1.485 + return &mRows[aIndex]; 1.486 + } else { 1.487 + NS_ASSERTION(aIndex < mColumnCount && aIndex >= 0, "Index out of range"); 1.488 + return &mColumns[aIndex]; 1.489 + } 1.490 +} 1.491 + 1.492 +nsGridCell* 1.493 +nsGrid::GetCellAt(int32_t aX, int32_t aY) 1.494 +{ 1.495 + RebuildIfNeeded(); 1.496 + 1.497 + NS_ASSERTION(aY < mRowCount && aY >= 0, "Index out of range"); 1.498 + NS_ASSERTION(aX < mColumnCount && aX >= 0, "Index out of range"); 1.499 + return &mCellMap[aY*mColumnCount+aX]; 1.500 +} 1.501 + 1.502 +int32_t 1.503 +nsGrid::GetExtraColumnCount(bool aIsHorizontal) 1.504 +{ 1.505 + return GetExtraRowCount(!aIsHorizontal); 1.506 +} 1.507 + 1.508 +int32_t 1.509 +nsGrid::GetExtraRowCount(bool aIsHorizontal) 1.510 +{ 1.511 + RebuildIfNeeded(); 1.512 + 1.513 + if (aIsHorizontal) 1.514 + return mExtraRowCount; 1.515 + else 1.516 + return mExtraColumnCount; 1.517 +} 1.518 + 1.519 + 1.520 +/** 1.521 + * These methods return the preferred, min, max sizes for a given row index. 1.522 + * aIsHorizontal if aIsHorizontal is true. If you pass false you will get the inverse. 1.523 + * As if you called GetPrefColumnSize(aState, index, aPref) 1.524 + */ 1.525 +nsSize 1.526 +nsGrid::GetPrefRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal) 1.527 +{ 1.528 + nsSize size(0,0); 1.529 + if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal))) 1.530 + return size; 1.531 + 1.532 + nscoord height = GetPrefRowHeight(aState, aRowIndex, aIsHorizontal); 1.533 + SetLargestSize(size, height, aIsHorizontal); 1.534 + 1.535 + return size; 1.536 +} 1.537 + 1.538 +nsSize 1.539 +nsGrid::GetMinRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal) 1.540 +{ 1.541 + nsSize size(0,0); 1.542 + if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal))) 1.543 + return size; 1.544 + 1.545 + nscoord height = GetMinRowHeight(aState, aRowIndex, aIsHorizontal); 1.546 + SetLargestSize(size, height, aIsHorizontal); 1.547 + 1.548 + return size; 1.549 +} 1.550 + 1.551 +nsSize 1.552 +nsGrid::GetMaxRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal) 1.553 +{ 1.554 + nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE); 1.555 + if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal))) 1.556 + return size; 1.557 + 1.558 + nscoord height = GetMaxRowHeight(aState, aRowIndex, aIsHorizontal); 1.559 + SetSmallestSize(size, height, aIsHorizontal); 1.560 + 1.561 + return size; 1.562 +} 1.563 + 1.564 +// static 1.565 +nsIGridPart* 1.566 +nsGrid::GetPartFromBox(nsIFrame* aBox) 1.567 +{ 1.568 + if (!aBox) 1.569 + return nullptr; 1.570 + 1.571 + nsBoxLayout* layout = aBox->GetLayoutManager(); 1.572 + return layout ? layout->AsGridPart() : nullptr; 1.573 +} 1.574 + 1.575 +nsMargin 1.576 +nsGrid::GetBoxTotalMargin(nsIFrame* aBox, bool aIsHorizontal) 1.577 +{ 1.578 + nsMargin margin(0,0,0,0); 1.579 + // walk the boxes parent chain getting the border/padding/margin of our parent rows 1.580 + 1.581 + // first get the layour manager 1.582 + nsIGridPart* part = GetPartFromBox(aBox); 1.583 + if (part) 1.584 + margin = part->GetTotalMargin(aBox, aIsHorizontal); 1.585 + 1.586 + return margin; 1.587 +} 1.588 + 1.589 +/** 1.590 + * The first and last rows can be affected by <rows> tags with borders or margin 1.591 + * gets first and last rows and their indexes. 1.592 + * If it fails because there are no rows then: 1.593 + * FirstRow is nullptr 1.594 + * LastRow is nullptr 1.595 + * aFirstIndex = -1 1.596 + * aLastIndex = -1 1.597 + */ 1.598 +void 1.599 +nsGrid::GetFirstAndLastRow(nsBoxLayoutState& aState, 1.600 + int32_t& aFirstIndex, 1.601 + int32_t& aLastIndex, 1.602 + nsGridRow*& aFirstRow, 1.603 + nsGridRow*& aLastRow, 1.604 + bool aIsHorizontal) 1.605 +{ 1.606 + aFirstRow = nullptr; 1.607 + aLastRow = nullptr; 1.608 + aFirstIndex = -1; 1.609 + aLastIndex = -1; 1.610 + 1.611 + int32_t count = GetRowCount(aIsHorizontal); 1.612 + 1.613 + if (count == 0) 1.614 + return; 1.615 + 1.616 + 1.617 + // We could have collapsed columns either before or after our index. 1.618 + // they should not count. So if we are the 5th row and the first 4 are 1.619 + // collaped we become the first row. Or if we are the 9th row and 1.620 + // 10 up to the last row are collapsed we then become the last. 1.621 + 1.622 + // see if we are first 1.623 + int32_t i; 1.624 + for (i=0; i < count; i++) 1.625 + { 1.626 + nsGridRow* row = GetRowAt(i,aIsHorizontal); 1.627 + if (!row->IsCollapsed()) { 1.628 + aFirstIndex = i; 1.629 + aFirstRow = row; 1.630 + break; 1.631 + } 1.632 + } 1.633 + 1.634 + // see if we are last 1.635 + for (i=count-1; i >= 0; i--) 1.636 + { 1.637 + nsGridRow* row = GetRowAt(i,aIsHorizontal); 1.638 + if (!row->IsCollapsed()) { 1.639 + aLastIndex = i; 1.640 + aLastRow = row; 1.641 + break; 1.642 + } 1.643 + 1.644 + } 1.645 +} 1.646 + 1.647 +/** 1.648 + * A row can have a top and bottom offset. Usually this is just the top and bottom border/padding. 1.649 + * However if the row is the first or last it could be affected by the fact a column or columns could 1.650 + * have a top or bottom margin. 1.651 + */ 1.652 +void 1.653 +nsGrid::GetRowOffsets(nsBoxLayoutState& aState, int32_t aIndex, nscoord& aTop, nscoord& aBottom, bool aIsHorizontal) 1.654 +{ 1.655 + 1.656 + RebuildIfNeeded(); 1.657 + 1.658 + nsGridRow* row = GetRowAt(aIndex, aIsHorizontal); 1.659 + 1.660 + if (row->IsOffsetSet()) 1.661 + { 1.662 + aTop = row->mTop; 1.663 + aBottom = row->mBottom; 1.664 + return; 1.665 + } 1.666 + 1.667 + // first get the rows top and bottom border and padding 1.668 + nsIFrame* box = row->GetBox(); 1.669 + 1.670 + // add up all the padding 1.671 + nsMargin margin(0,0,0,0); 1.672 + nsMargin border(0,0,0,0); 1.673 + nsMargin padding(0,0,0,0); 1.674 + nsMargin totalBorderPadding(0,0,0,0); 1.675 + nsMargin totalMargin(0,0,0,0); 1.676 + 1.677 + // if there is a box and it's not bogus take its 1.678 + // borders padding into account 1.679 + if (box && !row->mIsBogus) 1.680 + { 1.681 + if (!box->IsCollapsed()) 1.682 + { 1.683 + // get real border and padding. GetBorderAndPadding 1.684 + // is redefined on nsGridRowLeafFrame. If we called it here 1.685 + // we would be in finite recurson. 1.686 + box->GetBorder(border); 1.687 + box->GetPadding(padding); 1.688 + 1.689 + totalBorderPadding += border; 1.690 + totalBorderPadding += padding; 1.691 + } 1.692 + 1.693 + // if we are the first or last row 1.694 + // take into account <rows> tags around us 1.695 + // that could have borders or margins. 1.696 + // fortunately they only affect the first 1.697 + // and last row inside the <rows> tag 1.698 + 1.699 + totalMargin = GetBoxTotalMargin(box, aIsHorizontal); 1.700 + } 1.701 + 1.702 + if (aIsHorizontal) { 1.703 + row->mTop = totalBorderPadding.top; 1.704 + row->mBottom = totalBorderPadding.bottom; 1.705 + row->mTopMargin = totalMargin.top; 1.706 + row->mBottomMargin = totalMargin.bottom; 1.707 + } else { 1.708 + row->mTop = totalBorderPadding.left; 1.709 + row->mBottom = totalBorderPadding.right; 1.710 + row->mTopMargin = totalMargin.left; 1.711 + row->mBottomMargin = totalMargin.right; 1.712 + } 1.713 + 1.714 + // if we are the first or last row take into account the top and bottom borders 1.715 + // of each columns. 1.716 + 1.717 + // If we are the first row then get the largest top border/padding in 1.718 + // our columns. If that's larger than the rows top border/padding use it. 1.719 + 1.720 + // If we are the last row then get the largest bottom border/padding in 1.721 + // our columns. If that's larger than the rows bottom border/padding use it. 1.722 + int32_t firstIndex = 0; 1.723 + int32_t lastIndex = 0; 1.724 + nsGridRow* firstRow = nullptr; 1.725 + nsGridRow* lastRow = nullptr; 1.726 + GetFirstAndLastRow(aState, firstIndex, lastIndex, firstRow, lastRow, aIsHorizontal); 1.727 + 1.728 + if (aIndex == firstIndex || aIndex == lastIndex) { 1.729 + nscoord maxTop = 0; 1.730 + nscoord maxBottom = 0; 1.731 + 1.732 + // run through the columns. Look at each column 1.733 + // pick the largest top border or bottom border 1.734 + int32_t count = GetColumnCount(aIsHorizontal); 1.735 + 1.736 + for (int32_t i=0; i < count; i++) 1.737 + { 1.738 + nsMargin totalChildBorderPadding(0,0,0,0); 1.739 + 1.740 + nsGridRow* column = GetColumnAt(i,aIsHorizontal); 1.741 + nsIFrame* box = column->GetBox(); 1.742 + 1.743 + if (box) 1.744 + { 1.745 + // ignore collapsed children 1.746 + if (!box->IsCollapsed()) 1.747 + { 1.748 + // include the margin of the columns. To the row 1.749 + // at this point border/padding and margins all added 1.750 + // up to more needed space. 1.751 + margin = GetBoxTotalMargin(box, !aIsHorizontal); 1.752 + // get real border and padding. GetBorderAndPadding 1.753 + // is redefined on nsGridRowLeafFrame. If we called it here 1.754 + // we would be in finite recurson. 1.755 + box->GetBorder(border); 1.756 + box->GetPadding(padding); 1.757 + totalChildBorderPadding += border; 1.758 + totalChildBorderPadding += padding; 1.759 + totalChildBorderPadding += margin; 1.760 + } 1.761 + 1.762 + nscoord top; 1.763 + nscoord bottom; 1.764 + 1.765 + // pick the largest top margin 1.766 + if (aIndex == firstIndex) { 1.767 + if (aIsHorizontal) { 1.768 + top = totalChildBorderPadding.top; 1.769 + } else { 1.770 + top = totalChildBorderPadding.left; 1.771 + } 1.772 + if (top > maxTop) 1.773 + maxTop = top; 1.774 + } 1.775 + 1.776 + // pick the largest bottom margin 1.777 + if (aIndex == lastIndex) { 1.778 + if (aIsHorizontal) { 1.779 + bottom = totalChildBorderPadding.bottom; 1.780 + } else { 1.781 + bottom = totalChildBorderPadding.right; 1.782 + } 1.783 + if (bottom > maxBottom) 1.784 + maxBottom = bottom; 1.785 + } 1.786 + 1.787 + } 1.788 + 1.789 + // If the biggest top border/padding the columns is larger than this rows top border/padding 1.790 + // the use it. 1.791 + if (aIndex == firstIndex) { 1.792 + if (maxTop > (row->mTop + row->mTopMargin)) 1.793 + row->mTop = maxTop - row->mTopMargin; 1.794 + } 1.795 + 1.796 + // If the biggest bottom border/padding the columns is larger than this rows bottom border/padding 1.797 + // the use it. 1.798 + if (aIndex == lastIndex) { 1.799 + if (maxBottom > (row->mBottom + row->mBottomMargin)) 1.800 + row->mBottom = maxBottom - row->mBottomMargin; 1.801 + } 1.802 + } 1.803 + } 1.804 + 1.805 + aTop = row->mTop; 1.806 + aBottom = row->mBottom; 1.807 +} 1.808 + 1.809 +/** 1.810 + * These methods return the preferred, min, max coord for a given row index if 1.811 + * aIsHorizontal is true. If you pass false you will get the inverse. 1.812 + * As if you called GetPrefColumnHeight(aState, index, aPref). 1.813 + */ 1.814 +nscoord 1.815 +nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal) 1.816 +{ 1.817 + RebuildIfNeeded(); 1.818 + 1.819 + nsGridRow* row = GetRowAt(aIndex, aIsHorizontal); 1.820 + 1.821 + if (row->IsCollapsed()) 1.822 + return 0; 1.823 + 1.824 + if (row->IsPrefSet()) 1.825 + return row->mPref; 1.826 + 1.827 + nsIFrame* box = row->mBox; 1.828 + 1.829 + // set in CSS? 1.830 + if (box) 1.831 + { 1.832 + bool widthSet, heightSet; 1.833 + nsSize cssSize(-1, -1); 1.834 + nsIFrame::AddCSSPrefSize(box, cssSize, widthSet, heightSet); 1.835 + 1.836 + row->mPref = GET_HEIGHT(cssSize, aIsHorizontal); 1.837 + 1.838 + // yep do nothing. 1.839 + if (row->mPref != -1) 1.840 + return row->mPref; 1.841 + } 1.842 + 1.843 + // get the offsets so they are cached. 1.844 + nscoord top; 1.845 + nscoord bottom; 1.846 + GetRowOffsets(aState, aIndex, top, bottom, aIsHorizontal); 1.847 + 1.848 + // is the row bogus? If so then just ask it for its size 1.849 + // it should not be affected by cells in the grid. 1.850 + if (row->mIsBogus) 1.851 + { 1.852 + nsSize size(0,0); 1.853 + if (box) 1.854 + { 1.855 + size = box->GetPrefSize(aState); 1.856 + nsBox::AddMargin(box, size); 1.857 + nsGridLayout2::AddOffset(aState, box, size); 1.858 + } 1.859 + 1.860 + row->mPref = GET_HEIGHT(size, aIsHorizontal); 1.861 + return row->mPref; 1.862 + } 1.863 + 1.864 + nsSize size(0,0); 1.865 + 1.866 + nsGridCell* child; 1.867 + 1.868 + int32_t count = GetColumnCount(aIsHorizontal); 1.869 + 1.870 + for (int32_t i=0; i < count; i++) 1.871 + { 1.872 + if (aIsHorizontal) 1.873 + child = GetCellAt(i,aIndex); 1.874 + else 1.875 + child = GetCellAt(aIndex,i); 1.876 + 1.877 + // ignore collapsed children 1.878 + if (!child->IsCollapsed()) 1.879 + { 1.880 + nsSize childSize = child->GetPrefSize(aState); 1.881 + 1.882 + nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal); 1.883 + } 1.884 + } 1.885 + 1.886 + row->mPref = GET_HEIGHT(size, aIsHorizontal) + top + bottom; 1.887 + 1.888 + return row->mPref; 1.889 +} 1.890 + 1.891 +nscoord 1.892 +nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal) 1.893 +{ 1.894 + RebuildIfNeeded(); 1.895 + 1.896 + nsGridRow* row = GetRowAt(aIndex, aIsHorizontal); 1.897 + 1.898 + if (row->IsCollapsed()) 1.899 + return 0; 1.900 + 1.901 + if (row->IsMinSet()) 1.902 + return row->mMin; 1.903 + 1.904 + nsIFrame* box = row->mBox; 1.905 + 1.906 + // set in CSS? 1.907 + if (box) { 1.908 + bool widthSet, heightSet; 1.909 + nsSize cssSize(-1, -1); 1.910 + nsIFrame::AddCSSMinSize(aState, box, cssSize, widthSet, heightSet); 1.911 + 1.912 + row->mMin = GET_HEIGHT(cssSize, aIsHorizontal); 1.913 + 1.914 + // yep do nothing. 1.915 + if (row->mMin != -1) 1.916 + return row->mMin; 1.917 + } 1.918 + 1.919 + // get the offsets so they are cached. 1.920 + nscoord top; 1.921 + nscoord bottom; 1.922 + GetRowOffsets(aState, aIndex, top, bottom, aIsHorizontal); 1.923 + 1.924 + // is the row bogus? If so then just ask it for its size 1.925 + // it should not be affected by cells in the grid. 1.926 + if (row->mIsBogus) 1.927 + { 1.928 + nsSize size(0,0); 1.929 + if (box) { 1.930 + size = box->GetPrefSize(aState); 1.931 + nsBox::AddMargin(box, size); 1.932 + nsGridLayout2::AddOffset(aState, box, size); 1.933 + } 1.934 + 1.935 + row->mMin = GET_HEIGHT(size, aIsHorizontal) + top + bottom; 1.936 + return row->mMin; 1.937 + } 1.938 + 1.939 + nsSize size(0,0); 1.940 + 1.941 + nsGridCell* child; 1.942 + 1.943 + int32_t count = GetColumnCount(aIsHorizontal); 1.944 + 1.945 + for (int32_t i=0; i < count; i++) 1.946 + { 1.947 + if (aIsHorizontal) 1.948 + child = GetCellAt(i,aIndex); 1.949 + else 1.950 + child = GetCellAt(aIndex,i); 1.951 + 1.952 + // ignore collapsed children 1.953 + if (!child->IsCollapsed()) 1.954 + { 1.955 + nsSize childSize = child->GetMinSize(aState); 1.956 + 1.957 + nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal); 1.958 + } 1.959 + } 1.960 + 1.961 + row->mMin = GET_HEIGHT(size, aIsHorizontal); 1.962 + 1.963 + return row->mMin; 1.964 +} 1.965 + 1.966 +nscoord 1.967 +nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal) 1.968 +{ 1.969 + RebuildIfNeeded(); 1.970 + 1.971 + nsGridRow* row = GetRowAt(aIndex, aIsHorizontal); 1.972 + 1.973 + if (row->IsCollapsed()) 1.974 + return 0; 1.975 + 1.976 + if (row->IsMaxSet()) 1.977 + return row->mMax; 1.978 + 1.979 + nsIFrame* box = row->mBox; 1.980 + 1.981 + // set in CSS? 1.982 + if (box) { 1.983 + bool widthSet, heightSet; 1.984 + nsSize cssSize(-1, -1); 1.985 + nsIFrame::AddCSSMaxSize(box, cssSize, widthSet, heightSet); 1.986 + 1.987 + row->mMax = GET_HEIGHT(cssSize, aIsHorizontal); 1.988 + 1.989 + // yep do nothing. 1.990 + if (row->mMax != -1) 1.991 + return row->mMax; 1.992 + } 1.993 + 1.994 + // get the offsets so they are cached. 1.995 + nscoord top; 1.996 + nscoord bottom; 1.997 + GetRowOffsets(aState, aIndex, top, bottom, aIsHorizontal); 1.998 + 1.999 + // is the row bogus? If so then just ask it for its size 1.1000 + // it should not be affected by cells in the grid. 1.1001 + if (row->mIsBogus) 1.1002 + { 1.1003 + nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE); 1.1004 + if (box) { 1.1005 + size = box->GetPrefSize(aState); 1.1006 + nsBox::AddMargin(box, size); 1.1007 + nsGridLayout2::AddOffset(aState, box, size); 1.1008 + } 1.1009 + 1.1010 + row->mMax = GET_HEIGHT(size, aIsHorizontal); 1.1011 + return row->mMax; 1.1012 + } 1.1013 + 1.1014 + nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE); 1.1015 + 1.1016 + nsGridCell* child; 1.1017 + 1.1018 + int32_t count = GetColumnCount(aIsHorizontal); 1.1019 + 1.1020 + for (int32_t i=0; i < count; i++) 1.1021 + { 1.1022 + if (aIsHorizontal) 1.1023 + child = GetCellAt(i,aIndex); 1.1024 + else 1.1025 + child = GetCellAt(aIndex,i); 1.1026 + 1.1027 + // ignore collapsed children 1.1028 + if (!child->IsCollapsed()) 1.1029 + { 1.1030 + nsSize min = child->GetMinSize(aState); 1.1031 + nsSize childSize = nsBox::BoundsCheckMinMax(min, child->GetMaxSize(aState)); 1.1032 + nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal); 1.1033 + } 1.1034 + } 1.1035 + 1.1036 + row->mMax = GET_HEIGHT(size, aIsHorizontal) + top + bottom; 1.1037 + 1.1038 + return row->mMax; 1.1039 +} 1.1040 + 1.1041 +bool 1.1042 +nsGrid::IsGrid(nsIFrame* aBox) 1.1043 +{ 1.1044 + nsIGridPart* part = GetPartFromBox(aBox); 1.1045 + if (!part) 1.1046 + return false; 1.1047 + 1.1048 + nsGridLayout2* grid = part->CastToGridLayout(); 1.1049 + 1.1050 + if (grid) 1.1051 + return true; 1.1052 + 1.1053 + return false; 1.1054 +} 1.1055 + 1.1056 +/** 1.1057 + * This get the flexibilty of the row at aIndex. It's not trivial. There are a few 1.1058 + * things we need to look at. Specifically we need to see if any <rows> or <columns> 1.1059 + * tags are around us. Their flexibilty will affect ours. 1.1060 + */ 1.1061 +nscoord 1.1062 +nsGrid::GetRowFlex(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal) 1.1063 +{ 1.1064 + RebuildIfNeeded(); 1.1065 + 1.1066 + nsGridRow* row = GetRowAt(aIndex, aIsHorizontal); 1.1067 + 1.1068 + if (row->IsFlexSet()) 1.1069 + return row->mFlex; 1.1070 + 1.1071 + nsIFrame* box = row->mBox; 1.1072 + row->mFlex = 0; 1.1073 + 1.1074 + if (box) { 1.1075 + 1.1076 + // We need our flex but a inflexible row could be around us. If so 1.1077 + // neither are we. However if its the row tag just inside the grid it won't 1.1078 + // affect us. We need to do this for this case: 1.1079 + // <grid> 1.1080 + // <rows> 1.1081 + // <rows> // this is not flexible. So our children should not be flexible 1.1082 + // <row flex="1"/> 1.1083 + // <row flex="1"/> 1.1084 + // </rows> 1.1085 + // <row/> 1.1086 + // </rows> 1.1087 + // </grid> 1.1088 + // 1.1089 + // or.. 1.1090 + // 1.1091 + // <grid> 1.1092 + // <rows> 1.1093 + // <rows> // this is not flexible. So our children should not be flexible 1.1094 + // <rows flex="1"> 1.1095 + // <row flex="1"/> 1.1096 + // <row flex="1"/> 1.1097 + // </rows> 1.1098 + // <row/> 1.1099 + // </rows> 1.1100 + // </row> 1.1101 + // </grid> 1.1102 + 1.1103 + 1.1104 + // So here is how it looks 1.1105 + // 1.1106 + // <grid> 1.1107 + // <rows> // parentsParent 1.1108 + // <rows> // parent 1.1109 + // <row flex="1"/> 1.1110 + // <row flex="1"/> 1.1111 + // </rows> 1.1112 + // <row/> 1.1113 + // </rows> 1.1114 + // </grid> 1.1115 + 1.1116 + // so the answer is simple: 1) Walk our parent chain. 2) If we find 1.1117 + // someone who is not flexible and they aren't the rows immediately in 1.1118 + // the grid. 3) Then we are not flexible 1.1119 + 1.1120 + box = GetScrollBox(box); 1.1121 + nsIFrame* parent = box->GetParentBox(); 1.1122 + nsIFrame* parentsParent=nullptr; 1.1123 + 1.1124 + while(parent) 1.1125 + { 1.1126 + parent = GetScrollBox(parent); 1.1127 + parentsParent = parent->GetParentBox(); 1.1128 + 1.1129 + // if our parents parent is not a grid 1.1130 + // the get its flex. If its 0 then we are 1.1131 + // not flexible. 1.1132 + if (parentsParent) { 1.1133 + if (!IsGrid(parentsParent)) { 1.1134 + nscoord flex = parent->GetFlex(aState); 1.1135 + nsIFrame::AddCSSFlex(aState, parent, flex); 1.1136 + if (flex == 0) { 1.1137 + row->mFlex = 0; 1.1138 + return row->mFlex; 1.1139 + } 1.1140 + } else 1.1141 + break; 1.1142 + } 1.1143 + 1.1144 + parent = parentsParent; 1.1145 + } 1.1146 + 1.1147 + // get the row flex. 1.1148 + row->mFlex = box->GetFlex(aState); 1.1149 + nsIFrame::AddCSSFlex(aState, box, row->mFlex); 1.1150 + } 1.1151 + 1.1152 + return row->mFlex; 1.1153 +} 1.1154 + 1.1155 +void 1.1156 +nsGrid::SetLargestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal) 1.1157 +{ 1.1158 + if (aIsHorizontal) { 1.1159 + if (aSize.height < aHeight) 1.1160 + aSize.height = aHeight; 1.1161 + } else { 1.1162 + if (aSize.width < aHeight) 1.1163 + aSize.width = aHeight; 1.1164 + } 1.1165 +} 1.1166 + 1.1167 +void 1.1168 +nsGrid::SetSmallestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal) 1.1169 +{ 1.1170 + if (aIsHorizontal) { 1.1171 + if (aSize.height > aHeight) 1.1172 + aSize.height = aHeight; 1.1173 + } else { 1.1174 + if (aSize.width < aHeight) 1.1175 + aSize.width = aHeight; 1.1176 + } 1.1177 +} 1.1178 + 1.1179 +int32_t 1.1180 +nsGrid::GetRowCount(int32_t aIsHorizontal) 1.1181 +{ 1.1182 + RebuildIfNeeded(); 1.1183 + 1.1184 + if (aIsHorizontal) 1.1185 + return mRowCount; 1.1186 + else 1.1187 + return mColumnCount; 1.1188 +} 1.1189 + 1.1190 +int32_t 1.1191 +nsGrid::GetColumnCount(int32_t aIsHorizontal) 1.1192 +{ 1.1193 + return GetRowCount(!aIsHorizontal); 1.1194 +} 1.1195 + 1.1196 +/* 1.1197 + * A cell in the given row or columns at the given index has had a child added or removed 1.1198 + */ 1.1199 +void 1.1200 +nsGrid::CellAddedOrRemoved(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal) 1.1201 +{ 1.1202 + // TBD see if the cell will fit in our current row. If it will 1.1203 + // just add it in. 1.1204 + // but for now rebuild everything. 1.1205 + if (mMarkingDirty) 1.1206 + return; 1.1207 + 1.1208 + NeedsRebuild(aState); 1.1209 +} 1.1210 + 1.1211 +/** 1.1212 + * A row or columns at the given index had been added or removed 1.1213 + */ 1.1214 +void 1.1215 +nsGrid::RowAddedOrRemoved(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal) 1.1216 +{ 1.1217 + // TBD see if we have extra room in the table and just add the new row in 1.1218 + // for now rebuild the world 1.1219 + if (mMarkingDirty) 1.1220 + return; 1.1221 + 1.1222 + NeedsRebuild(aState); 1.1223 +} 1.1224 + 1.1225 +/* 1.1226 + * Scrollframes are tranparent. If this is given a scrollframe is will return the 1.1227 + * frame inside. If there is no scrollframe it does nothing. 1.1228 + */ 1.1229 +nsIFrame* 1.1230 +nsGrid::GetScrolledBox(nsIFrame* aChild) 1.1231 +{ 1.1232 + // first see if it is a scrollframe. If so walk down into it and get the scrolled child 1.1233 + nsIScrollableFrame *scrollFrame = do_QueryFrame(aChild); 1.1234 + if (scrollFrame) { 1.1235 + nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame(); 1.1236 + NS_ASSERTION(scrolledFrame,"Error no scroll frame!!"); 1.1237 + return scrolledFrame; 1.1238 + } 1.1239 + 1.1240 + return aChild; 1.1241 +} 1.1242 + 1.1243 +/* 1.1244 + * Scrollframes are tranparent. If this is given a child in a scrollframe is will return the 1.1245 + * scrollframe ourside it. If there is no scrollframe it does nothing. 1.1246 + */ 1.1247 +nsIFrame* 1.1248 +nsGrid::GetScrollBox(nsIFrame* aChild) 1.1249 +{ 1.1250 + if (!aChild) 1.1251 + return nullptr; 1.1252 + 1.1253 + // get parent 1.1254 + nsIFrame* parent = aChild->GetParentBox(); 1.1255 + 1.1256 + // walk up until we find a scrollframe or a part 1.1257 + // if it's a scrollframe return it. 1.1258 + // if it's a parent then the child passed does not 1.1259 + // have a scroll frame immediately wrapped around it. 1.1260 + while (parent) { 1.1261 + nsIScrollableFrame *scrollFrame = do_QueryFrame(parent); 1.1262 + // scrollframe? Yep return it. 1.1263 + if (scrollFrame) 1.1264 + return parent; 1.1265 + 1.1266 + nsCOMPtr<nsIGridPart> parentGridRow = GetPartFromBox(parent); 1.1267 + // if a part then just return the child 1.1268 + if (parentGridRow) 1.1269 + break; 1.1270 + 1.1271 + parent = parent->GetParentBox(); 1.1272 + } 1.1273 + 1.1274 + return aChild; 1.1275 +} 1.1276 + 1.1277 + 1.1278 + 1.1279 +#ifdef DEBUG_grid 1.1280 +void 1.1281 +nsGrid::PrintCellMap() 1.1282 +{ 1.1283 + 1.1284 + printf("-----Columns------\n"); 1.1285 + for (int x=0; x < mColumnCount; x++) 1.1286 + { 1.1287 + 1.1288 + nsGridRow* column = GetColumnAt(x); 1.1289 + printf("%d(pf=%d, mn=%d, mx=%d) ", x, column->mPref, column->mMin, column->mMax); 1.1290 + } 1.1291 + 1.1292 + printf("\n-----Rows------\n"); 1.1293 + for (x=0; x < mRowCount; x++) 1.1294 + { 1.1295 + nsGridRow* column = GetRowAt(x); 1.1296 + printf("%d(pf=%d, mn=%d, mx=%d) ", x, column->mPref, column->mMin, column->mMax); 1.1297 + } 1.1298 + 1.1299 + printf("\n"); 1.1300 + 1.1301 +} 1.1302 +#endif