////////////////////////////////////////////////////////////////////////////////
//
//  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 spark.components.gridClasses
{
import flash.geom.Rectangle;

import mx.collections.IList;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.PropertyChangeEvent;

[ExcludeClass]

/**
 *  A sparse data structure that represents the widths and heights of a grid.
 *  
 *  <p>Provides efficient support for finding the cumulative y distance to the
 *  start of a particular cell as well as finding the index of a particular
 *  cell at a certain y value.
 *  GridDimensions optimizes these operations by bookmarking the most recently
 *  visited rows.</p>
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.0
 *  @productversion Flex 4.5
 */
public class GridDimensions 
{
    include "../../core/Version.as";
    
    //--------------------------------------------------------------------------
    //
    //  Class methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Inserts specified elements starting from startIndex.
     *  
     *  <pre>Our implementation of:
     *      var argArray:Array = [];
     *      for each (var x:Number in values)
     *      {
     *          argArray.push(x);
     *      }
     *      argArray.splice(0, 0, startIndex, 0);
     *      vec.splice.apply(vec, argArray);</pre>
     * 
     *  @param vec The vector to insert into.
     *  @param startIndex The index to insert at.
     *  @param elements The elements to be inserted.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public static function insertElementsToVector(vec:Vector.<Number>, startIndex:int, elements:Vector.<Number>):void
    {
        const oldLength:int = vec.length;
        const count:int = elements.length;
        vec.length += count;
        const vecLength:int = vec.length;
        var i:int;

        // Shift elements down by count.
        for (i = oldLength - 1; i >= startIndex; i--)
            vec[i + count] = vec[i];
        
        const endIndex:int = startIndex + elements.length;
        var j:int = 0;
        for (i = startIndex; i < endIndex; i++)
            vec[i] = elements[j++];
    }
    
    /**
     *  Insert count elements of the specified value starting from
     *  startIndex.
     *  
     *  @param vec The vector to insert into.
     *  @param startIndex The index to insert at.
     *  @param count The number of elements to insert
     *  @param value The value of the inserted elements
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public static function insertValueToVector(vec:Vector.<Number>, startIndex:int, count:int, value:Number):void
    {
        const oldLength:int = vec.length;
        vec.length += count;
        const vecLength:int = vec.length;
        
        // Shift elements down by count.
        for (var i:int = oldLength - 1; i >= startIndex; i--)
            vec[i + count] = vec[i];
        
        clearVector(vec, value, startIndex, count);
    }
    
    /**
     *  Sets all of the numbers in a vector to be value unless otherwise
     *  specified.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public static function clearVector(vec:Vector.<Number>, value:Number, startIndex:int = 0, count:int = -1):void
    {
        const endIndex:int = (count == -1) ? vec.length : startIndex + count;
        
        for (var i:int = startIndex; i < endIndex; i++)
            vec[i] = value;
    }
    
    /**
     *  @private
     *  Restrict a number to a particular min and max.
     */
    private static function bound(a:Number, min:Number, max:Number):Number
    {
        if (a < min)
            a = min;
        else if (a > max)
            a = max;
        
        return a;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    private var rowList:GridRowList = new GridRowList();
    private var _columnWidths:Vector.<Number> = new Vector.<Number>();

    // Bookmark recently visited rows by caching the node representing the row
    // and the y-value corresponding to the start of the node.
    // startY/recentNode is the bookmark used by getRowIndexAt()
    private var startY:Number = 0;
    private var recentNode:GridRowNode = null;
    // startY2/recentNode2 is bookmark used by getCellY()
    private var startY2:Number = 0;
    private var recentNode2:GridRowNode = null;
    
    private const typicalCellWidths:Vector.<Number> = new Vector.<Number>();
    private const typicalCellHeights:Vector.<Number> = new Vector.<Number>();
    private var maxTypicalCellHeight:Number = NaN;
    private var useMaxTypicalCellHeight:Boolean = true;
    
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Constructor.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function GridDimensions()
    {
        super();
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  rowCount
    //----------------------------------
    
    private var _rowCount:int = 0;
    
    /**
     *  The number of rows in the Grid. If this is decreased, the 
     *  excess rows will be removed.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get rowCount():int
    {
        return _rowCount;
    }
    
    /**
     *  @private
     */
    public function set rowCount(value:int):void
    {
        if (value == _rowCount)
            return;
        
        // remove rows greater than value.
        // This also clears the cached nodes.
        if (value < _rowCount)
            removeRowsAt(value, value - _rowCount)
        
        _rowCount = value;
    }
    
    //----------------------------------
    //  columnCount
    //----------------------------------
    
    private var _columnCount:int = 0;
    
    /**
     *  The number of columns in the Grid.
     *  Setting this property will clear the cache.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get columnCount():int
    {
        return _columnCount;
    }
    
    /**
     *  @private
     */
    public function set columnCount(value:int):void
    {
        // Don't short-circuit return if the column count didn't change.
        // There might be a new set of columns which is the same length
        // as the old set of columns.

        // clear cached information
        clearHeights();
        
        // fix up the number of columns
        _columnCount = value;
        _columnWidths.length = value;
        typicalCellHeights.length = value;
        typicalCellWidths.length = value;
        rowList.numColumns = value;
        
        // clear the rest of the vectors
        clearTypicalCellWidthsAndHeights();
        clearVector(_columnWidths, NaN, 0, _columnCount);
    }

    //----------------------------------
    //  rowGap
    //----------------------------------

    private var _rowGap:Number = 0;
    
    /**
     *  The gap between rows.
     * 
     *  @default 0 
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get rowGap():Number
    {
        return _rowGap;
    }
    
    /**
     *  @private
     */
    public function set rowGap(value:Number):void
    {
        if (value == _rowGap)
            return;
        
        _rowGap = value;

        clearCachedNodes();
    }
    
    //----------------------------------
    //  columnGap
    //----------------------------------

    private var _columnGap:Number = 0;
    
    /**
     *  The gap between columns.
     * 
     *  @default 0
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5 
     */
    public function get columnGap():Number
    {
        return _columnGap;
    }
    
    /**
     *  @private
     */
    public function set columnGap(value:Number):void
    {
        if (value == _columnGap)
            return;
        
        _columnGap = value;

        clearCachedNodes();
    }
    
    //----------------------------------
    //  defaultRowHeight
    //----------------------------------

    private var _defaultRowHeight:Number = NaN;
    
    /**
     *  The default height of a row.
     *
     *  <p>If this property is not set explicitly, it will use the maximum
     *  of the typical cell heights.</p>
     *
     *  <p>When variableRowHeight is false, all rows have a height of
     *  defaultRowHeight.</p>
     *
     *  @default NaN
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get defaultRowHeight():Number
    {
        return useMaxTypicalCellHeight ? maxTypicalCellHeight : _defaultRowHeight;
    }
    
    /**
     *  @private
     */
    public function set defaultRowHeight(value:Number):void
    {
        if (value == _defaultRowHeight)
            return;
        
        _defaultRowHeight = bound(value, _minRowHeight, _maxRowHeight);
        useMaxTypicalCellHeight = isNaN(_defaultRowHeight);
        
        clearCachedNodes();
    }
    
    //----------------------------------
    //  defaultColumnWidth
    //----------------------------------
    
    private var _defaultColumnWidth:Number = 150;
    
    /**
     *  The default width of a column.
     *  If this changes, update the ASDoc for GridLayout/getItemRendererAt().
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get defaultColumnWidth():Number
    {
        return _defaultColumnWidth;
    }
    
    /**
     *  @private
     */
    public function set defaultColumnWidth(value:Number):void
    {
        if (value == _defaultColumnWidth)
            return;
        
        _defaultColumnWidth = value;
    }    
    
    //----------------------------------
    //  variableRowHeight
    //----------------------------------
    
    private var _variableRowHeight:Boolean = false;  // default value must match Grid property default value
    
    /**
     *  If variableRowHeight is false, calling getRowHeight
     *  will return the value of defaultRowHeight.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get variableRowHeight():Boolean
    {
        return _variableRowHeight;
    }
    
    /**
     *  @private
     */
    public function set variableRowHeight(value:Boolean):void
    {
        if (value == _variableRowHeight)
            return;
        
        _variableRowHeight = value;
    }       
    
    //----------------------------------
    //  minRowHeight
    //----------------------------------
    
    private var _minRowHeight:Number = 0;
    
    /**
     *  The minimum height of each row.
     * 
     *  @default 0
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get minRowHeight():Number
    {
        return _minRowHeight;
    }
    
    /**
     *  @private
     */
    public function set minRowHeight(value:Number):void
    {
        if (value == _minRowHeight)
            return;
        
        _minRowHeight = value;
        _defaultRowHeight = Math.max(_defaultRowHeight, _minRowHeight);
    }
    
    //----------------------------------
    //  maxRowHeight
    //----------------------------------
    
    private var _maxRowHeight:Number = 10000;
    
    /**
     *  The maximum height of each row.
     * 
     *  @default 10000
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function get maxRowHeight():Number
    {
        return _maxRowHeight;
    }
    
    /**
     *  @private
     */
    public function set maxRowHeight(value:Number):void
    {
        if (value == _maxRowHeight)
            return;
        
        _maxRowHeight = value;
        _defaultRowHeight = Math.min(_defaultRowHeight, _maxRowHeight);
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Clears bookmarked nodes.
     *  Each bookmarked node is associated with a cumulative y-value representing
     *  the total height of the grid up to the start of the row.
     *  These values are cleared as well.
     */
    private function clearCachedNodes():void
    {
        recentNode = null;
        startY = 0;
        recentNode2 = null;
        startY2 = 0;
    }
    
    /**
     *  Returns the height of the row at the given index. If variableRowHeight
     *  is true, then the height in precendence order is: the height set by setRowHeight,
     *  the natural height of the row (determined by the maximum of its cell heights),
     *  and defaultRowHeight. If variableRowHeight is false, then the height returned
     *  is the defaultRowHeight. The returned height is always bounded by the minRowHeight
     *  and maxRowHeight.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getRowHeight(row:int):Number
    {
        // Unless setRowHeight is called, return the max cell height for this row
        var height:Number = defaultRowHeight;
        
        if (variableRowHeight)
        {
            var node:GridRowNode = rowList.find(row);
            if (node)
            {
                if (node.fixedHeight >= 0)
                    height = node.fixedHeight;
                else if (node.maxCellHeight >= 0)
                    height = node.maxCellHeight;
            }
        }
        
        return (!isNaN(height)) ? bound(height, minRowHeight, maxRowHeight) : height;
    }
    
    /**
     *  Sets the height of a given row. This height takes precedence over
     *  the natural height of the row (determined by the maximum of its 
     *  cell heights) and the defaultRowHeight. However, if variableRowHeight
     *  is true, this method has no effect.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function setRowHeight(row:int, height:Number):void
    {
        if (!variableRowHeight)
            return;
        
        var node:GridRowNode = rowList.find(row);
        
        if (node)
        {
            node.fixedHeight = bound(height, minRowHeight, maxRowHeight);
        }
        else
        {
            node = rowList.insert(row);
            
            if (node)
                node.fixedHeight = bound(height, minRowHeight, maxRowHeight);
        }
        
        clearCachedNodes();
    }

    /**
     *  Returns the width of the column at the given index. Returns
     *  the width specified by setColumnWidth. If no width has been
     *  specified, returns the typical width. If no typical width has
     *  been set, it returns the defaultColumnWidth.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getColumnWidth(col:int):Number
    {    
        var w:Number = NaN;

        w = _columnWidths[col];
        
        if (isNaN(w))
            w = typicalCellWidths[col];
        
        if (isNaN(w))
            w = this.defaultColumnWidth;
        
        return w;
    }
    
    /**
     *  Sets the width of a given column.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function setColumnWidth(col:int, width:Number):void
    {
        _columnWidths[col] = width;
    }

    /**
     *  Returns the height of the specified cell. Returns the height
     *  specified by setCellHeight. If the height has not been specified,
     *  returns NaN.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getCellHeight(row:int, col:int):Number
    {
        var node:GridRowNode = rowList.find(row);
        
        if (node)
            return node.getCellHeight(col);
        
        return NaN;
    }
    
    /**
     *  Sets the height of the specified cell.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function setCellHeight(row:int, col:int, height:Number):void
    {
        if (!variableRowHeight)
            return;
        
        var node:GridRowNode = rowList.find(row);
        var oldHeight:Number = defaultRowHeight;
        
        if (node == null)
            node = rowList.insert(row);
        else
            oldHeight = node.maxCellHeight;
        
        if (node && node.setCellHeight(col, height))
        {
           if (recentNode && node.rowIndex < recentNode.rowIndex)
               startY += node.maxCellHeight - oldHeight;
           
           if (recentNode2 && node.rowIndex < recentNode2.rowIndex)
               startY2 += node.maxCellHeight - oldHeight;
        }
    }
    
    /**
     *  Returns the layout bounds of the specified cell. The cell height
     *  and width are determined by its row's height and column's width.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getCellBounds(row:int, col:int):Rectangle
    {
        // TODO (klin): provide optional return value (Rectangle) parameter
        if (row < 0 || row >= rowCount || col < 0 || col >= columnCount)
            return null;
        
        var x:Number = getCellX(row, col);
        var y:Number = getCellY(row, col);
        
        var width:Number = getColumnWidth(col);
        var height:Number = getRowHeight(row);
        
        return new Rectangle(x, y, width, height);
    }
    
    /**
     *  Returns the X coordinate of the origin of the specified cell.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getCellX(row:int, col:int):Number
    {   
        var x:Number = 0;
        
        for (var i:int = 0; i < col; i++)
        {
            x += getColumnWidth(i) + columnGap;
        }
        
        return x;
    }
    
    /**
     *  Returns the Y coordinate of the origin of the specified cell.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getCellY(row:int, col:int):Number
    { 
        // no cache so we use default heights for each row.
        if (!variableRowHeight || rowList.length == 0)
            return row * (defaultRowHeight + rowGap);
        
        if (row == 0)
            return 0;
        
        // initialize first node.
        if (!recentNode2)
        {
            recentNode2 = rowList.first;
            startY2 = recentNode2.rowIndex * (defaultRowHeight + rowGap);
        }
        
        var y:Number;
        var recentIndex:int = recentNode2.rowIndex;

        if (row == recentIndex)
            y = startY2;
        else if (row < recentIndex)
            y = getPrevYAt(row, recentNode2, startY2);
        else
            y = getNextYAt(row, recentNode2, startY2);

        return y;
    }

    /**
     *  @private
     *  Returns the starting y value of the specified row. The row must be before
     *  startNode.
     *  
     *  @param row the target row
     *  @param startNode the node to search from
     *  @param startY the cumulative y value from the first row to the beginning
     *  of startNode's row.
     * 
     *  @return the y value of the start of the row.
     */
    private function getPrevYAt(row:int, startNode:GridRowNode, startY:Number):Number
    {
        var node:GridRowNode = startNode;
        var nodeY:Number = startY;
        var prevNode:GridRowNode;
        var currentY:Number = startY;
        var indDiff:int;
        
        while (node)
        {
            if (node.rowIndex == row)
                break;
            
            prevNode = node.prev;
            
            if (!prevNode || (row < node.rowIndex && row > prevNode.rowIndex))
            {
                // at the beginning or somewhere between nodes
                // so we've found the target row.
                indDiff = node.rowIndex - row;
                currentY -= indDiff * (defaultRowHeight + rowGap);
                break;
            }
            
            // subtract previous node's height and its gap.
            indDiff = node.rowIndex - prevNode.rowIndex - 1;
            currentY = currentY - indDiff * (defaultRowHeight + rowGap) - (getRowHeight(prevNode.rowIndex) + rowGap);
            nodeY = currentY;
            node = prevNode;
        }
        
        this.recentNode2 = node;
        this.startY2 = nodeY;
        
        return currentY;
    }
    
    /**
     *  @private
     *  Returns the starting y value of the specified row. The row must be after
     *  startNode.
     *  
     *  @param row the target row
     *  @param startNode the node to search from
     *  @param startY the cumulative y value from the first row to beginning of
     *  startNode's row.
     * 
     *  @return the y value of the start of the row.
     */
    private function getNextYAt(row:int, startNode:GridRowNode, startY:Number):Number
    {
        var node:GridRowNode = startNode;
        var nodeY:Number = startY;
        var nextNode:GridRowNode;
        var currentY:Number = startY;
        var indDiff:int;
        
        while (node)
        {
            if (node.rowIndex == row)
                break;

            // add next row's height and rowGap
            currentY += getRowHeight(node.rowIndex);
            if (node.rowIndex < _rowCount - 1)
                currentY += rowGap;
            
            nextNode = node.next;
            
            if (!nextNode || (row > node.rowIndex && row < nextNode.rowIndex))
            {
                // at the beginning or somewhere between nodes
                // so we've found the target row.
                indDiff = row - node.rowIndex - 1;
                currentY += indDiff * (defaultRowHeight + rowGap);
                break;
            }
            
            // add estimated heights of rows in between measured rows.
            indDiff = nextNode.rowIndex - node.rowIndex - 1;
            currentY = currentY + indDiff * (defaultRowHeight + rowGap);
            nodeY = currentY; 
            node = nextNode;
        }
        
        this.recentNode2 = node;
        this.startY2 = nodeY;
        
        return currentY;
    }
    
    /**
     *  Returns the layout bounds of the specified row.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getRowBounds(row:int):Rectangle
    {
        // TODO (klin): provide optional return value (Rectangle) parameter    
        if ((row < 0) || (row >= _rowCount))
            return null;
        
        if (_columnCount == 0 || _rowCount == 0)
            return new Rectangle(0, 0, 0, 0);
        
        const x:Number = getCellX(row, 0);
        const y:Number = getCellY(row, 0);
        const rowWidth:Number = getCellX(row, _columnCount - 1) + getColumnWidth(_columnCount - 1) - x;
        const rowHeight:Number = getRowHeight(row);
        return new Rectangle(x, y, rowWidth, rowHeight);
    }
    
    /**
     *  Return the dimensions of a row that's being used to "pad" the grid
     *  by filling unused space below the last row in a layout where all rows
     *  are visible.  Pad rows have index >= rowCount, height = defaultRowHeight.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getPadRowBounds(row:int):Rectangle
    {
        if (row < 0)
            return null;
        
        if (row < rowCount)
            return getRowBounds(row);
        
        const lastRow:int = rowCount - 1;
        const lastCol:int = columnCount - 1;
        
        const x:Number = (lastRow >= 0) ? getCellX(lastRow, 0) : 0;
        const lastRowBottom:Number = (lastRow >= 0) ? getCellY(lastRow, 0) + getRowHeight(lastRow) : 0;
        const padRowCount:int = row - rowCount;
        const padRowTotalGap:Number = (padRowCount > 0) ? (padRowCount - 1) * rowGap : 0;
        const y:Number = lastRowBottom + (padRowCount * defaultRowHeight) + padRowTotalGap;
        
        var rowWidth:Number = 0;
        if ((lastCol >= 0) && (lastRow >= 0))
            rowWidth = getCellX(lastRow, lastCol) + getColumnWidth(lastCol) - x;
        else if (lastCol >= 0)
            rowWidth = getCellX(0, lastCol) + getColumnWidth(lastCol) - x;
        else if (lastRow >= 0)
            rowWidth = getCellX(lastRow, 0) + getColumnWidth(0) - x;
        
        return new Rectangle(x, y, rowWidth, defaultRowHeight);
        
    }
    
    /**
     *  Returns the layout bounds of the specified column.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getColumnBounds(col:int):Rectangle
    {
        // TODO (klin): provide optional return value (Rectangle) parameter
        if ((col < 0) || (col >= _columnCount))
            return null;
        
        if (_columnCount == 0)
            return new Rectangle(0, 0, 0, 0);

        const x:Number = getCellX(0, col);
        const y:Number = getCellY(0, col);
        const colWidth:Number = getColumnWidth(col);
        var colHeight:Number = 0;
		
		if (_rowCount > 0)
			colHeight = getCellY(_rowCount - 1, col) + getRowHeight(_rowCount - 1) - y;

        return new Rectangle(x, y, colWidth, colHeight);
    }
    
    /**
     *  Returns the index of the row at the specified coordinates. If
     *  the coordinates lie in a gap area, the index returned is the
     *  previous row.
     * 
     *  @return The index of the row at the coordinates provided. If the
     *  coordinates are out of bounds, return -1.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getRowIndexAt(x:Number, y:Number):int
    {
        if (y < 0)
            return -1;
        
        var index:int;
        
        if (!variableRowHeight || rowList.length == 0)
        {
            index = y / (defaultRowHeight + rowGap);
            return index < _rowCount ? index : -1;
        }
        
        if (y == 0)
            return _rowCount > 0 ? 0 : -1;
        
        // initialize first node.
        if (!recentNode)
        {
            recentNode = rowList.first;
            startY = recentNode.rowIndex * (defaultRowHeight + rowGap);
        }
        
        // if we are already at the right row, then use the index.
        if (isYInRow(y, startY, recentNode))
            index = recentNode.rowIndex;
        else if (y < startY)
            index = getPrevRowIndexAt(y, recentNode, startY);
        else
            index = getNextRowIndexAt(y, recentNode, startY);
        
        return index < _rowCount ? index : -1;
    }
    
    /**
     *  @private
     *  Checks if a certain y value lies in a row's bounds.
     */
    private function isYInRow(y:Number, startY:Number, node:GridRowNode):Boolean
    {
        var end:Number = startY + getRowHeight(node.rowIndex);
        
        // don't add gap for last row.
        if (node.rowIndex != rowCount - 1)
            end += rowGap;
        
        // if y is between cumY and cumY + rowHeight - 1 then y is in the row.
        if (y >= startY && y < end)
            return true;
        
        return false;
    }
    
    /**
     *  @private
     *  Returns the index of the row that contains the specified y value.
     *  The row will be before startNode.
     *  
     *  @param y the target y value
     *  @param startNode the node to search from
     *  @param startY the cumulative y value from the first row to startNode
     * 
     *  @return the index of the row that contains the y value.
     */
    private function getPrevRowIndexAt(y:Number, startNode:GridRowNode, startY:Number):int
    {
        var node:GridRowNode = startNode;
        var prevNode:GridRowNode = null;
        var index:int = node.rowIndex;
        var currentY:Number = startY;
        var prevY:Number;
        var targetY:Number = y;

        while (node)
        {
            // check the current node.
            if (isYInRow(targetY, currentY, node))
                break;
            
            // calculate previous y.
            prevNode = node.prev;
            
            if (!prevNode)
            {
                prevY = 0;
            }
            else
            {
                prevY = currentY;
                
                var indDiff:int = node.rowIndex - prevNode.rowIndex;
                
                // subtract default row heights if difference is greater than one.
                if (indDiff > 1)
                    prevY -= (indDiff - 1) * (defaultRowHeight + rowGap);
            }
            
            // check if target Y is in range.
            if (targetY < currentY && targetY >= prevY)
            {
                index = index - Math.ceil(Number(currentY - targetY)/(defaultRowHeight + rowGap));
                break;
            }

            // subtract previous node's height and its gap.
            currentY = prevY - getRowHeight(prevNode.rowIndex) - rowGap;
            node = node.prev;
            index = node.rowIndex;
        }
        
        this.recentNode = node;
        this.startY = currentY;
        
        return index;
    }
    
    /**
     *  @private
     *  Returns the index of the row that contains the specified y value.
     *  The row will be after startNode.
     *  
     *  @param y the target y value
     *  @param startNode the node to search from
     *  @param startY the cumulative y value from the first row to startNode
     * 
     *  @return the index of the row that contains the y value.
     */
    private function getNextRowIndexAt(y:Number, startNode:GridRowNode, startY:Number):int
    {
        var node:GridRowNode = startNode;
        var nextNode:GridRowNode = null;
        var index:int = node.rowIndex;
        var nodeY:Number = startY;
        var currentY:Number = startY;
        var nextY:Number;
        var targetY:Number = y;
        
        while (node)
        {
            // check the current node.
            if (isYInRow(targetY, nodeY, node))
                break;
            
            // currentY increments to end of the current node.
            currentY += getRowHeight(node.rowIndex);
            if (node.rowIndex != rowCount - 1)
                currentY += rowGap;
            
            // calculate end of next section.
            nextNode = node.next;
            nextY = currentY;
            
            var indDiff:int;
            
            if (!nextNode)
            {
                indDiff = rowCount - 1 - node.rowIndex;
                // the y at the end doesn't have a rowGap, but includes the final pixel.
                nextY += indDiff * (defaultRowHeight + rowGap) - rowGap + 1;
            }
            else
            {
                indDiff = nextNode.rowIndex - node.rowIndex;
                nextY += (indDiff - 1) * (defaultRowHeight + rowGap);
            }
            
            // check if target Y is within default row heights range.
            if (targetY >= currentY && targetY < nextY)
            {
                index = index + Math.ceil(Number(targetY - currentY)/(defaultRowHeight + rowGap));
                break;
            }
            
            // if no next node and we didn't find the target, then the row doesn't exist.
            if (!nextNode)
            {
                index = -1;
                break;
            }
            
            // move y values ahead to next node.
            nodeY = currentY = nextY;
            
            node = node.next;
            index = node.rowIndex;
        }
        
        this.recentNode = node;
        this.startY = nodeY;
        
        return index;
    }
    
    /**
     *  Returns the index of the column at the specified coordinates. If
     *  the coordinates lie in a gap area, the index returned is the
     *  previous column. Returns -1 if the coordinates are out of bounds.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getColumnIndexAt(x:Number, y:Number):int
    {
        var current:Number = x;
        var i:int;

        if(current < 0)
            return -1;

        for (i = 0; i < _columnCount; i++)
        {
            var columnWidth:Number = _columnWidths[i];
            
            // fall back on typical widths if the actual width isn't set.
            if (isNaN(columnWidth))
            {
                columnWidth = typicalCellWidths[i];
                if (columnWidth == 0) // invisible column
                    continue;
            }
            
            // fall back on defaultColumnWidth
            if (isNaN(columnWidth))
                columnWidth = defaultColumnWidth;
            
            current -= columnWidth + columnGap;

            if (current < 0)
                return i;
        }
        
        return -1;
    }
    
    /**
     *  Returns the total layout width of the content including gaps.   If 
	 *  columnCountOverride is specified, then the overall width of as many columns
	 *  is returned.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getContentWidth(columnCountOverride:int = -1, startColumnIndex:int = 0):Number
    {
        const nCols:int = (columnCountOverride == -1) ? columnCount - startColumnIndex : columnCountOverride;
        var contentWidth:Number = 0;
        var measuredColCount:int = 0;
        
        for (var columnIndex:int = startColumnIndex; (columnIndex < columnCount) && (measuredColCount < nCols); columnIndex++)
        {
            if (columnIndex >= _columnWidths.length)
            {
                contentWidth += defaultColumnWidth;
                measuredColCount++;
                continue;
            }
            
            var width:Number = _columnWidths[columnIndex];
            
            // fall back on typical width
            if (isNaN(width))
            {
                width = typicalCellWidths[columnIndex];
                // column.visible==false, skip this column.
                if (width == 0)
                    continue;
            }
            
            // fall back on defaultColumnWidth
            if (isNaN(width))
                width = defaultColumnWidth;
            
            contentWidth += width;
            measuredColCount++;
        }
        
        if (measuredColCount > 1)
            contentWidth += (measuredColCount - 1) * columnGap;
        
        return contentWidth;
    }
    
    /**
     *  Returns the total layout height of the content including gaps.  If 
	 *  rowCountOverride is specified, then the overall height of as many rows
	 *  is returned.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getContentHeight(rowCountOverride:int = -1, startRowIndex:int = 0):Number
    {
        const nRows:int = (rowCountOverride == -1) ? rowCount - startRowIndex : rowCountOverride;        
        const maxRow:int = (rowCountOverride == -1) ? rowCount : startRowIndex + rowCountOverride;
		var contentHeight:Number = 0;
        
        if (nRows > 1)
            contentHeight += (nRows - 1) * rowGap;
        
        if (!variableRowHeight || rowList.length == 0)
            return contentHeight + nRows * defaultRowHeight;
        
        var node:GridRowNode = (startRowIndex == 0) ? rowList.first : rowList.findNearestLTE(startRowIndex);
        var numRows:int = 0;
        
        while (node && node.rowIndex < maxRow)  
        {
            if (node.rowIndex < startRowIndex)
            {
                node = node.next;
                continue;
            }
            contentHeight += getRowHeight(node.rowIndex);
            numRows++;
            node = node.next;
        }
    
        contentHeight += (nRows - numRows) * defaultRowHeight;
        
        return contentHeight;
    }
    
    /**
     *  Returns the sum of the typical cell widths including gaps.  If 
	 *  columnCountOverride is specified, then the overall typicalCellWidth 
     *  of as many columns is returned. 
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getTypicalContentWidth(columnCountOverride:int = -1, startColumnIndex:int = 0):Number
    {
        const nCols:int = (columnCountOverride == -1) ? columnCount - startColumnIndex : columnCountOverride;
        var contentWidth:Number = 0;
        var measuredColCount:int = 0;
        
        for (var columnIndex:int = startColumnIndex; (columnIndex < columnCount) && (measuredColCount < nCols); columnIndex++)
        {
            // column.visible==false columns will have a typicalCellWidth of 0, so skip them.
            var width:Number = columnIndex < columnCount ? typicalCellWidths[columnIndex] : NaN;
            if (width == 0)
                continue;
            
            if (isNaN(width))
                width = defaultColumnWidth;
            
            contentWidth += width;
            measuredColCount++;
        }
        
        if (measuredColCount > 1)
            contentWidth += (measuredColCount - 1) * columnGap;

        return contentWidth;
    }
    
    /**
     *  Returns the content height which is maximum cell height of the
     *  typical item times the total number of rows including gaps. 
     *  If rowCountOverride is specified, then we only include that many rows.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getTypicalContentHeight(rowCountOverride:int = -1, startRowIndex:int = 0):Number
    {
        const nRows:int = (rowCountOverride == -1) ? rowCount - startRowIndex : rowCountOverride;          
        var contentHeight:Number = 0;
        
        if (nRows > 1)
            contentHeight += (nRows - 1) * rowGap;
        
        if (!isNaN(defaultRowHeight))
            return contentHeight + nRows * defaultRowHeight;
        
        return 0;
    }
        
    /**
     *  Return the preferred bounds width of the grid's typicalItem when rendered with the item renderer 
     *  for the specified column.  If no value has yet been specified, return NaN.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function getTypicalCellWidth(columnIndex:int):Number
    {
        return typicalCellWidths[columnIndex];
    }
    
    /**
     *  Sets the preferred bounds width of the grid's typicalItem for the specified column.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function setTypicalCellWidth(columnIndex:int, value:Number):void
    {
        typicalCellWidths[columnIndex] = value;
    }
    
    /**
     *  Return the preferred bounds height of the grid's typicalItem when rendered with the item renderer 
     *  for the specified column.  If no value has yet been specified, return NaN.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */    
    public function getTypicalCellHeight(columnIndex:int):Number
    {
        return typicalCellHeights[columnIndex];
    }
    
    /**
     *  Sets the preferred bounds height of the grid's typicalItem for the specified column.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */    
    public function setTypicalCellHeight(columnIndex:int, value:Number):void
    {
        typicalCellHeights[columnIndex] = value;
        
        var max:Number = 0;
        const typicalCellHeightsLength:int = typicalCellHeights.length;
        for (var i:int = 0; i < typicalCellHeightsLength; i++)
        {
            if (!isNaN(typicalCellHeights[i])) 
                max = Math.max(max, typicalCellHeights[i]);
        }
        this.maxTypicalCellHeight = max;
    }
    
    /**
     *  Clears the typical cell for every column and row.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function clearTypicalCellWidthsAndHeights():void
    {
        clearVector(typicalCellWidths, NaN);
        clearVector(typicalCellHeights, NaN);
        maxTypicalCellHeight = NaN;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods for handling dataProvider and column list changes
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Inserts count number of rows starting from startRow. This shifts
     *  any rows after startRow down by count and will increment 
     *  rowCount.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function insertRows(startRow:int, count:int):void
    {
        insertRowsAt(startRow, count);
    }
    
    /**
     *  Inserts count number of columns starting from startColumn. This
     *  shifts any columns after startColumn down by count and will
     *  increment columnCount. 
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function insertColumns(startColumn:int, count:int):void
    {
        const oldColumnCount:int = _columnCount;
        const newColumnCount:int = _columnCount + count;
        
        if (startColumn < 0 || startColumn > oldColumnCount)
            return;
        
        // change column count of all nodes in GridRowList.
        rowList.insertColumns(startColumn, count);
        
        // add to columnCount
        _columnCount = newColumnCount;
        
        // insert new values into the arrays.
        insertValueToVector(_columnWidths, startColumn, count, NaN);
        insertValueToVector(typicalCellWidths, startColumn, count, NaN);
        insertValueToVector(typicalCellHeights, startColumn, count, NaN);
    }
    
    /**
     *  Removes count number of rows starting from startRow. This
     *  shifts any rows after startRow up by count and will
     *  decrement rowCount.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function removeRows(startRow:int, count:int):void
    {
        removeRowsAt(startRow, count);
    }
    
    /**
     *  Removes count number of columns starting from startColumn. This
     *  shifts any columns after startColumn up by count and will
     *  decrement columnCount.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function removeColumns(startColumn:int, count:int):void
    {
        const oldColumnCount:int = _columnCount;
        const newColumnCount:int = _columnCount - count;
        
        if (startColumn < 0 || startColumn >= oldColumnCount)
            return;
        
        // if we remove all the columns, clear everything.
        if (newColumnCount <= 0)
        {
            columnCount = 0;
            return;
        }
        
        // Otherwise, lets remove the specified columns.
        // change column count of all nodes in GridRowList.
        rowList.removeColumns(startColumn, count)
        
        // lower columnCount without clearing anything else.
        _columnCount = newColumnCount;
        
        // remove values from the needed vectors
        _columnWidths.splice(startColumn, count);
        typicalCellWidths.splice(startColumn, count);
        typicalCellHeights.splice(startColumn, count);
        
        // bookmarks are invalid because row heights may have changed.
        clearCachedNodes();
    }
    
    /**
     *  Removes any nodes that occupy the indices between startRow
     *  and startRow + count.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function clearRows(startRow:int, count:int):void
    {
        if (startRow < 0 || count <= 0)
            return;
        
        var node:GridRowNode = rowList.findNearestLTE(startRow);
        var endRow:int = startRow + count;
        var oldNode:GridRowNode;
        
        if (node && node.rowIndex < startRow)
            node = node.next;
        
        while (node && node.rowIndex < endRow)
        {
            oldNode = node;
            node = node.next;
            rowList.removeNode(oldNode);
        }
        
        // bookmarks are invalid because row heights may have changed.
        clearCachedNodes();
    }
    
    /**
     *  Clears any columns that occupy the indices between startColumn
     *  and startColumn + count.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function clearColumns(startColumn:int, count:int):void
    {
        if (startColumn < 0 || startColumn >= _columnCount)
            return;
        
        rowList.clearColumns(startColumn, count);
        
        clearVector(typicalCellWidths, NaN, startColumn, count);
        clearVector(typicalCellHeights, NaN, startColumn, count);
        clearVector(_columnWidths, NaN, startColumn, count);
        
        // bookmarks are invalid because row heights may have changed.
        clearCachedNodes(); 
    }
        
    /**
     *  Moves count number of rows from the fromRow index to the toRow
     *  index. This operation will not affect rowCount.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function moveRows(fromRow:int, toRow:int, count:int):void
    {
        var rows:Vector.<GridRowNode> = removeRowsAt(fromRow, count);
        
        // Set the row indices of the nodes that are moving.
        var diff:int = toRow - fromRow;
        for each (var node:GridRowNode in rows)
        {
            node.rowIndex = node.rowIndex + diff;
        }
        
        insertRowsAt(toRow, count, rows);
    }
    
    /**
     *  Moves count number of columns from the fromCol index to the toCol
     *  index. This operation will not affect colCount.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function moveColumns(fromCol:int, toCol:int, count:int):void
    {
        if (fromCol < 0 || fromCol >= _columnCount || toCol < 0 || toCol > _columnCount)
            return;
        
        rowList.moveColumns(fromCol, toCol, count);
        
        insertElementsToVector(_columnWidths, toCol, _columnWidths.splice(fromCol, count));
        insertElementsToVector(typicalCellWidths, toCol, typicalCellWidths.splice(fromCol, count));
        insertElementsToVector(typicalCellHeights, toCol, typicalCellHeights.splice(fromCol, count));
    }
    
    /**
     *  Clears all cached heights.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function clearHeights():void
    {
        rowList.removeAll();
        clearCachedNodes();
    }
    
    /**
     *  @private
     *  Inserts count number of rows starting from startRow. This will increment 
     *  rowCount. If the nodes parameter is set, the nodes will be inserted
     *  to the rowList.
     */
    private function insertRowsAt(startRow:int, count:int, nodes:Vector.<GridRowNode> = null):void
    {
        // TODO (klin): Push this to GridRowList.
        
        if (startRow < 0 || count <= 0)
            return;
        
        var startNode:GridRowNode = rowList.findNearestLTE(startRow);
        var node:GridRowNode;
        
        if (startNode && startNode.rowIndex < startRow)
            startNode = startNode.next;
        
        // first we insert the nodes before this node if it exists,
        // if not, we just push it at the end.
        if (nodes)
        {
            if (startNode)
            {
                for each (node in nodes)
                    rowList.insertBefore(startNode, node);
            }
            else
            {
                for each (node in nodes)
                    rowList.push(node);
            }
        }
        
        // increment the index of nodes after the last node.
        node = startNode;
        while (node)
        {
            node.rowIndex += count;
            node = node.next;
        }
        
        this.rowCount += count;
        
        // bookmarks are invalid because row heights may have changed.
        clearCachedNodes();
    }
    
    /**
     *  @private
     *  Removes count number of rows starting from startRow. This will
     *  decrement rowCount. Returns any removed nodes.
     */
    private function removeRowsAt(startRow:int, count:int):Vector.<GridRowNode>
    {
        var vec:Vector.<GridRowNode> = new Vector.<GridRowNode>();
        if (startRow < 0 || count <= 0)
            return vec;
        
        var node:GridRowNode = rowList.findNearestLTE(startRow);
        var endRow:int = startRow + count;
        var oldNode:GridRowNode;
        
        if (node && node.rowIndex < startRow)
            node = node.next;
        
        while (node && node.rowIndex < endRow)
        {
            oldNode = node;
            vec.push(oldNode);
            node = node.next;
            rowList.removeNode(oldNode);
        }
        
        while (node)
        {
            node.rowIndex -= count;
            node = node.next;
        }
        
        _rowCount -= count;
        
        // bookmarks are invalid because row heights may have changed.
        clearCachedNodes();
        return vec;
    }
    
    /**
     *  Handles changes in the dataProvider.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function dataProviderCollectionChanged(event:CollectionEvent):void 
    {
        switch (event.kind)
        {
            case CollectionEventKind.ADD: 
            {
                insertRows(event.location, event.items.length);
                break;
            }
                
            case CollectionEventKind.REMOVE:
            {
                removeRows(event.location, event.items.length);
                break;
            }
                
            case CollectionEventKind.MOVE:
            {
                moveRows(event.oldLocation, event.location, event.items.length);
                break;
            }
                
            case CollectionEventKind.REFRESH:
            {
                clearHeights();
                break;
            }
                
            case CollectionEventKind.RESET:
            {
                clearHeights();
                clearTypicalCellWidthsAndHeights();
                break;
            }
                
            case CollectionEventKind.UPDATE:
            {
                // handled by GridLayout
                break;
            }
                
            case CollectionEventKind.REPLACE:
            {
                clearRows(event.location, event.items.length);
                break;
            }   
        }
    }
    
    /**
     *  Handles changes in columns.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */
    public function columnsCollectionChanged(event:CollectionEvent):void
    {
        switch (event.kind)
        {
            case CollectionEventKind.ADD: 
            {
                insertColumns(event.location, event.items.length);
                break;
            }
            
            case CollectionEventKind.REMOVE:
            {
                removeColumns(event.location, event.items.length);
                break;
            }
            
            case CollectionEventKind.MOVE:
            {
                moveColumns(event.oldLocation, event.location, event.items.length);
                break;
            }
                    
            case CollectionEventKind.REFRESH:
            case CollectionEventKind.RESET:
            {
                columnCount = IList(event.target).length;
                break;
            }
                
            case CollectionEventKind.UPDATE:
            {
                // column may have changed visiblity                
                var pcEvent:PropertyChangeEvent;
                
                const itemsLength:int = event.items ? event.items.length : 0;                
                for (var i:int = 0; i < itemsLength; i++)
                {
                    pcEvent = event.items[i] as PropertyChangeEvent;
                    if (pcEvent && pcEvent.property == "visible")
                        columns_visibleChangedHandler(pcEvent);
                }
                break;
            }
            
            case CollectionEventKind.REPLACE:
            {
                clearColumns(event.location, event.items.length);
                break;
            }
        }
    }
    
    /**
     *  @private
     *  Handle CollectionEventKind.UPDATE for a column whose 'visibility' 
     *  property changed.
     */
    private function columns_visibleChangedHandler(pcEvent:PropertyChangeEvent):void
    {
        const column:GridColumn = pcEvent.source as GridColumn;
        const columnIndex:int = column.columnIndex;
        if (!column || columnIndex < 0 || columnIndex >= _columnCount)
            return;
        
        clearColumns(columnIndex, 1);
        
        // column.visible==true columns need to have their typical sizes and 
        // actual column width updated, while column.visible==false column
        // have their typical sizes updated to 0 and actual column width
        // set to NaN.
        if (column.visible)
        {
            setTypicalCellWidth(columnIndex, NaN);
            setTypicalCellHeight(columnIndex, NaN);
            if (!isNaN(column.width))
                setColumnWidth(columnIndex, column.width);
        }
        else
        {
            setTypicalCellWidth(columnIndex, 0);
            setTypicalCellHeight(columnIndex, 0);
            setColumnWidth(columnIndex, NaN);
        }
    }
    
    /**
     *  @private
     *  For debugging purposes.
     */
    public function toString():String
    {
        return rowList.toString();
    }
}
}
