LCOV - app.info - layout/xul/base/src/grid/nsGrid.cpp

LCOV - code coverage report
| Current view: | directory - layout/xul/base/src/grid - nsGrid.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 486 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 36 | 0 | 0.0 %

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

Generated by: LCOV version 1.7