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-06-02 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