/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // // 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 "nsGridLayout2.h" #include "nsGridRow.h" #include "nsGridCell.h" #include "nsHTMLReflowState.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. */ using namespace mozilla; nsGrid::nsGrid():mBox(nullptr), mRowsBox(nullptr), mColumnsBox(nullptr), mNeedsRebuild(true), mRowCount(0), mColumnCount(0), mExtraRowCount(0), mExtraColumnCount(0), mMarkingDirty(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 = true; // find the new row and column box. They could have // been changed. mRowsBox = nullptr; mColumnsBox = nullptr; 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 = false; // find the row and columns frames FindRowsAndColumns(&mRowsBox, &mColumnsBox); // count the rows and columns int32_t computedRowCount = 0; int32_t computedColumnCount = 0; int32_t rowCount = 0; int32_t 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: // // // // // // // //