////////////////////////////////////////////////////////////////////////////////
//
//  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 temp:Number = _columnWidths[i];
            
            // fall back on typical widths if the actual width isn't set.
            if (isNaN(temp))
            {
                temp = typicalCellWidths[i];
                if (temp == 0) // invisible column
                    continue;
            }
            
            // fall back on defaultColumnWidth
            if (isNaN(temp))
                temp = defaultColumnWidth;
            
            current -= temp + 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();
    }
}
}
