LCOV - code coverage report
Current view: top level - layout/xul/grid - nsGrid.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 477 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
       6             : //
       7             : // Eric Vaughan
       8             : // Netscape Communications
       9             : //
      10             : // See documentation in associated header file
      11             : //
      12             : 
      13             : #include "nsGrid.h"
      14             : #include "nsGridRowGroupLayout.h"
      15             : #include "nsBox.h"
      16             : #include "nsIScrollableFrame.h"
      17             : #include "nsSprocketLayout.h"
      18             : #include "nsGridLayout2.h"
      19             : #include "nsGridRow.h"
      20             : #include "nsGridCell.h"
      21             : #include "mozilla/ReflowInput.h"
      22             : 
      23             : /*
      24             : The grid control expands the idea of boxes from 1 dimension to 2 dimensions.
      25             : It works by allowing the XUL to define a collection of rows and columns and then
      26             : stacking them on top of each other. Here is and example.
      27             : 
      28             : Example 1:
      29             : 
      30             : <grid>
      31             :    <columns>
      32             :       <column/>
      33             :       <column/>
      34             :    </columns>
      35             : 
      36             :    <rows>
      37             :       <row/>
      38             :       <row/>
      39             :    </rows>
      40             : </grid>
      41             : 
      42             : example 2:
      43             : 
      44             : <grid>
      45             :    <columns>
      46             :       <column flex="1"/>
      47             :       <column flex="1"/>
      48             :    </columns>
      49             : 
      50             :    <rows>
      51             :       <row>
      52             :          <text value="hello"/>
      53             :          <text value="there"/>
      54             :       </row>
      55             :    </rows>
      56             : </grid>
      57             : 
      58             : example 3:
      59             : 
      60             : <grid>
      61             : 
      62             : <rows>
      63             :       <row>
      64             :          <text value="hello"/>
      65             :          <text value="there"/>
      66             :       </row>
      67             :    </rows>
      68             : 
      69             :    <columns>
      70             :       <column>
      71             :          <text value="Hey I'm in the column and I'm on top!"/>
      72             :       </column>
      73             :       <column/>
      74             :    </columns>
      75             : 
      76             : </grid>
      77             : 
      78             : Usually the columns are first and the rows are second, so the rows will be drawn on top of the columns.
      79             : You can reverse this by defining the rows first.
      80             : Other tags are then placed in the <row> or <column> tags causing the grid to accommodate everyone.
      81             : It does this by creating 3 things: A cellmap, a row list, and a column list. The cellmap is a 2
      82             : dimensional array of nsGridCells. Each cell contains 2 boxes.  One cell from the column list
      83             : and one from the row list. When a cell is asked for its size it returns that smallest size it can
      84             : be to accommodate the 2 cells. Row lists and Column lists use the same data structure: nsGridRow.
      85             : Essentially a row and column are the same except a row goes alone the x axis and a column the y.
      86             : To make things easier and save code everything is written in terms of the x dimension. A flag is
      87             : passed in called "isHorizontal" that can flip the calculations to the y axis.
      88             : 
      89             : Usually the number of cells in a row match the number of columns, but not always.
      90             : It is possible to define 5 columns for a grid but have 10 cells in one of the rows.
      91             : In this case 5 extra columns will be added to the column list to handle the situation.
      92             : These are called extraColumns/Rows.
      93             : */
      94             : 
      95             : using namespace mozilla;
      96             : 
      97           0 : nsGrid::nsGrid():mBox(nullptr),
      98             :                  mRowsBox(nullptr),
      99             :                  mColumnsBox(nullptr),
     100             :                  mNeedsRebuild(true),
     101             :                  mRowCount(0),
     102             :                  mColumnCount(0),
     103             :                  mExtraRowCount(0),
     104             :                  mExtraColumnCount(0),
     105           0 :                  mMarkingDirty(false)
     106             : {
     107           0 :     MOZ_COUNT_CTOR(nsGrid);
     108           0 : }
     109             : 
     110           0 : nsGrid::~nsGrid()
     111             : {
     112           0 :     FreeMap();
     113           0 :     MOZ_COUNT_DTOR(nsGrid);
     114           0 : }
     115             : 
     116             : /*
     117             :  * This is called whenever something major happens in the grid. And example
     118             :  * might be when many cells or row are added. It sets a flag signaling that
     119             :  * all the grids caches information should be recalculated.
     120             :  */
     121             : void
     122           0 : nsGrid::NeedsRebuild(nsBoxLayoutState& aState)
     123             : {
     124           0 :   if (mNeedsRebuild)
     125           0 :     return;
     126             : 
     127             :   // iterate through columns and rows and dirty them
     128           0 :   mNeedsRebuild = true;
     129             : 
     130             :   // find the new row and column box. They could have
     131             :   // been changed.
     132           0 :   mRowsBox = nullptr;
     133           0 :   mColumnsBox = nullptr;
     134           0 :   FindRowsAndColumns(&mRowsBox, &mColumnsBox);
     135             : 
     136             :   // tell all the rows and columns they are dirty
     137           0 :   DirtyRows(mRowsBox, aState);
     138           0 :   DirtyRows(mColumnsBox, aState);
     139             : }
     140             : 
     141             : 
     142             : 
     143             : /**
     144             :  * If we are marked for rebuild. Then build everything
     145             :  */
     146             : void
     147           0 : nsGrid::RebuildIfNeeded()
     148             : {
     149           0 :   if (!mNeedsRebuild)
     150           0 :     return;
     151             : 
     152           0 :   mNeedsRebuild = false;
     153             : 
     154             :   // find the row and columns frames
     155           0 :   FindRowsAndColumns(&mRowsBox, &mColumnsBox);
     156             : 
     157             :   // count the rows and columns
     158           0 :   int32_t computedRowCount = 0;
     159           0 :   int32_t computedColumnCount = 0;
     160           0 :   int32_t rowCount = 0;
     161           0 :   int32_t columnCount = 0;
     162             : 
     163           0 :   CountRowsColumns(mRowsBox, rowCount, computedColumnCount);
     164           0 :   CountRowsColumns(mColumnsBox, columnCount, computedRowCount);
     165             : 
     166             :   // computedRowCount are the actual number of rows as determined by the
     167             :   // columns children.
     168             :   // computedColumnCount are the number of columns as determined by the number
     169             :   // of rows children.
     170             :   // We can use this information to see how many extra columns or rows we need.
     171             :   // This can happen if there are are more children in a row that number of columns
     172             :   // defined. Example:
     173             :   //
     174             :   // <columns>
     175             :   //   <column/>
     176             :   // </columns>
     177             :   //
     178             :   // <rows>
     179             :   //   <row>
     180             :   //     <button/><button/>
     181             :   //   </row>
     182             :   // </rows>
     183             :   //
     184             :   // computedColumnCount = 2 // for the 2 buttons in the row tag
     185             :   // computedRowCount = 0 // there is nothing in the  column tag
     186             :   // mColumnCount = 1 // one column defined
     187             :   // mRowCount = 1 // one row defined
     188             :   //
     189             :   // So in this case we need to make 1 extra column.
     190             :   //
     191             : 
     192             :   // Make sure to update mExtraColumnCount no matter what, since it might
     193             :   // happen that we now have as many columns as are defined, and we wouldn't
     194             :   // want to have a positive mExtraColumnCount hanging about in that case!
     195           0 :   mExtraColumnCount = computedColumnCount - columnCount;
     196           0 :   if (computedColumnCount > columnCount) {
     197           0 :      columnCount = computedColumnCount;
     198             :   }
     199             : 
     200             :   // Same for rows.
     201           0 :   mExtraRowCount = computedRowCount - rowCount;
     202           0 :   if (computedRowCount > rowCount) {
     203           0 :      rowCount = computedRowCount;
     204             :   }
     205             : 
     206             :   // build and poplulate row and columns arrays
     207           0 :   mRows = BuildRows(mRowsBox, rowCount, true);
     208           0 :   mColumns = BuildRows(mColumnsBox, columnCount, false);
     209             : 
     210             :   // build and populate the cell map
     211           0 :   mCellMap = BuildCellMap(rowCount, columnCount);
     212             : 
     213           0 :   mRowCount = rowCount;
     214           0 :   mColumnCount = columnCount;
     215             : 
     216             :   // populate the cell map from column and row children
     217           0 :   PopulateCellMap(mRows.get(), mColumns.get(), mRowCount, mColumnCount, true);
     218           0 :   PopulateCellMap(mColumns.get(), mRows.get(), mColumnCount, mRowCount, false);
     219             : }
     220             : 
     221             : void
     222           0 : nsGrid::FreeMap()
     223             : {
     224           0 :   mRows = nullptr;
     225           0 :   mColumns = nullptr;
     226           0 :   mCellMap = nullptr;
     227           0 :   mColumnCount = 0;
     228           0 :   mRowCount = 0;
     229           0 :   mExtraColumnCount = 0;
     230           0 :   mExtraRowCount = 0;
     231           0 :   mRowsBox = nullptr;
     232           0 :   mColumnsBox = nullptr;
     233           0 : }
     234             : 
     235             : /**
     236             :  * finds the first <rows> and <columns> tags in the <grid> tag
     237             :  */
     238             : void
     239           0 : nsGrid::FindRowsAndColumns(nsIFrame** aRows, nsIFrame** aColumns)
     240             : {
     241           0 :   *aRows = nullptr;
     242           0 :   *aColumns = nullptr;
     243             : 
     244             :   // find the boxes that contain our rows and columns
     245           0 :   nsIFrame* child = nullptr;
     246             :   // if we have <grid></grid> then mBox will be null (bug 125689)
     247           0 :   if (mBox)
     248           0 :     child = nsBox::GetChildXULBox(mBox);
     249             : 
     250           0 :   while(child)
     251             :   {
     252           0 :     nsIFrame* oldBox = child;
     253           0 :     nsIScrollableFrame *scrollFrame = do_QueryFrame(child);
     254           0 :     if (scrollFrame) {
     255           0 :        nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame();
     256           0 :        NS_ASSERTION(scrolledFrame,"Error no scroll frame!!");
     257           0 :        child = do_QueryFrame(scrolledFrame);
     258             :     }
     259             : 
     260           0 :     nsCOMPtr<nsIGridPart> monument = GetPartFromBox(child);
     261           0 :     if (monument)
     262             :     {
     263           0 :       nsGridRowGroupLayout* rowGroup = monument->CastToRowGroupLayout();
     264           0 :       if (rowGroup) {
     265           0 :          bool isHorizontal = !nsSprocketLayout::IsXULHorizontal(child);
     266           0 :          if (isHorizontal)
     267           0 :            *aRows = child;
     268             :          else
     269           0 :            *aColumns = child;
     270             : 
     271           0 :          if (*aRows && *aColumns)
     272           0 :            return;
     273             :       }
     274             :     }
     275             : 
     276           0 :     if (scrollFrame) {
     277           0 :       child = oldBox;
     278             :     }
     279             : 
     280           0 :     child = nsBox::GetNextXULBox(child);
     281             :   }
     282             : }
     283             : 
     284             : /**
     285             :  * Count the number of rows and columns in the given box. aRowCount well become the actual number
     286             :  * rows defined in the xul. aComputedColumnCount will become the number of columns by counting the number
     287             :  * of cells in each row.
     288             :  */
     289             : void
     290           0 : nsGrid::CountRowsColumns(nsIFrame* aRowBox, int32_t& aRowCount, int32_t& aComputedColumnCount)
     291             : {
     292           0 :   aRowCount = 0;
     293           0 :   aComputedColumnCount = 0;
     294             :   // get the rowboxes layout manager. Then ask it to do the work for us
     295           0 :   if (aRowBox) {
     296           0 :     nsCOMPtr<nsIGridPart> monument = GetPartFromBox(aRowBox);
     297           0 :     if (monument)
     298           0 :        monument->CountRowsColumns(aRowBox, aRowCount, aComputedColumnCount);
     299             :   }
     300           0 : }
     301             : 
     302             : 
     303             : /**
     304             :  * Given the number of rows create nsGridRow objects for them and full them out.
     305             :  */
     306             : UniquePtr<nsGridRow[]>
     307           0 : nsGrid::BuildRows(nsIFrame* aBox, int32_t aRowCount, bool aIsHorizontal)
     308             : {
     309             :   // if no rows then return null
     310           0 :   if (aRowCount == 0) {
     311           0 :     return nullptr;
     312             :   }
     313             : 
     314             :   // create the array
     315           0 :   UniquePtr<nsGridRow[]> row;
     316             : 
     317             :   // only create new rows if we have to. Reuse old rows.
     318           0 :   if (aIsHorizontal)
     319             :   {
     320           0 :     if (aRowCount > mRowCount) {
     321           0 :        row = MakeUnique<nsGridRow[]>(aRowCount);
     322             :     } else {
     323           0 :       for (int32_t i=0; i < mRowCount; i++)
     324           0 :         mRows[i].Init(nullptr, false);
     325             : 
     326           0 :       row = Move(mRows);
     327             :     }
     328             :   } else {
     329           0 :     if (aRowCount > mColumnCount) {
     330           0 :        row = MakeUnique<nsGridRow[]>(aRowCount);
     331             :     } else {
     332           0 :        for (int32_t i=0; i < mColumnCount; i++)
     333           0 :          mColumns[i].Init(nullptr, false);
     334             : 
     335           0 :        row = Move(mColumns);
     336             :     }
     337             :   }
     338             : 
     339             :   // populate it if we can. If not it will contain only dynamic columns
     340           0 :   if (aBox)
     341             :   {
     342           0 :     nsCOMPtr<nsIGridPart> monument = GetPartFromBox(aBox);
     343           0 :     if (monument) {
     344           0 :        monument->BuildRows(aBox, row.get());
     345             :     }
     346             :   }
     347             : 
     348           0 :   return row;
     349             : }
     350             : 
     351             : 
     352             : /**
     353             :  * Given the number of rows and columns. Build a cellmap
     354             :  */
     355             : UniquePtr<nsGridCell[]>
     356           0 : nsGrid::BuildCellMap(int32_t aRows, int32_t aColumns)
     357             : {
     358           0 :   int32_t size = aRows*aColumns;
     359           0 :   int32_t oldsize = mRowCount*mColumnCount;
     360           0 :   if (size == 0) {
     361           0 :     return nullptr;
     362             :   }
     363             : 
     364           0 :   if (size > oldsize) {
     365           0 :     return MakeUnique<nsGridCell[]>(size);
     366             :   }
     367             : 
     368             :   // clear out cellmap
     369           0 :   for (int32_t i=0; i < oldsize; i++) {
     370           0 :     mCellMap[i].SetBoxInRow(nullptr);
     371           0 :     mCellMap[i].SetBoxInColumn(nullptr);
     372             :   }
     373           0 :   return Move(mCellMap);
     374             : }
     375             : 
     376             : /**
     377             :  * Run through all the cells in the rows and columns and populate then with 2 cells. One from the row and one
     378             :  * from the column
     379             :  */
     380             : void
     381           0 : nsGrid::PopulateCellMap(nsGridRow* aRows, nsGridRow* aColumns, int32_t aRowCount, int32_t aColumnCount, bool aIsHorizontal)
     382             : {
     383           0 :   if (!aRows)
     384           0 :     return;
     385             : 
     386             :    // look through the columns
     387           0 :   int32_t j = 0;
     388             : 
     389           0 :   for(int32_t i=0; i < aRowCount; i++)
     390             :   {
     391           0 :      nsIFrame* child = nullptr;
     392           0 :      nsGridRow* row = &aRows[i];
     393             : 
     394             :      // skip bogus rows. They have no cells
     395           0 :      if (row->mIsBogus)
     396           0 :        continue;
     397             : 
     398           0 :      child = row->mBox;
     399           0 :      if (child) {
     400           0 :        child = nsBox::GetChildXULBox(child);
     401             : 
     402           0 :        j = 0;
     403             : 
     404           0 :        while(child && j < aColumnCount)
     405             :        {
     406             :          // skip bogus column. They have no cells
     407           0 :          nsGridRow* column = &aColumns[j];
     408           0 :          if (column->mIsBogus)
     409             :          {
     410           0 :            j++;
     411           0 :            continue;
     412             :          }
     413             : 
     414           0 :          if (aIsHorizontal)
     415           0 :            GetCellAt(j,i)->SetBoxInRow(child);
     416             :          else
     417           0 :            GetCellAt(i,j)->SetBoxInColumn(child);
     418             : 
     419           0 :          child = nsBox::GetNextXULBox(child);
     420             : 
     421           0 :          j++;
     422             :        }
     423             :      }
     424             :   }
     425             : }
     426             : 
     427             : /**
     428             :  * Run through the rows in the given box and mark them dirty so they
     429             :  * will get recalculated and get a layout.
     430             :  */
     431             : void
     432           0 : nsGrid::DirtyRows(nsIFrame* aRowBox, nsBoxLayoutState& aState)
     433             : {
     434             :   // make sure we prevent others from dirtying things.
     435           0 :   mMarkingDirty = true;
     436             : 
     437             :   // if the box is a grid part have it recursively hand it.
     438           0 :   if (aRowBox) {
     439           0 :     nsCOMPtr<nsIGridPart> part = GetPartFromBox(aRowBox);
     440           0 :     if (part)
     441           0 :        part->DirtyRows(aRowBox, aState);
     442             :   }
     443             : 
     444           0 :   mMarkingDirty = false;
     445           0 : }
     446             : 
     447             : nsGridRow*
     448           0 : nsGrid::GetColumnAt(int32_t aIndex, bool aIsHorizontal)
     449             : {
     450           0 :   return GetRowAt(aIndex, !aIsHorizontal);
     451             : }
     452             : 
     453             : nsGridRow*
     454           0 : nsGrid::GetRowAt(int32_t aIndex, bool aIsHorizontal)
     455             : {
     456           0 :   RebuildIfNeeded();
     457             : 
     458           0 :   if (aIsHorizontal) {
     459           0 :     NS_ASSERTION(aIndex < mRowCount && aIndex >= 0, "Index out of range");
     460           0 :     return &mRows[aIndex];
     461             :   } else {
     462           0 :     NS_ASSERTION(aIndex < mColumnCount && aIndex >= 0, "Index out of range");
     463           0 :     return &mColumns[aIndex];
     464             :   }
     465             : }
     466             : 
     467             : nsGridCell*
     468           0 : nsGrid::GetCellAt(int32_t aX, int32_t aY)
     469             : {
     470           0 :   RebuildIfNeeded();
     471             : 
     472           0 :   NS_ASSERTION(aY < mRowCount && aY >= 0, "Index out of range");
     473           0 :   NS_ASSERTION(aX < mColumnCount && aX >= 0, "Index out of range");
     474           0 :   return &mCellMap[aY*mColumnCount+aX];
     475             : }
     476             : 
     477             : int32_t
     478           0 : nsGrid::GetExtraColumnCount(bool aIsHorizontal)
     479             : {
     480           0 :   return GetExtraRowCount(!aIsHorizontal);
     481             : }
     482             : 
     483             : int32_t
     484           0 : nsGrid::GetExtraRowCount(bool aIsHorizontal)
     485             : {
     486           0 :   RebuildIfNeeded();
     487             : 
     488           0 :   if (aIsHorizontal)
     489           0 :     return mExtraRowCount;
     490             :   else
     491           0 :     return mExtraColumnCount;
     492             : }
     493             : 
     494             : 
     495             : /**
     496             :  * These methods return the preferred, min, max sizes for a given row index.
     497             :  * aIsHorizontal if aIsHorizontal is true. If you pass false you will get the inverse.
     498             :  * As if you called GetPrefColumnSize(aState, index, aPref)
     499             :  */
     500             : nsSize
     501           0 : nsGrid::GetPrefRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal)
     502             : {
     503           0 :   nsSize size(0,0);
     504           0 :   if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal)))
     505           0 :     return size;
     506             : 
     507           0 :   nscoord height = GetPrefRowHeight(aState, aRowIndex, aIsHorizontal);
     508           0 :   SetLargestSize(size, height, aIsHorizontal);
     509             : 
     510           0 :   return size;
     511             : }
     512             : 
     513             : nsSize
     514           0 : nsGrid::GetMinRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal)
     515             : {
     516           0 :   nsSize size(0,0);
     517           0 :   if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal)))
     518           0 :     return size;
     519             : 
     520           0 :   nscoord height = GetMinRowHeight(aState, aRowIndex, aIsHorizontal);
     521           0 :   SetLargestSize(size, height, aIsHorizontal);
     522             : 
     523           0 :   return size;
     524             : }
     525             : 
     526             : nsSize
     527           0 : nsGrid::GetMaxRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal)
     528             : {
     529           0 :   nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
     530           0 :   if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal)))
     531           0 :     return size;
     532             : 
     533           0 :   nscoord height = GetMaxRowHeight(aState, aRowIndex, aIsHorizontal);
     534           0 :   SetSmallestSize(size, height, aIsHorizontal);
     535             : 
     536           0 :   return size;
     537             : }
     538             : 
     539             : // static
     540             : nsIGridPart*
     541           0 : nsGrid::GetPartFromBox(nsIFrame* aBox)
     542             : {
     543           0 :   if (!aBox)
     544           0 :     return nullptr;
     545             : 
     546           0 :   nsBoxLayout* layout = aBox->GetXULLayoutManager();
     547           0 :   return layout ? layout->AsGridPart() : nullptr;
     548             : }
     549             : 
     550             : nsMargin
     551           0 : nsGrid::GetBoxTotalMargin(nsIFrame* aBox, bool aIsHorizontal)
     552             : {
     553           0 :   nsMargin margin(0,0,0,0);
     554             :   // walk the boxes parent chain getting the border/padding/margin of our parent rows
     555             : 
     556             :   // first get the layour manager
     557           0 :   nsIGridPart* part = GetPartFromBox(aBox);
     558           0 :   if (part)
     559           0 :     margin = part->GetTotalMargin(aBox, aIsHorizontal);
     560             : 
     561           0 :   return margin;
     562             : }
     563             : 
     564             : /**
     565             :  * The first and last rows can be affected by <rows> tags with borders or margin
     566             :  * gets first and last rows and their indexes.
     567             :  * If it fails because there are no rows then:
     568             :  * FirstRow is nullptr
     569             :  * LastRow is nullptr
     570             :  * aFirstIndex = -1
     571             :  * aLastIndex = -1
     572             :  */
     573             : void
     574           0 : nsGrid::GetFirstAndLastRow(int32_t& aFirstIndex,
     575             :                            int32_t& aLastIndex,
     576             :                            nsGridRow*& aFirstRow,
     577             :                            nsGridRow*& aLastRow,
     578             :                            bool aIsHorizontal)
     579             : {
     580           0 :   aFirstRow = nullptr;
     581           0 :   aLastRow = nullptr;
     582           0 :   aFirstIndex = -1;
     583           0 :   aLastIndex = -1;
     584             : 
     585           0 :   int32_t count = GetRowCount(aIsHorizontal);
     586             : 
     587           0 :   if (count == 0)
     588           0 :     return;
     589             : 
     590             : 
     591             :   // We could have collapsed columns either before or after our index.
     592             :   // they should not count. So if we are the 5th row and the first 4 are
     593             :   // collaped we become the first row. Or if we are the 9th row and
     594             :   // 10 up to the last row are collapsed we then become the last.
     595             : 
     596             :   // see if we are first
     597             :   int32_t i;
     598           0 :   for (i=0; i < count; i++)
     599             :   {
     600           0 :      nsGridRow* row = GetRowAt(i,aIsHorizontal);
     601           0 :      if (!row->IsXULCollapsed()) {
     602           0 :        aFirstIndex = i;
     603           0 :        aFirstRow = row;
     604           0 :        break;
     605             :      }
     606             :   }
     607             : 
     608             :   // see if we are last
     609           0 :   for (i=count-1; i >= 0; i--)
     610             :   {
     611           0 :      nsGridRow* row = GetRowAt(i,aIsHorizontal);
     612           0 :      if (!row->IsXULCollapsed()) {
     613           0 :        aLastIndex = i;
     614           0 :        aLastRow = row;
     615           0 :        break;
     616             :      }
     617             : 
     618             :   }
     619             : }
     620             : 
     621             : /**
     622             :  * A row can have a top and bottom offset. Usually this is just the top and bottom border/padding.
     623             :  * However if the row is the first or last it could be affected by the fact a column or columns could
     624             :  * have a top or bottom margin.
     625             :  */
     626             : void
     627           0 : nsGrid::GetRowOffsets(int32_t aIndex, nscoord& aTop, nscoord& aBottom, bool aIsHorizontal)
     628             : {
     629             : 
     630           0 :   RebuildIfNeeded();
     631             : 
     632           0 :   nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
     633             : 
     634           0 :   if (row->IsOffsetSet())
     635             :   {
     636           0 :     aTop    = row->mTop;
     637           0 :     aBottom = row->mBottom;
     638           0 :     return;
     639             :   }
     640             : 
     641             :   // first get the rows top and bottom border and padding
     642           0 :   nsIFrame* box = row->GetBox();
     643             : 
     644             :   // add up all the padding
     645           0 :   nsMargin margin(0,0,0,0);
     646           0 :   nsMargin border(0,0,0,0);
     647           0 :   nsMargin padding(0,0,0,0);
     648           0 :   nsMargin totalBorderPadding(0,0,0,0);
     649           0 :   nsMargin totalMargin(0,0,0,0);
     650             : 
     651             :   // if there is a box and it's not bogus take its
     652             :   // borders padding into account
     653           0 :   if (box && !row->mIsBogus)
     654             :   {
     655           0 :     if (!box->IsXULCollapsed())
     656             :     {
     657             :        // get real border and padding. GetXULBorderAndPadding
     658             :        // is redefined on nsGridRowLeafFrame. If we called it here
     659             :        // we would be in finite recurson.
     660           0 :        box->GetXULBorder(border);
     661           0 :        box->GetXULPadding(padding);
     662             : 
     663           0 :        totalBorderPadding += border;
     664           0 :        totalBorderPadding += padding;
     665             :      }
     666             : 
     667             :      // if we are the first or last row
     668             :      // take into account <rows> tags around us
     669             :      // that could have borders or margins.
     670             :      // fortunately they only affect the first
     671             :      // and last row inside the <rows> tag
     672             : 
     673           0 :      totalMargin = GetBoxTotalMargin(box, aIsHorizontal);
     674             :   }
     675             : 
     676           0 :   if (aIsHorizontal) {
     677           0 :     row->mTop = totalBorderPadding.top;
     678           0 :     row->mBottom = totalBorderPadding.bottom;
     679           0 :     row->mTopMargin = totalMargin.top;
     680           0 :     row->mBottomMargin = totalMargin.bottom;
     681             :   } else {
     682           0 :     row->mTop = totalBorderPadding.left;
     683           0 :     row->mBottom = totalBorderPadding.right;
     684           0 :     row->mTopMargin = totalMargin.left;
     685           0 :     row->mBottomMargin = totalMargin.right;
     686             :   }
     687             : 
     688             :   // if we are the first or last row take into account the top and bottom borders
     689             :   // of each columns.
     690             : 
     691             :   // If we are the first row then get the largest top border/padding in
     692             :   // our columns. If that's larger than the rows top border/padding use it.
     693             : 
     694             :   // If we are the last row then get the largest bottom border/padding in
     695             :   // our columns. If that's larger than the rows bottom border/padding use it.
     696           0 :   int32_t firstIndex = 0;
     697           0 :   int32_t lastIndex = 0;
     698           0 :   nsGridRow* firstRow = nullptr;
     699           0 :   nsGridRow* lastRow = nullptr;
     700           0 :   GetFirstAndLastRow(firstIndex, lastIndex, firstRow, lastRow, aIsHorizontal);
     701             : 
     702           0 :   if (aIndex == firstIndex || aIndex == lastIndex) {
     703           0 :     nscoord maxTop = 0;
     704           0 :     nscoord maxBottom = 0;
     705             : 
     706             :     // run through the columns. Look at each column
     707             :     // pick the largest top border or bottom border
     708           0 :     int32_t count = GetColumnCount(aIsHorizontal);
     709             : 
     710           0 :     for (int32_t i=0; i < count; i++)
     711             :     {
     712           0 :       nsMargin totalChildBorderPadding(0,0,0,0);
     713             : 
     714           0 :       nsGridRow* column = GetColumnAt(i,aIsHorizontal);
     715           0 :       nsIFrame* box = column->GetBox();
     716             : 
     717           0 :       if (box)
     718             :       {
     719             :         // ignore collapsed children
     720           0 :         if (!box->IsXULCollapsed())
     721             :         {
     722             :            // include the margin of the columns. To the row
     723             :            // at this point border/padding and margins all added
     724             :            // up to more needed space.
     725           0 :            margin = GetBoxTotalMargin(box, !aIsHorizontal);
     726             :            // get real border and padding. GetXULBorderAndPadding
     727             :            // is redefined on nsGridRowLeafFrame. If we called it here
     728             :            // we would be in finite recurson.
     729           0 :            box->GetXULBorder(border);
     730           0 :            box->GetXULPadding(padding);
     731           0 :            totalChildBorderPadding += border;
     732           0 :            totalChildBorderPadding += padding;
     733           0 :            totalChildBorderPadding += margin;
     734             :         }
     735             : 
     736             :         nscoord top;
     737             :         nscoord bottom;
     738             : 
     739             :         // pick the largest top margin
     740           0 :         if (aIndex == firstIndex) {
     741           0 :           if (aIsHorizontal) {
     742           0 :             top = totalChildBorderPadding.top;
     743             :           } else {
     744           0 :             top = totalChildBorderPadding.left;
     745             :           }
     746           0 :           if (top > maxTop)
     747           0 :             maxTop = top;
     748             :         }
     749             : 
     750             :         // pick the largest bottom margin
     751           0 :         if (aIndex == lastIndex) {
     752           0 :           if (aIsHorizontal) {
     753           0 :             bottom = totalChildBorderPadding.bottom;
     754             :           } else {
     755           0 :             bottom = totalChildBorderPadding.right;
     756             :           }
     757           0 :           if (bottom > maxBottom)
     758           0 :              maxBottom = bottom;
     759             :         }
     760             : 
     761             :       }
     762             : 
     763             :       // If the biggest top border/padding the columns is larger than this rows top border/padding
     764             :       // the use it.
     765           0 :       if (aIndex == firstIndex) {
     766           0 :         if (maxTop > (row->mTop + row->mTopMargin))
     767           0 :           row->mTop = maxTop - row->mTopMargin;
     768             :       }
     769             : 
     770             :       // If the biggest bottom border/padding the columns is larger than this rows bottom border/padding
     771             :       // the use it.
     772           0 :       if (aIndex == lastIndex) {
     773           0 :         if (maxBottom > (row->mBottom + row->mBottomMargin))
     774           0 :           row->mBottom = maxBottom - row->mBottomMargin;
     775             :       }
     776             :     }
     777             :   }
     778             : 
     779           0 :   aTop    = row->mTop;
     780           0 :   aBottom = row->mBottom;
     781             : }
     782             : 
     783             : /**
     784             :  * These methods return the preferred, min, max coord for a given row index if
     785             :  * aIsHorizontal is true. If you pass false you will get the inverse.
     786             :  * As if you called GetPrefColumnHeight(aState, index, aPref).
     787             :  */
     788             : nscoord
     789           0 : nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
     790             : {
     791           0 :   RebuildIfNeeded();
     792             : 
     793           0 :   nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
     794             : 
     795           0 :   if (row->IsXULCollapsed())
     796           0 :     return 0;
     797             : 
     798           0 :   if (row->IsPrefSet())
     799           0 :     return row->mPref;
     800             : 
     801           0 :   nsIFrame* box = row->mBox;
     802             : 
     803             :   // set in CSS?
     804           0 :   if (box)
     805             :   {
     806             :     bool widthSet, heightSet;
     807           0 :     nsSize cssSize(-1, -1);
     808           0 :     nsIFrame::AddXULPrefSize(box, cssSize, widthSet, heightSet);
     809             : 
     810           0 :     row->mPref = GET_HEIGHT(cssSize, aIsHorizontal);
     811             : 
     812             :     // yep do nothing.
     813           0 :     if (row->mPref != -1)
     814           0 :       return row->mPref;
     815             :   }
     816             : 
     817             :   // get the offsets so they are cached.
     818             :   nscoord top;
     819             :   nscoord bottom;
     820           0 :   GetRowOffsets(aIndex, top, bottom, aIsHorizontal);
     821             : 
     822             :   // is the row bogus? If so then just ask it for its size
     823             :   // it should not be affected by cells in the grid.
     824           0 :   if (row->mIsBogus)
     825             :   {
     826           0 :      nsSize size(0,0);
     827           0 :      if (box)
     828             :      {
     829           0 :        size = box->GetXULPrefSize(aState);
     830           0 :        nsBox::AddMargin(box, size);
     831           0 :        nsGridLayout2::AddOffset(box, size);
     832             :      }
     833             : 
     834           0 :      row->mPref = GET_HEIGHT(size, aIsHorizontal);
     835           0 :      return row->mPref;
     836             :   }
     837             : 
     838           0 :   nsSize size(0,0);
     839             : 
     840             :   nsGridCell* child;
     841             : 
     842           0 :   int32_t count = GetColumnCount(aIsHorizontal);
     843             : 
     844           0 :   for (int32_t i=0; i < count; i++)
     845             :   {
     846           0 :     if (aIsHorizontal)
     847           0 :      child = GetCellAt(i,aIndex);
     848             :     else
     849           0 :      child = GetCellAt(aIndex,i);
     850             : 
     851             :     // ignore collapsed children
     852           0 :     if (!child->IsXULCollapsed())
     853             :     {
     854           0 :       nsSize childSize = child->GetXULPrefSize(aState);
     855             : 
     856           0 :       nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
     857             :     }
     858             :   }
     859             : 
     860           0 :   row->mPref = GET_HEIGHT(size, aIsHorizontal) + top + bottom;
     861             : 
     862           0 :   return row->mPref;
     863             : }
     864             : 
     865             : nscoord
     866           0 : nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
     867             : {
     868           0 :   RebuildIfNeeded();
     869             : 
     870           0 :   nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
     871             : 
     872           0 :   if (row->IsXULCollapsed())
     873           0 :     return 0;
     874             : 
     875           0 :   if (row->IsMinSet())
     876           0 :     return row->mMin;
     877             : 
     878           0 :   nsIFrame* box = row->mBox;
     879             : 
     880             :   // set in CSS?
     881           0 :   if (box) {
     882             :     bool widthSet, heightSet;
     883           0 :     nsSize cssSize(-1, -1);
     884           0 :     nsIFrame::AddXULMinSize(aState, box, cssSize, widthSet, heightSet);
     885             : 
     886           0 :     row->mMin = GET_HEIGHT(cssSize, aIsHorizontal);
     887             : 
     888             :     // yep do nothing.
     889           0 :     if (row->mMin != -1)
     890           0 :       return row->mMin;
     891             :   }
     892             : 
     893             :   // get the offsets so they are cached.
     894             :   nscoord top;
     895             :   nscoord bottom;
     896           0 :   GetRowOffsets(aIndex, top, bottom, aIsHorizontal);
     897             : 
     898             :   // is the row bogus? If so then just ask it for its size
     899             :   // it should not be affected by cells in the grid.
     900           0 :   if (row->mIsBogus)
     901             :   {
     902           0 :      nsSize size(0,0);
     903           0 :      if (box) {
     904           0 :        size = box->GetXULPrefSize(aState);
     905           0 :        nsBox::AddMargin(box, size);
     906           0 :        nsGridLayout2::AddOffset(box, size);
     907             :      }
     908             : 
     909           0 :      row->mMin = GET_HEIGHT(size, aIsHorizontal) + top + bottom;
     910           0 :      return row->mMin;
     911             :   }
     912             : 
     913           0 :   nsSize size(0,0);
     914             : 
     915             :   nsGridCell* child;
     916             : 
     917           0 :   int32_t count = GetColumnCount(aIsHorizontal);
     918             : 
     919           0 :   for (int32_t i=0; i < count; i++)
     920             :   {
     921           0 :     if (aIsHorizontal)
     922           0 :      child = GetCellAt(i,aIndex);
     923             :     else
     924           0 :      child = GetCellAt(aIndex,i);
     925             : 
     926             :     // ignore collapsed children
     927           0 :     if (!child->IsXULCollapsed())
     928             :     {
     929           0 :       nsSize childSize = child->GetXULMinSize(aState);
     930             : 
     931           0 :       nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
     932             :     }
     933             :   }
     934             : 
     935           0 :   row->mMin = GET_HEIGHT(size, aIsHorizontal);
     936             : 
     937           0 :   return row->mMin;
     938             : }
     939             : 
     940             : nscoord
     941           0 : nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
     942             : {
     943           0 :   RebuildIfNeeded();
     944             : 
     945           0 :   nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
     946             : 
     947           0 :   if (row->IsXULCollapsed())
     948           0 :     return 0;
     949             : 
     950           0 :   if (row->IsMaxSet())
     951           0 :     return row->mMax;
     952             : 
     953           0 :   nsIFrame* box = row->mBox;
     954             : 
     955             :   // set in CSS?
     956           0 :   if (box) {
     957             :     bool widthSet, heightSet;
     958           0 :     nsSize cssSize(-1, -1);
     959           0 :     nsIFrame::AddXULMaxSize(box, cssSize, widthSet, heightSet);
     960             : 
     961           0 :     row->mMax = GET_HEIGHT(cssSize, aIsHorizontal);
     962             : 
     963             :     // yep do nothing.
     964           0 :     if (row->mMax != -1)
     965           0 :       return row->mMax;
     966             :   }
     967             : 
     968             :   // get the offsets so they are cached.
     969             :   nscoord top;
     970             :   nscoord bottom;
     971           0 :   GetRowOffsets(aIndex, top, bottom, aIsHorizontal);
     972             : 
     973             :   // is the row bogus? If so then just ask it for its size
     974             :   // it should not be affected by cells in the grid.
     975           0 :   if (row->mIsBogus)
     976             :   {
     977           0 :      nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
     978           0 :      if (box) {
     979           0 :        size = box->GetXULPrefSize(aState);
     980           0 :        nsBox::AddMargin(box, size);
     981           0 :        nsGridLayout2::AddOffset(box, size);
     982             :      }
     983             : 
     984           0 :      row->mMax = GET_HEIGHT(size, aIsHorizontal);
     985           0 :      return row->mMax;
     986             :   }
     987             : 
     988           0 :   nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
     989             : 
     990             :   nsGridCell* child;
     991             : 
     992           0 :   int32_t count = GetColumnCount(aIsHorizontal);
     993             : 
     994           0 :   for (int32_t i=0; i < count; i++)
     995             :   {
     996           0 :     if (aIsHorizontal)
     997           0 :      child = GetCellAt(i,aIndex);
     998             :     else
     999           0 :      child = GetCellAt(aIndex,i);
    1000             : 
    1001             :     // ignore collapsed children
    1002           0 :     if (!child->IsXULCollapsed())
    1003             :     {
    1004           0 :       nsSize min = child->GetXULMinSize(aState);
    1005           0 :       nsSize childSize = nsBox::BoundsCheckMinMax(min, child->GetXULMaxSize(aState));
    1006           0 :       nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
    1007             :     }
    1008             :   }
    1009             : 
    1010           0 :   row->mMax = GET_HEIGHT(size, aIsHorizontal) + top + bottom;
    1011             : 
    1012           0 :   return row->mMax;
    1013             : }
    1014             : 
    1015             : bool
    1016           0 : nsGrid::IsGrid(nsIFrame* aBox)
    1017             : {
    1018           0 :   nsIGridPart* part = GetPartFromBox(aBox);
    1019           0 :   if (!part)
    1020           0 :     return false;
    1021             : 
    1022           0 :   nsGridLayout2* grid = part->CastToGridLayout();
    1023             : 
    1024           0 :   if (grid)
    1025           0 :     return true;
    1026             : 
    1027           0 :   return false;
    1028             : }
    1029             : 
    1030             : /**
    1031             :  * This get the flexibilty of the row at aIndex. It's not trivial. There are a few
    1032             :  * things we need to look at. Specifically we need to see if any <rows> or <columns>
    1033             :  * tags are around us. Their flexibilty will affect ours.
    1034             :  */
    1035             : nscoord
    1036           0 : nsGrid::GetRowFlex(int32_t aIndex, bool aIsHorizontal)
    1037             : {
    1038           0 :   RebuildIfNeeded();
    1039             : 
    1040           0 :   nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
    1041             : 
    1042           0 :   if (row->IsFlexSet())
    1043           0 :     return row->mFlex;
    1044             : 
    1045           0 :   nsIFrame* box = row->mBox;
    1046           0 :   row->mFlex = 0;
    1047             : 
    1048           0 :   if (box) {
    1049             : 
    1050             :     // We need our flex but a inflexible row could be around us. If so
    1051             :     // neither are we. However if its the row tag just inside the grid it won't
    1052             :     // affect us. We need to do this for this case:
    1053             :     // <grid>
    1054             :     //   <rows>
    1055             :     //     <rows> // this is not flexible. So our children should not be flexible
    1056             :     //        <row flex="1"/>
    1057             :     //        <row flex="1"/>
    1058             :     //     </rows>
    1059             :     //        <row/>
    1060             :     //   </rows>
    1061             :     // </grid>
    1062             :     //
    1063             :     // or..
    1064             :     //
    1065             :     // <grid>
    1066             :     //  <rows>
    1067             :     //   <rows> // this is not flexible. So our children should not be flexible
    1068             :     //     <rows flex="1">
    1069             :     //        <row flex="1"/>
    1070             :     //        <row flex="1"/>
    1071             :     //     </rows>
    1072             :     //        <row/>
    1073             :     //   </rows>
    1074             :     //  </row>
    1075             :     // </grid>
    1076             : 
    1077             : 
    1078             :     // So here is how it looks
    1079             :     //
    1080             :     // <grid>
    1081             :     //   <rows>   // parentsParent
    1082             :     //     <rows> // parent
    1083             :     //        <row flex="1"/>
    1084             :     //        <row flex="1"/>
    1085             :     //     </rows>
    1086             :     //        <row/>
    1087             :     //   </rows>
    1088             :     // </grid>
    1089             : 
    1090             :     // so the answer is simple: 1) Walk our parent chain. 2) If we find
    1091             :     // someone who is not flexible and they aren't the rows immediately in
    1092             :     // the grid. 3) Then we are not flexible
    1093             : 
    1094           0 :     box = GetScrollBox(box);
    1095           0 :     nsIFrame* parent = nsBox::GetParentXULBox(box);
    1096           0 :     nsIFrame* parentsParent=nullptr;
    1097             : 
    1098           0 :     while(parent)
    1099             :     {
    1100           0 :       parent = GetScrollBox(parent);
    1101           0 :       parentsParent = nsBox::GetParentXULBox(parent);
    1102             : 
    1103             :       // if our parents parent is not a grid
    1104             :       // the get its flex. If its 0 then we are
    1105             :       // not flexible.
    1106           0 :       if (parentsParent) {
    1107           0 :         if (!IsGrid(parentsParent)) {
    1108           0 :           nscoord flex = parent->GetXULFlex();
    1109           0 :           nsIFrame::AddXULFlex(parent, flex);
    1110           0 :           if (flex == 0) {
    1111           0 :             row->mFlex = 0;
    1112           0 :             return row->mFlex;
    1113             :           }
    1114             :         } else
    1115           0 :           break;
    1116             :       }
    1117             : 
    1118           0 :       parent = parentsParent;
    1119             :     }
    1120             : 
    1121             :     // get the row flex.
    1122           0 :     row->mFlex = box->GetXULFlex();
    1123           0 :     nsIFrame::AddXULFlex(box, row->mFlex);
    1124             :   }
    1125             : 
    1126           0 :   return row->mFlex;
    1127             : }
    1128             : 
    1129             : void
    1130           0 : nsGrid::SetLargestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal)
    1131             : {
    1132           0 :   if (aIsHorizontal) {
    1133           0 :     if (aSize.height < aHeight)
    1134           0 :       aSize.height = aHeight;
    1135             :   } else {
    1136           0 :     if (aSize.width < aHeight)
    1137           0 :       aSize.width = aHeight;
    1138             :   }
    1139           0 : }
    1140             : 
    1141             : void
    1142           0 : nsGrid::SetSmallestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal)
    1143             : {
    1144           0 :   if (aIsHorizontal) {
    1145           0 :     if (aSize.height > aHeight)
    1146           0 :       aSize.height = aHeight;
    1147             :   } else {
    1148           0 :     if (aSize.width < aHeight)
    1149           0 :       aSize.width = aHeight;
    1150             :   }
    1151           0 : }
    1152             : 
    1153             : int32_t
    1154           0 : nsGrid::GetRowCount(int32_t aIsHorizontal)
    1155             : {
    1156           0 :   RebuildIfNeeded();
    1157             : 
    1158           0 :   if (aIsHorizontal)
    1159           0 :     return mRowCount;
    1160             :   else
    1161           0 :     return mColumnCount;
    1162             : }
    1163             : 
    1164             : int32_t
    1165           0 : nsGrid::GetColumnCount(int32_t aIsHorizontal)
    1166             : {
    1167           0 :   return GetRowCount(!aIsHorizontal);
    1168             : }
    1169             : 
    1170             : /*
    1171             :  * A cell in the given row or columns at the given index has had a child added or removed
    1172             :  */
    1173             : void
    1174           0 : nsGrid::CellAddedOrRemoved(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
    1175             : {
    1176             :   // TBD see if the cell will fit in our current row. If it will
    1177             :   // just add it in.
    1178             :   // but for now rebuild everything.
    1179           0 :   if (mMarkingDirty)
    1180           0 :     return;
    1181             : 
    1182           0 :   NeedsRebuild(aState);
    1183             : }
    1184             : 
    1185             : /**
    1186             :  * A row or columns at the given index had been added or removed
    1187             :  */
    1188             : void
    1189           0 : nsGrid::RowAddedOrRemoved(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
    1190             : {
    1191             :   // TBD see if we have extra room in the table and just add the new row in
    1192             :   // for now rebuild the world
    1193           0 :   if (mMarkingDirty)
    1194           0 :     return;
    1195             : 
    1196           0 :   NeedsRebuild(aState);
    1197             : }
    1198             : 
    1199             : /*
    1200             :  * Scrollframes are tranparent. If this is given a scrollframe is will return the
    1201             :  * frame inside. If there is no scrollframe it does nothing.
    1202             :  */
    1203             : nsIFrame*
    1204           0 : nsGrid::GetScrolledBox(nsIFrame* aChild)
    1205             : {
    1206             :   // first see if it is a scrollframe. If so walk down into it and get the scrolled child
    1207           0 :       nsIScrollableFrame *scrollFrame = do_QueryFrame(aChild);
    1208           0 :       if (scrollFrame) {
    1209           0 :          nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame();
    1210           0 :          NS_ASSERTION(scrolledFrame,"Error no scroll frame!!");
    1211           0 :          return scrolledFrame;
    1212             :       }
    1213             : 
    1214           0 :       return aChild;
    1215             : }
    1216             : 
    1217             : /*
    1218             :  * Scrollframes are tranparent. If this is given a child in a scrollframe is will return the
    1219             :  * scrollframe ourside it. If there is no scrollframe it does nothing.
    1220             :  */
    1221             : nsIFrame*
    1222           0 : nsGrid::GetScrollBox(nsIFrame* aChild)
    1223             : {
    1224           0 :   if (!aChild)
    1225           0 :     return nullptr;
    1226             : 
    1227             :   // get parent
    1228           0 :   nsIFrame* parent = nsBox::GetParentXULBox(aChild);
    1229             : 
    1230             :   // walk up until we find a scrollframe or a part
    1231             :   // if it's a scrollframe return it.
    1232             :   // if it's a parent then the child passed does not
    1233             :   // have a scroll frame immediately wrapped around it.
    1234           0 :   while (parent) {
    1235           0 :     nsIScrollableFrame *scrollFrame = do_QueryFrame(parent);
    1236             :     // scrollframe? Yep return it.
    1237           0 :     if (scrollFrame)
    1238           0 :       return parent;
    1239             : 
    1240           0 :     nsCOMPtr<nsIGridPart> parentGridRow = GetPartFromBox(parent);
    1241             :     // if a part then just return the child
    1242           0 :     if (parentGridRow)
    1243           0 :       break;
    1244             : 
    1245           0 :     parent = nsBox::GetParentXULBox(parent);
    1246             :   }
    1247             : 
    1248           0 :   return aChild;
    1249             : }
    1250             : 
    1251             : 
    1252             : 
    1253             : #ifdef DEBUG_grid
    1254             : void
    1255             : nsGrid::PrintCellMap()
    1256             : {
    1257             : 
    1258             :   printf("-----Columns------\n");
    1259             :   for (int x=0; x < mColumnCount; x++)
    1260             :   {
    1261             : 
    1262             :     nsGridRow* column = GetColumnAt(x);
    1263             :     printf("%d(pf=%d, mn=%d, mx=%d) ", x, column->mPref, column->mMin, column->mMax);
    1264             :   }
    1265             : 
    1266             :   printf("\n-----Rows------\n");
    1267             :   for (x=0; x < mRowCount; x++)
    1268             :   {
    1269             :     nsGridRow* column = GetRowAt(x);
    1270             :     printf("%d(pf=%d, mn=%d, mx=%d) ", x, column->mPref, column->mMin, column->mMax);
    1271             :   }
    1272             : 
    1273             :   printf("\n");
    1274             : 
    1275             : }
    1276             : #endif

Generated by: LCOV version 1.13