/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ // // Eric Vaughan // Netscape Communications // // See documentation in associated header file // #include "nsGrid.h" #include "nsGridRowGroupLayout.h" #include "nsBox.h" #include "nsIScrollableFrame.h" #include "nsSprocketLayout.h" #include "nsGridRow.h" #include "nsGridCell.h" /* The grid control expands the idea of boxes from 1 dimension to 2 dimensions. It works by allowing the XUL to define a collection of rows and columns and then stacking them on top of each other. Here is and example. Example 1: example 2: example 3: Usually the columns are first and the rows are second, so the rows will be drawn on top of the columns. You can reverse this by defining the rows first. Other tags are then placed in the or tags causing the grid to accommodate everyone. It does this by creating 3 things: A cellmap, a row list, and a column list. The cellmap is a 2 dimensional array of nsGridCells. Each cell contains 2 boxes. One cell from the column list and one from the row list. When a cell is asked for its size it returns that smallest size it can be to accommodate the 2 cells. Row lists and Column lists use the same data structure: nsGridRow. Essentially a row and column are the same except a row goes alone the x axis and a column the y. To make things easier and save code everything is written in terms of the x dimension. A flag is passed in called "isHorizontal" that can flip the calculations to the y axis. Usually the number of cells in a row match the number of columns, but not always. It is possible to define 5 columns for a grid but have 10 cells in one of the rows. In this case 5 extra columns will be added to the column list to handle the situation. These are called extraColumns/Rows. */ nsGrid::nsGrid():mBox(nsnull), mRows(nsnull), mColumns(nsnull), mRowsBox(nsnull), mColumnsBox(nsnull), mNeedsRebuild(PR_TRUE), mRowCount(0), mColumnCount(0), mExtraRowCount(0), mExtraColumnCount(0), mCellMap(nsnull), mMarkingDirty(PR_FALSE) { MOZ_COUNT_CTOR(nsGrid); } nsGrid::~nsGrid() { FreeMap(); MOZ_COUNT_DTOR(nsGrid); } /* * This is called whenever something major happens in the grid. And example * might be when many cells or row are added. It sets a flag signaling that * all the grids caches information should be recalculated. */ void nsGrid::NeedsRebuild(nsBoxLayoutState& aState) { if (mNeedsRebuild) return; // iterate through columns and rows and dirty them mNeedsRebuild = PR_TRUE; // find the new row and column box. They could have // been changed. mRowsBox = nsnull; mColumnsBox = nsnull; FindRowsAndColumns(&mRowsBox, &mColumnsBox); // tell all the rows and columns they are dirty DirtyRows(mRowsBox, aState); DirtyRows(mColumnsBox, aState); } /** * If we are marked for rebuild. Then build everything */ void nsGrid::RebuildIfNeeded() { if (!mNeedsRebuild) return; mNeedsRebuild = PR_FALSE; // find the row and columns frames FindRowsAndColumns(&mRowsBox, &mColumnsBox); // count the rows and columns PRInt32 computedRowCount = 0; PRInt32 computedColumnCount = 0; PRInt32 rowCount = 0; PRInt32 columnCount = 0; CountRowsColumns(mRowsBox, rowCount, computedColumnCount); CountRowsColumns(mColumnsBox, columnCount, computedRowCount); // computedRowCount are the actual number of rows as determined by the // columns children. // computedColumnCount are the number of columns as determined by the number // of rows children. // We can use this information to see how many extra columns or rows we need. // This can happen if there are are more children in a row that number of columns // defined. Example: // // // // // // // //