| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (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.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.containers |
| { |
| |
| import mx.containers.gridClasses.GridColumnInfo; |
| import mx.containers.gridClasses.GridRowInfo; |
| import mx.core.EdgeMetrics; |
| |
| //-------------------------------------- |
| // Styles |
| //-------------------------------------- |
| |
| /** |
| * Number of pixels between children in the horizontal direction. |
| * The default value is 8. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="horizontalGap", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * Number of pixels between children in the vertical direction. |
| * The default value is 6. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="verticalGap", type="Number", format="Length", inherit="no")] |
| |
| //-------------------------------------- |
| // Excluded APIs |
| //-------------------------------------- |
| |
| [Exclude(name="direction", kind="property")] |
| |
| [Exclude(name="focusIn", kind="event")] |
| [Exclude(name="focusOut", kind="event")] |
| |
| [Exclude(name="focusBlendMode", kind="style")] |
| [Exclude(name="focusSkin", kind="style")] |
| [Exclude(name="focusThickness", kind="style")] |
| |
| [Exclude(name="focusInEffect", kind="effect")] |
| [Exclude(name="focusOutEffect", kind="effect")] |
| |
| [IconFile("Grid.png")] |
| |
| /** |
| * A Grid container lets you arrange children as rows and columns |
| * of cells, similar to an HTML table. |
| * The Grid container contains one or more rows, and each row can contain |
| * one or more cells, or items. You use the following tags to define a Grid control: |
| * |
| * <ul> |
| * <li>The <code><mx:Grid></code> tag defines a Grid container.</li> |
| * |
| * <li>The <code><mx:GridRow></code> tag defines a grid row, |
| * which has one or more cells. The grid row must be a child of the |
| * <code><Grid></code> tag.</li> |
| * |
| * <li>The <code><mx:GridItem></code> tag defines a grid cell, |
| * and must be a child of the <code><GridRow></code> tag. |
| * The <code><mx:GridItem></code> tag can contain |
| * any number of children.</li> |
| * </ul> |
| * |
| * <p>The height of all the cells in a single row is the same, |
| * but each row can have a different height. |
| * The width of all cells in a single column is the same, |
| * but each column can have a different width. |
| * You can define a different number of cells |
| * for each row or each column of the Grid container. |
| * In addition, a cell can span multiple columns |
| * or multiple rows of the container.</p> |
| * |
| * <p>The Grid, GridRow, and GridItem containers have the following default sizing characteristics:</p> |
| * <table class="innertable"> |
| * <tr> |
| * <th>Characteristic</th> |
| * <th>Description</th> |
| * </tr> |
| * <tr> |
| * <td>Grid height</td> |
| * <td>The sum of the default or explicit heights of all rows plus the gaps between rows.</td> |
| * </tr> |
| * <tr> |
| * <td>Grid width</td> |
| * <td>The sum of the default or explicit width of all columns plus the gaps between columns.</td> |
| * </tr> |
| * <tr> |
| * <td>Height of each row and each cell</td> |
| * <td>The default or explicit height of the tallest item in the row. If a GridItem container does not |
| * have an explicit size, its default height is the default or explicit height of the child in the cell.</td> |
| * </tr> |
| * <tr> |
| * <td>Width of each column and each cell</td> |
| * <td>The default or explicit width of the widest item in the column. If a GridItem container does not have an explicit |
| * width, its default width is the default or explicit width of the child in the cell.</td> |
| * </tr> |
| * <tr> |
| * <td>Gap between rows and columns</td> |
| * <td>Determined by the horizontalGap and verticalGap styles of the Grid class. The default value for both |
| * gaps is 6 pixels.</td> |
| * </tr> |
| * <tr> |
| * <td>Default padding</td> |
| * <td>0 pixels for the top, bottom, left, and right values, for all three container classes.</td> |
| * </tr> |
| * </table> |
| * |
| * @mxml |
| * |
| * <p>The <code><mx:Grid></code> tag inherits all of the tag |
| * attributes of its superclass, except the <code>Box.direction</code> |
| * property, and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <mx:Grid |
| * <strong>Styles</strong> |
| * horizontalGap="8" |
| * verticalGap="6" |
| * > |
| * ... |
| * <i>These child tags are examples only:</i> |
| * <mx:GridRow id="row1"> |
| * <mx:GridItem |
| * rowSpan="1" |
| * colSpan="1"> |
| * <mx:Button label="Button 1"/> |
| * </mx:GridItem> |
| * ... |
| * </mx:GridRow> |
| * ... |
| * </mx:Grid> |
| * </pre> |
| * |
| * @includeExample examples/GridLayoutExample.mxml |
| * |
| * @see mx.containers.GridRow |
| * @see mx.containers.GridItem |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class Grid extends Box |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function Grid() |
| { |
| super(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Minimum, maximum, and preferred width of each column. |
| */ |
| private var columnWidths:Array /* of GridColumnInfo */; |
| |
| /** |
| * @private |
| * Minimum, maximum, and preferred height of each row. |
| */ |
| private var rowHeights:Array /* of GridRowInfo */; |
| |
| /** |
| * @private |
| */ |
| private var needToRemeasure:Boolean = true; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods:UIComponent |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function invalidateSize():void |
| { |
| // When the Grid's size is invalidated, the rowHeights |
| // and columnWidths arrays need to be recalculated. |
| // Those arrays are usually recalculated in measure(), |
| // but set a flag in case measure() isn't called (which |
| // will happen if the Grid's width and height are explicit). |
| if (!isNaN(explicitWidth) && !isNaN(explicitHeight)) |
| needToRemeasure = true; |
| |
| super.invalidateSize(); |
| } |
| |
| /** |
| * Calculates the preferred, minimum, and maximum sizes of the Grid. |
| |
| * <p>You should not call this method directly; it is an advanced |
| * method for use in subclassing. |
| * The Flex LayoutManger calls the <code>measure()</code> method |
| * at the appropriate time. |
| * At application startup, the Flex LayoutManager attempts |
| * to measure all components from the children to the parents |
| * before setting them to their final sizes.</p> |
| * |
| * <p>To understand how the Grid container calculates its measurements, |
| * assume that every GridItem container has its <code>rowSpan</code> |
| * property and <code>colSpan</code> property set to 1. |
| * The measured width of the first column of the Grid container |
| * is equal to the maximum among of the measured widths |
| * of all GridItem containers in the first column. |
| * Similarly, the measured width of the second column is |
| * the maximum of all measured widths among the GridItem containers |
| * in the second column, and so on. |
| * The <code>measuredWidth</code> of the entire Grid container |
| * is the sum of all columns' measured widths, plus the thickness |
| * of the border, plus the left and right padding, plus room |
| * for the horizontal gap between adjacent grid cells.</p> |
| * |
| * <p>The <code>measuredHeight</code>, <code>minWidth</code>, |
| * <code>minHeight</code>, <code>maxWidth</code>, and |
| * <code>maxHeight</code> properties' values are all calculated |
| * in a similar manner, by adding together the values of the |
| * GridItem containers' <code>measuredHeight</code> properties, |
| * <code>minWidth</code> properties, and so on.</p> |
| * |
| * <p>If a GridItem container's <code>colSpan</code> property is 3, |
| * that GridItem container's <code>measuredWidth</code> is divided |
| * among 3 columns. |
| * If the <code>measuredWidth</code> is divided equally, |
| * each of the three columns calculates its measured width |
| * as if the GridItem container were only in that column |
| * and the GridItem container's <code>measuredWidth</code> |
| * were one-third of its actual value.</p> |
| * |
| * <p>However, the GridItem container's <code>measuredWidth</code> |
| * property is not always divided equally among all the columns it spans. |
| * If some of the columns have a property with a percentage value |
| * of <code>width</code>, the GridItem container's |
| * <code>measuredWidth</code> property is divided accordingly, |
| * attempting to give each column the requested percentage |
| * of the Grid container.</p> |
| * |
| * <p>All of the values described previously are the |
| * <i>measured</i> widths and heights of Grid. |
| * The user can override the measured values by explicitly |
| * supplying a value for the following properties:</p> |
| * |
| * <ul> |
| * <li><code>minHeight</code></li> |
| * <li><code>minWidth</code></li> |
| * <li><code>maxHeight</code></li> |
| * <li><code>maxWidth</code></li> |
| * <li><code>height</code></li> |
| * <li><code>width</code></li> |
| * </ul> |
| * |
| * <p>If you override this method, your implementation must call the |
| * <code>super.measure()</code> method or set the |
| * <code>measuredHeight</code> and <code>measuredWidth</code> properties. |
| * You may also optionally set the following properties:</p> |
| * |
| * <ul> |
| * <li><code>measuredMinWidth</code></li> |
| * <li><code>measuredMinHeight</code></li> |
| * </ul> |
| * |
| * <p>These properties correspond to the layout properties listed previously |
| * and, therefore, are not documented separately.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function measure():void |
| { |
| // 1. Determine the number of grid columns, |
| // taking into account rowSpan and colSpan |
| |
| var numGridRows:int = 0; |
| var numGridColumns:int = 0; |
| var columnOccupiedUntilRow:Array = []; |
| var gridRow:GridRow; |
| var gridItem:GridItem; |
| var i:int; |
| var j:int; |
| var colIndex:int; |
| |
| var rowList:Array = []; // GridRows |
| |
| for (var index:int = 0; index < numChildren; index++) |
| { |
| gridRow = GridRow(getChildAt(index)); |
| if (gridRow.includeInLayout) |
| { |
| rowList.push(gridRow); |
| numGridRows++; |
| } |
| } |
| |
| |
| for (i = 0; i < numGridRows; i++) |
| { |
| colIndex = 0; |
| gridRow = rowList[i]; |
| |
| // Cache the number of children as a property on the gridRow |
| gridRow.numGridItems = gridRow.numChildren; |
| |
| // Tell the grid row what row number it is |
| gridRow.rowIndex = i; |
| for (j = 0; j < gridRow.numGridItems; j++) |
| { |
| // If this column is occupied by a cell in the previous row, |
| // then push cells in this row to the right. |
| if (i > 0) |
| { |
| var occupied:int = columnOccupiedUntilRow[colIndex]; |
| while (!isNaN(occupied) && occupied >= i) |
| { |
| colIndex++; |
| occupied = columnOccupiedUntilRow[colIndex]; |
| } |
| } |
| |
| // Set the position of this GridItem to the next |
| // available space. |
| gridItem = GridItem(gridRow.getChildAt(j)); |
| gridItem.colIndex = colIndex; |
| |
| // If this cell extends to rows beyond this one, remember |
| // which columns are occupied. |
| if (gridItem.rowSpan > 1) |
| { |
| var lastRowOccupied:int = i + gridItem.rowSpan - 1; |
| for (var k:int = 0; k < gridItem.colSpan; k++) |
| { |
| columnOccupiedUntilRow[colIndex + k] = lastRowOccupied; |
| } |
| } |
| |
| colIndex += gridItem.colSpan; |
| } |
| |
| if (colIndex > numGridColumns) |
| numGridColumns = colIndex; |
| } |
| |
| // 2. Create the rowHeights and colWidths arrays. |
| // Initially set all heights and widths to zero. |
| |
| rowHeights = new Array(numGridRows); |
| columnWidths = new Array(numGridColumns); |
| |
| for (i = 0; i < numGridRows; i++) |
| { |
| rowHeights[i] = new GridRowInfo(); |
| } |
| for (i = 0; i < numGridColumns; i++) |
| { |
| columnWidths[i] = new GridColumnInfo(); |
| } |
| |
| // 3. Visit all the GridItems again. |
| // Expand each row and each column so it's large enough |
| // to hold its GridItems. |
| // We'll deal with rowSpans and colSpans of 1 first, |
| // then rowSpans and colSpans of 2, and so on. |
| |
| var BIG_INT:int = int.MAX_VALUE; |
| var curSpan:int; |
| var nextSpan:int = 1; |
| |
| var horizontalGap:Number = getStyle("horizontalGap"); |
| var verticalGap:Number = getStyle("verticalGap"); |
| |
| do |
| { |
| curSpan = nextSpan; |
| nextSpan = BIG_INT; |
| |
| for (i = 0; i < numGridRows; i++) |
| { |
| gridRow = rowList[i]; |
| |
| // Store pointers to the columnWidths and rowHeights arrays |
| // on each GridRow object. |
| gridRow.columnWidths = columnWidths; |
| gridRow.rowHeights = rowHeights; |
| |
| for (j = 0; j < gridRow.numGridItems; j++) |
| { |
| gridItem = GridItem(gridRow.getChildAt(j)); |
| var rowSpan:int = gridItem.rowSpan; |
| var colSpan:int = gridItem.colSpan; |
| |
| // During this iteration of the outermost do-while loop, |
| // we're dealing with rows and columns that have a rowSpan |
| // or colSpan equal to curSpan. If we encounter a row or |
| // column with a larger span, remember its span in nextSpan |
| // for the next iteration through the do-while loop. |
| |
| if (rowSpan == curSpan) |
| distributeItemHeight(gridItem, i, verticalGap, rowHeights); |
| else if (rowSpan > curSpan && rowSpan < nextSpan) |
| nextSpan = rowSpan; |
| |
| if (colSpan == curSpan) |
| { |
| distributeItemWidth(gridItem, gridItem.colIndex, |
| horizontalGap, columnWidths); |
| } |
| else if (colSpan > curSpan && colSpan < nextSpan) |
| { |
| nextSpan = colSpan; |
| } |
| } |
| } |
| } |
| while (nextSpan < BIG_INT); |
| |
| // 4. Reconcile min/preferred/max values, so that min <= pref <= max. |
| // Also compute sums of all measurements. |
| |
| var minWidth:Number = 0; |
| var minHeight:Number = 0; |
| var preferredWidth:Number = 0; |
| var preferredHeight:Number = 0; |
| |
| for (i = 0; i < numGridRows; i++) |
| { |
| var rowInfo:GridRowInfo = rowHeights[i]; |
| |
| if (rowInfo.min > rowInfo.preferred) |
| rowInfo.min = rowInfo.preferred; |
| if (rowInfo.max < rowInfo.preferred) |
| rowInfo.max = rowInfo.preferred; |
| |
| minHeight += rowInfo.min; |
| preferredHeight += rowInfo.preferred; |
| } |
| |
| for (i = 0; i < numGridColumns; i++) |
| { |
| var columnInfo:GridColumnInfo = columnWidths[i]; |
| |
| if (columnInfo.min > columnInfo.preferred) |
| columnInfo.min = columnInfo.preferred; |
| if (columnInfo.max < columnInfo.preferred) |
| columnInfo.max = columnInfo.preferred; |
| |
| minWidth += columnInfo.min; |
| preferredWidth += columnInfo.preferred; |
| } |
| |
| // 5. Add horizontal space for the gaps between the grid cells |
| // and the margins around them. |
| |
| // Add space for grid's left and right margins |
| var vm:EdgeMetrics = viewMetricsAndPadding; |
| var padding:Number = vm.left + vm.right; |
| var row:GridRow; |
| var rowVm:EdgeMetrics; |
| var maxRowPadding:Number = 0; |
| |
| // Add space for horizontal gaps between grid items. |
| if (numGridColumns > 1) |
| padding += getStyle("horizontalGap") * (numGridColumns - 1); |
| |
| // Add space for the gridrow's left and right margins. |
| for (i = 0; i < numGridRows; i++) |
| { |
| row = rowList[i]; |
| rowVm = row.viewMetricsAndPadding; |
| var rowPadding:Number = rowVm.left + rowVm.right; |
| if (rowPadding > maxRowPadding) |
| maxRowPadding = rowPadding; |
| } |
| padding += maxRowPadding; |
| |
| minWidth += padding; |
| preferredWidth += padding; |
| |
| // 6. Add vertical space for the gaps between grid cells |
| // and the margins around them. |
| |
| // Add space for grid's left and right margins. |
| padding = vm.top + vm.bottom; |
| |
| // Add space for vertical gaps between grid items. |
| if (numGridRows > 1) |
| padding += getStyle("verticalGap") * (numGridRows - 1); |
| |
| // Add each of the grid rows' margins. |
| for (i = 0; i < numGridRows; i++) |
| { |
| row = rowList[i]; |
| rowVm = row.viewMetricsAndPadding; |
| padding += rowVm.top + rowVm.bottom; |
| } |
| |
| minHeight += padding; |
| preferredHeight += padding; |
| |
| // 7. Now that the Grid is finished measuring itself, |
| // update all the measurements of the child GridRows. |
| |
| for (i = 0; i < numGridRows; i++) |
| { |
| row = rowList[i]; |
| row.updateRowMeasurements(); |
| } |
| |
| // 8. Up until now, we've calculated all our measurements |
| // based on the GridItems. |
| // If someone has explicitly set the width (or percentWidth |
| // or whatever) of a GridRow, we've been ignoring it. |
| // Run the standard Box measurement algorithm, which will |
| // take into account hard-coded values on the GridRow objects, |
| // and combine the measured values with the ones |
| // we've calculated based on GridItems. |
| |
| super.measure(); |
| |
| measuredMinWidth = Math.max(measuredMinWidth, minWidth); |
| measuredMinHeight = Math.max(measuredMinHeight, minHeight); |
| measuredWidth = Math.max(measuredWidth, preferredWidth); |
| measuredHeight = Math.max(measuredHeight, preferredHeight); |
| |
| needToRemeasure = false; |
| } |
| |
| /** |
| * Sets the size and position of each child of the Grid. |
| * |
| * <p>You should not call this method directly; it is an advanced |
| * method for use in subclassing. |
| * The Flex LayoutManager calls the <code>updateDisplayList</code> |
| * method at the appropriate time. |
| * At application startup, the Flex LayoutManager calls |
| * the <code>updateDisplayList()</code> method on every component, |
| * starting with the root and working downward.</p> |
| * |
| * <p>The Grid container follows the same layout rules |
| * as the VBox container. |
| * The positions and sizes of the GridRow containers |
| * are calculated the same way that a VBox container |
| * determines the positions and sizes of its children. |
| * Similarly, a GridRow container positions its GridItem containers |
| * using a similar layout algorithm of an HBox container.</p> |
| * |
| * <p>The only difference is that the GridRow containers |
| * all coordinate with one another, so they all choose |
| * the same positions and sizes for their children |
| * (so that the columns of the Grid container align). </p> |
| * |
| * <p>If you override this method, your implementation should call |
| * the <code>super.updateDisplayList()</code> method |
| * and call the <code>move()</code> and the <code>setActualSize()</code> |
| * methods on each of the children. |
| * For the purposes of performing layout, you should get the size |
| * of this container from the <code>unscaledWidth</code> |
| * and <code>unscaledHeight</code> properties, not the |
| * <code>width</code> and <code>height</code> properties. |
| * The <code>width</code> and <code>height</code> properties do not |
| * take into account the values of the <code>scaleX</code> |
| * and <code>scaleY</code> properties for this container.</p> |
| * |
| * @param unscaledWidth Specifies the width of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleX</code> property of the component. |
| * |
| * @param unscaledHeight Specifies the height of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleY</code> property of the component. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function updateDisplayList(unscaledWidth:Number, |
| unscaledHeight:Number):void |
| { |
| // If the measure function wasn't called (because the widths |
| // and heights of the Grid are explicitly set), then we need |
| // to generate the rowHeights and columnWidths arrays now. |
| if (needToRemeasure) |
| measure(); |
| |
| // Follow standard VBox rules for laying out the child rows. |
| super.updateDisplayList(unscaledWidth, unscaledHeight); |
| |
| var n:int = 0; |
| var i:int; |
| var child:GridRow; |
| |
| var rowList:Array = []; // GridRows |
| |
| for (var index:int = 0; index < numChildren; index++) |
| { |
| child = GridRow(getChildAt(index)); |
| if (child.includeInLayout) |
| { |
| rowList.push(child); |
| n++; |
| } |
| } |
| |
| // Copy the row heights, which were calculated by the VBox layout |
| // algorithm, into the rowHeights array. |
| for (i = 0; i < n; i++) |
| { |
| child = rowList[i]; |
| |
| rowHeights[i].y = child.y; |
| rowHeights[i].height = child.height; |
| } |
| |
| // Now that all the rows have been layed out, lay out the GridItems |
| // in those rows, based on the info stored in the colWidths and |
| // rowHeights arrays. |
| for (i = 0; i < n; i++) |
| { |
| child = rowList[i]; |
| |
| child.doRowLayout(child.width * child.scaleX, |
| child.height * child.scaleY); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private function distributeItemHeight(item:GridItem, rowIndex:Number, |
| verticalGap:Number, |
| rowHeights:Array):void |
| { |
| var maxHeight:Number = item.maxHeight; |
| var preferredHeightToDistribute:Number = |
| item.getExplicitOrMeasuredHeight(); |
| var minHeightToDistribute:Number = item.minHeight; |
| var rowSpan:int = item.rowSpan; |
| var totalFlex:Number = 0; |
| var divideEqually:Boolean = false; |
| var i:int; |
| var rowInfo:GridRowInfo; |
| |
| // If the row(s) spanned by this GridItem are already non-empty, |
| // subtract the existing sizes of those rows from the item's height. |
| for (i = rowIndex; i < rowIndex + rowSpan; i++) |
| { |
| rowInfo = rowHeights[i]; |
| preferredHeightToDistribute -= rowInfo.preferred; |
| minHeightToDistribute -= rowInfo.min; |
| totalFlex += rowInfo.flex; |
| } |
| |
| // Subtract space for gaps between the rows. |
| if (rowSpan > 1) |
| { |
| var gap:Number = verticalGap * (rowSpan - 1); |
| preferredHeightToDistribute -= gap; |
| minHeightToDistribute -= gap; |
| } |
| |
| // If none of the rows spanned by this item are resizable, |
| // then divide space among the rows equally. |
| if (totalFlex == 0) |
| { |
| totalFlex = rowSpan; |
| divideEqually = true; |
| } |
| |
| // If we haven't yet distributed the height of the object, |
| // divide remaining height among the rows. |
| // If some rows are resizable and others are not, |
| // allocate space to the resizable ones. |
| preferredHeightToDistribute = |
| preferredHeightToDistribute > 0 ? |
| Math.ceil(preferredHeightToDistribute / totalFlex) : |
| 0; |
| minHeightToDistribute = |
| minHeightToDistribute > 0 ? |
| Math.ceil(minHeightToDistribute / totalFlex) : |
| 0; |
| |
| for (i = rowIndex; i < rowIndex + rowSpan; i++) |
| { |
| rowInfo = rowHeights[i]; |
| var flex:Number = divideEqually ? 1 : rowInfo.flex; |
| rowInfo.preferred += preferredHeightToDistribute * flex; |
| rowInfo.min += minHeightToDistribute * flex; |
| } |
| |
| // The GridItem.maxHeight attribute is respected only for rows |
| // with a rowSpan of 1. |
| if (rowSpan == 1 && maxHeight < rowInfo.max) |
| rowInfo.max = maxHeight; |
| } |
| |
| /** |
| * @private |
| */ |
| private function distributeItemWidth(item:GridItem, colIndex:int, |
| horizontalGap:Number, columnWidths:Array):void |
| { |
| var maxWidth:Number = item.maxWidth; |
| var preferredWidthToDistribute:Number = |
| item.getExplicitOrMeasuredWidth(); |
| var minWidthToDistribute:Number = item.minWidth; |
| var colSpan:int = item.colSpan; |
| var percentWidth:Number = item.percentWidth; |
| var totalFlex:Number = 0; |
| var divideEqually:Boolean = false; |
| var i:int; |
| var columnInfo:GridColumnInfo; |
| |
| // If the column(s) spanned by this GridItem are already non-empty, |
| // subtract the existing sizes of those columns from the item's width. |
| for (i = colIndex; i < colIndex + colSpan; i++) |
| { |
| columnInfo = columnWidths[i]; |
| preferredWidthToDistribute -= columnInfo.preferred; |
| minWidthToDistribute -= columnInfo.min; |
| totalFlex += columnInfo.flex; |
| } |
| |
| // Subtract space for gaps between the columns. |
| if (colSpan > 1) |
| { |
| var gap:Number = horizontalGap * (colSpan - 1); |
| preferredWidthToDistribute -= gap; |
| minWidthToDistribute -= gap; |
| } |
| |
| // If none of the columns spanned by this item are resizable, |
| // then divide space among the columns equally. |
| if (totalFlex == 0) |
| { |
| totalFlex = colSpan; |
| divideEqually = true; |
| } |
| |
| // If we haven't yet distributed the width of the object, |
| // divide remaining width among the columns. |
| // If some columns are resizable and others are not, |
| // allocate space to the resizable ones. |
| preferredWidthToDistribute = |
| preferredWidthToDistribute > 0 ? |
| Math.ceil(preferredWidthToDistribute / totalFlex) : |
| 0; |
| minWidthToDistribute = |
| minWidthToDistribute > 0 ? |
| Math.ceil(minWidthToDistribute / totalFlex) : |
| 0; |
| |
| for (i = colIndex; i < colIndex + colSpan; i++) |
| { |
| columnInfo = columnWidths[i]; |
| var flex:Number = divideEqually ? 1 : columnInfo.flex; |
| columnInfo.preferred += preferredWidthToDistribute * flex; |
| columnInfo.min += minWidthToDistribute * flex; |
| if (percentWidth) |
| { |
| columnInfo.percent = Math.max(columnInfo.percent, |
| percentWidth / colSpan); |
| } |
| } |
| |
| // The GridItem.maxWidth attribute is respected only for columns |
| // with a colSpan of 1. |
| if (colSpan == 1 && maxWidth < columnInfo.max) |
| columnInfo.max = maxWidth; |
| } |
| } |
| |
| } |