////////////////////////////////////////////////////////////////////////////////
//
//  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
{
import flash.display.InteractiveObject;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.getTimer;

import mx.collections.ArrayList;
import mx.collections.IList;
import mx.core.IFactory;
import mx.core.IVisualElement;
import mx.core.UIComponent;
import mx.core.UIComponentGlobals;
import mx.core.mx_internal;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.FlexEvent;
import mx.events.PropertyChangeEvent;
import mx.graphics.SolidColorStroke;
import mx.utils.ObjectUtil;

import spark.collections.SubListView;
import spark.components.gridClasses.CellPosition;
import spark.components.gridClasses.GridDoubleClickMode;
import spark.components.gridClasses.GridColumn;
import spark.components.gridClasses.GridDimensions;
import spark.components.gridClasses.GridDimensionsView;
import spark.components.gridClasses.GridLayout;
import spark.components.gridClasses.GridSelection;
import spark.components.gridClasses.GridSelectionMode;
import spark.components.gridClasses.GridView;
import spark.components.gridClasses.GridViewLayout;
import spark.components.gridClasses.IDataGridElement;
import spark.components.gridClasses.IGridItemRenderer;
import spark.components.supportClasses.GroupBase;
import spark.components.supportClasses.IDataProviderEnhance;
import spark.components.supportClasses.RegExPatterns;
import spark.events.GridCaretEvent;
import spark.events.GridEvent;
import spark.layouts.VerticalLayout;
import spark.layouts.supportClasses.LayoutBase;
import spark.primitives.Line;
import spark.primitives.Rect;
import spark.utils.MouseEventUtil;

use namespace mx_internal;

//--------------------------------------
//  Events
//--------------------------------------

/**
 *  Dispatched when the mouse button is pressed over a Grid cell.
 *
 *  @eventType spark.events.GridEvent.GRID_MOUSE_DOWN
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridMouseDown", type="spark.events.GridEvent")]

/**
 *  Dispatched after a <code>gridMouseDown</code> event 
 *  if the mouse moves before the button is released.
 *
 *  @eventType spark.events.GridEvent.GRID_MOUSE_DRAG
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridMouseDrag", type="spark.events.GridEvent")]

/**
 *  Dispatched when the mouse button is released over a Grid cell.
 *  During a drag operation, it is also dispatched after a 
 *  <code>gridMouseDown</code> event 
 *  when the mouse button is released, even if the mouse is no longer 
 *  in the Grid.
 *
 *  @eventType spark.events.GridEvent.GRID_MOUSE_UP
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridMouseUp", type="spark.events.GridEvent")]

/**
 *  Dispatched when the mouse enters a grid cell.
 *
 *  @eventType spark.events.GridEvent.GRID_ROLL_OVER
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridRollOver", type="spark.events.GridEvent")]

/**
 *  Dispatched when the mouse leaves a grid cell.
 *
 *  @eventType spark.events.GridEvent.GRID_ROLL_OUT
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridRollOut", type="spark.events.GridEvent")]

/**
 *  Dispatched when the mouse is clicked over a cell
 *
 *  @eventType spark.events.GridEvent.GRID_CLICK
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridClick", type="spark.events.GridEvent")]

/**
 *  Dispatched when the mouse is double-clicked over a cell
 *
 *  @eventType spark.events.GridEvent.GRID_DOUBLE_CLICK
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridDoubleClick", type="spark.events.GridEvent")]

/**
 *  Dispatched after the caret changes.  
 *
 *  @eventType spark.events.GridCaretEvent.CARET_CHANGE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="caretChange", type="spark.events.GridCaretEvent")]

/**
 *  The Grid control displays a list of data items called
 *  its <i>data provider</i> in a scrollable table or "grid", one item per row.
 *  Each of the grid's columns, defined by a GridColumn object,
 *  displays a value based on the item for the corresponding row.
 *  The grid's data provider is mutable, meaning its items can be added or
 *  removed, or changed.  
 *  Similarly, the list of columns is mutable.
 * 
 *  <p>The Grid component is intended to be used as a DataGrid skin part, or
 *  as an element of other custom composite components.  
 *  Therefore, it is not skinnable, it does not include a scroller or scrollbars, 
 *  and it does not provide default mouse or keyboard event handling.</p>
 * 
 *  <p>Each visible Grid <i>cell</i> is displayed by a GridItemRenderer
 *  instance created by using the <code>itemRenderer</code> property.  
 *  specify an item renderer for each column.
 *  Before it is displayed, each item renderer instance is configured 
 *  with the value of the data provider item for that row.
 *  Item renderers are created as needed and then, to keep creation
 *  overhead to a minimum, pooled and recycled.</p>
 *
 *  <p>The Grid control supports a doubleClick event, according the <code>doubleClickMode</code>
 *  property.</p>
 * 
 *  <p>The Grid control supports selection, according the <code>selectionMode</code>
 *  property.  The set of selected row or cell indices can be modified or
 *  queried programatically using the selection methods, such as 
 *  <code>setSelectedIndex</code> or <code>selectionContainsIndex()</code>.</p>
 * 
 *  <p>The Grid control displays hover, caret, and selection indicators based  
 *  on the <code>selectionMode</code> property and the corresponding 
 *  row index and column index properties, such as 
 *  <code>hoverRowIndex</code> and <code>columnRowIndex</code>.   
 *  An indicator can be any visual element.  
 *  Indicators that implement IGridVisualElement can configure themselves 
 *  according to the row and column in which they are used.</p>
 * 
 *  <p>The Grid control supports smooth scrolling.  
 *  Their vertical and horizontal scroll positions define the pixel origin 
 *  of the visible part of the grid and the grid's layout only displays 
 *  as many cell item renderers as are needed to fill the available space.</p>
 *
 *  <p>The Grid control supports variable height rows that automatically compute 
 *  their height based on the item renderers' contents.  
 *  This support is called grid <i>virtualization</i>
 *  because the mapping from (pixel) scroll positions to row and column indices
 *  is typically based on incomplete information about the preferred sizes 
 *  for grid cells.  
 *  The Grid caches the computed heights of rows that have been
 *  scrolled into view and estimates the rest based on a single 
 *  <code>typicalItem</code>.</p>
 * 
 *  <p>Transitions in DataGrid item renderers aren't supported. The GridItemRenderer class 
 *  has disabled its <code>transitions</code> property so setting it will have no effect.</p>
 *
 *  @mxml <p>The <code>&lt;s:Grid&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:Grid 
 *    <strong>Properties</strong>
 *  /&gt;
 *  </pre>
 *
 *  @see DataGrid
 *  @see spark.components.gridClasses.GridColumn
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
public class Grid extends Group implements IDataGridElement, IDataProviderEnhance
{
    include "../core/Version.as";
	
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  A list of functions to be called at commitProperties() time, after the dataProvider
     *  has been set.  This list is used to defer making grid selection updates per the 
     *  set methods for the selectedIndex, selectedIndices, selectedItem, selectedItems, 
     *  selectedCell and selectedCells properties.
     */
    private const deferredOperations:Vector.<Function> = new Vector.<Function>();
    
    /**
     *  @private
     *  Cache the dataItem that goes with the caretRowIndex so we can find the
     *  rowIndex of the caret after a collection refresh event.
     */    
    private var caretSelectedItem:Object = null;
    private var updateCaretForDataProviderChanged:Boolean = false;
    private var updateCaretForDataProviderChangeLastEvent:CollectionEvent;
    
    /**
     *  @private
     *  True while updateDisplayList is running.  Use to disable invalidateSize(),
     *  invalidateDisplayList() here and in the GridLayer class.
     */
    mx_internal var inUpdateDisplayList:Boolean = false;  
    
    /**
     *  @private
     *  True while doing a drag operation with the mouse.
     */
    private var dragInProgress:Boolean = false;
    
    /**
     *  @private
     *  True if the columns were generated rather than explicitly set.
     */
    private var generatedColumns:Boolean = false;
    
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Constructor. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function Grid()
    {
        super();
        
        layout = new GridLayout();
        
        MouseEventUtil.addDownDragUpListeners(this, 
            grid_mouseDownDragUpHandler, 
            grid_mouseDownDragUpHandler, 
            grid_mouseDownDragUpHandler);
                    
        addEventListener(MouseEvent.MOUSE_UP, grid_mouseUpHandler);
        addEventListener(MouseEvent.MOUSE_MOVE, grid_mouseMoveHandler);
        addEventListener(MouseEvent.ROLL_OUT, grid_mouseRollOutHandler);      
    }
    
    /**
     *  @private
     *  Return the GridView which contains the specified cell.   If rowIndex == -1,
     *  then return the topmost GridView that contains the specified column and 
     *  if columnIndex == -1 then return the leftmost GridView that contains the specified row. 
     */
    private function getGridViewAt(rowIndex:int, columnIndex:int):GridView
    {
        if ((rowIndex < 0) && (columnIndex < 0))
            return null;
		
		const gridLayout:GridLayout = layout as GridLayout;
        
        if ((rowIndex >= lockedRowCount) || (rowIndex == -1))
        {
            if ((columnIndex >= lockedColumnCount) || (columnIndex == -1))
                return gridLayout.centerGridView;
            
            return gridLayout.leftGridView;
        }
        
        return (columnIndex < lockedColumnCount) ? gridLayout.topLeftGridView : gridLayout.topGridView;
    }
    
    
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    private function dispatchChangeEvent(type:String):void
    {
        if (hasEventListener(type))
            dispatchEvent(new Event(type));
    }
    
    /**
     *  @private
     */
    private function dispatchFlexEvent(type:String):void
    {
        if (hasEventListener(type))
            dispatchEvent(new FlexEvent(type));
    }
    
    //----------------------------------
    //  anchorColumnIndex
    //----------------------------------
    
    private var _anchorColumnIndex:int = 0;
    
    /**
     *  @private
     *  True if either anchorColumnIndex or anchorRowIndex changes.
     */
    private var anchorChanged:Boolean = false;
    
    [Bindable("anchorColumnIndexChanged")]
    
    /**
     *  The column index of the <i>anchor</i> for the next shift selection.
     *  The anchor is the item most recently selected. 
     *  It defines the anchor item when selecting multiple items in the grid. 
     *  When you select multiple items, the set of items extends from 
     *  the anchor to the caret item.
     *
     *  <p>Grid event handlers should use this property to record the
     *  location of the most recent unshifted mouse down or keyboard
     *  event that defines one end of the next potential shift
     *  selection.  
     *  The caret index defines the other end.</p>
     * 
     *  @default 0
     * 
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#caretColumnIndex
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get anchorColumnIndex():int
    {
        return _anchorColumnIndex;
    }
    
    /**
     *  @private
     */
    public function set anchorColumnIndex(value:int):void
    {
        if (_anchorColumnIndex == value || 
            selectionMode == GridSelectionMode.SINGLE_ROW || 
            selectionMode == GridSelectionMode.MULTIPLE_ROWS)
        {
            return;
        }
        
		_anchorColumnIndex = value;
        
        anchorChanged = true;
        invalidateProperties();
        
        dispatchChangeEvent("anchorColumnIndexChanged");
    }
    
    //----------------------------------
    //  anchorRowIndex
    //----------------------------------
    
    private var _anchorRowIndex:int = 0; 
    
    [Bindable("anchorRowIndexChanged")]
    
    /**
     *  The row index of the <i>anchor</i> for the next shift selection.
     *  The anchor is the item most recently selected. 
     *  It defines the anchor item when selecting multiple items in the grid. 
     *  When you select multiple items, the set of items extends from 
     *  the anchor to the caret item.
     *
     *  <p>Grid event handlers should use this property to record the
     *  location of the most recent unshifted mouse down or keyboard
     *  event that defines one end of the next potential shift
     *  selection.  
     *  The caret index defines the other end.</p>
     * 
     *  @default 0
     *
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#caretColumnIndex
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get anchorRowIndex():int
    {
        return _anchorRowIndex;
    }
    
    /**
     *  @private
     */
    public function set anchorRowIndex(value:int):void
    {
        if (_anchorRowIndex == value)
            return;
        
        _anchorRowIndex = value;
        
        anchorChanged = true;
        invalidateProperties();
        
        dispatchChangeEvent("anchorRowIndexChanged");
    }
    
    //----------------------------------
    //  caretIndicator
    //----------------------------------
    
    private var _caretIndicator:IFactory = null;
    
    [Bindable("caretIndicatorChanged")]
    
    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> or
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
     *  a single visual element displayed for the caret row, 
     *  If <code>selectionMode</code> is
     *  <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, the
     *  visual element displayed for the caret cell.
     *  
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get caretIndicator():IFactory
    {
        return _caretIndicator;
    }
    
    /**
     *  @private
     */
    public function set caretIndicator(value:IFactory):void
    {
        if (_caretIndicator == value)
            return;
        
        _caretIndicator = value;
        invalidateDisplayListFor("caretIndicator");
        dispatchChangeEvent("caretIndicatorChanged");
    }    
    
    //----------------------------------
    //  caretColumnIndex
    //----------------------------------
    
    private var _caretColumnIndex:int = -1;
    private var _oldCaretColumnIndex:int = -1;
    private var caretChanged:Boolean = false;
    
    [Bindable("caretColumnIndexChanged")]
    
    /**
     *  If <code>showCaretIndicator</code> is <code>true</code>,
     *  the column index of the <code>caretIndicator</code>.
     
     *  <p>If <code>selectionMode</code> is
     *  <code>GridSelectionMode.SINGLE_ROW</code> or
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code> then the indicator
     *  occupies the entire row and <code>caretColumnIndex</code> is ignored.  
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, then the 
     *  <code>caretIndicator</code> occupies the specified cell.</p>
     * 
     *  <p>Setting <code>caretColumnIndex</code> to -1 means that the column 
     *  index is undefined and a cell caret is not shown.</p>
     *  
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get caretColumnIndex():int
    {
        return _caretColumnIndex;
    }
    
    /**
     *  @private
     */
    public function set caretColumnIndex(value:int):void
    {
        if (_caretColumnIndex == value || value < -1)
            return;
        
        _caretColumnIndex = value;
        
        caretChanged = true;
        invalidateProperties();
        
        // Unconditionally invalidate because renderers may depend on
        // caretColumnIndex even when the caretIndicator doesn't exist.
        invalidateDisplayListFor("caretIndicator");         
        dispatchChangeEvent("caretColumnIndexChanged");
    }
    
    //----------------------------------
    //  caretRowIndex
    //----------------------------------
    
    private var _caretRowIndex:int = -1;
    private var _oldCaretRowIndex:int = -1;
    
    [Bindable("caretRowIndexChanged")]
    
    /**
     *  If <code>showCaretIndicator</code> is <code>true</code>,   
     *  the row index of the <code>caretIndicator</code>.
     *  If <code>selectionMode</code> is
     *  <code>GridSelectionMode.SINGLE_ROW</code> or
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code> then the indicator
     *  occupies the entire row and the <code>caretColumnIndex</code> 
     *  property is ignored.  
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, then the <code>caretIndicator</code>
     *  occupies the specified cell.
     * 
     *  <p>Setting <code>caretRowIndex</code> to -1 means that the row index 
     *  is undefined and the caret will not be shown.</p>
     * 
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get caretRowIndex():int
    {
        return _caretRowIndex;
    }
    
    /**
     *  @private
     */
    public function set caretRowIndex(value:int):void
    {
        if (_caretRowIndex == value || value < -1)
            return;
        
        _caretRowIndex = value;
        
        caretChanged = true;
        invalidateProperties();

        // Unconditionally invalidate because renderers may depend on
        // caretRowIndex even when the caretIndicator doesn't exist.
        invalidateDisplayListFor("caretIndicator");         
        dispatchChangeEvent("caretRowIndexChanged");
    }
	
    //----------------------------------
    //  clipAndEnableScrolling (private override)
    //----------------------------------

    private var _clipAndEnableScrolling:Boolean = false;
    
    /**
     *  @private
     */
    override public function get clipAndEnableScrolling():Boolean 
    {
        return _clipAndEnableScrolling;
    }
    
    /**
     *  @private
     */
    override public function set clipAndEnableScrolling(value:Boolean):void 
    {
        if (value == _clipAndEnableScrolling)
            return;
        
        _clipAndEnableScrolling = value;
		
		const gridLayout:GridLayout = layout as GridLayout;
		const topGridView:GridView = gridLayout.topGridView;        
		const leftGridView:GridView = gridLayout.leftGridView;
		const centerGridView:GridView = gridLayout.centerGridView;		
        
        if (topGridView) topGridView.clipAndEnableScrolling = value;
        if (leftGridView) leftGridView.clipAndEnableScrolling = value;
        if (centerGridView) centerGridView.clipAndEnableScrolling = value;
    }
        
    
    //----------------------------------
    //  contentHeight (private get override)
    //---------------------------------- 
    
    /**
     *  @private
     */
    override public function get contentHeight():Number 
    {
        return Math.ceil(gridDimensions.getContentHeight());
    }
    
    //----------------------------------
    //  contentWidth (private get override)
    //---------------------------------- 
    
    /**
     *  @private
     */    
    override public function get contentWidth():Number 
    {
        return Math.ceil(gridDimensions.getContentWidth());
    }
    
    //----------------------------------
    //  horizontalScrollPosition (private override)
    //----------------------------------
    
    private var _horizontalScrollPosition:Number = 0;
    
    [Bindable]
    [Inspectable(minValue="0.0")] 
    
    /**
     *  @copy spark.core.IViewport#horizontalScrollPosition
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function get horizontalScrollPosition():Number 
    {
        return _horizontalScrollPosition;
    }
    
    /**
     *  @private
     */
    override public function set horizontalScrollPosition(value:Number):void 
    {
        if (_horizontalScrollPosition == value)
            return;
                
		const gridLayout:GridLayout = layout as GridLayout;
		const topGridView:GridView = gridLayout.topGridView;        
		const centerGridView:GridView = gridLayout.centerGridView;	
		
        if (centerGridView)
        {
            const gridViewLayout:GridViewLayout = centerGridView.gridViewLayout;
            const gridMaxHSP:Number = contentWidth - width;
	        const centerContentWidth:Number = Math.ceil(gridViewLayout.gridDimensionsView.getContentWidth());
	        const centerMaxHSP:Number = centerContentWidth - centerGridView.width;
			const hsp:Number = (gridMaxHSP > 0) ? (centerMaxHSP / gridMaxHSP) * value : 0;

            centerGridView.horizontalScrollPosition = hsp;
            
            if (topGridView)
                topGridView.horizontalScrollPosition = hsp;
        }
                
        _horizontalScrollPosition = value;
    }


    //----------------------------------
    //  isFirstRow
    //----------------------------------

    /**
    *  Returns if the selectedIndex is equal to the first row.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function get isFirstRow():Boolean
    {
        if (dataProvider && dataProvider.length > 0)
        {
            if (selectedIndex == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }


    //----------------------------------
    //  isLastRow
    //----------------------------------

    /**
    *  Returns if the selectedIndex is equal to the last row.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function get isLastRow():Boolean
    {
        if (dataProvider && dataProvider.length > 0)
        {
            if (selectedIndex == dataProvider.length - 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }


    //----------------------------------
    //  verticalScrollPosition (private override)
    //----------------------------------
    
    private var _verticalScrollPosition:Number = 0;
    
    [Bindable]
    [Inspectable(minValue="0.0")] 
    
    /**
     *  @copy spark.core.IViewport#verticalScrollPosition
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function get verticalScrollPosition():Number 
    {
        return _verticalScrollPosition;
    }
    
    /**
     *  @private
     */
    override public function set verticalScrollPosition(value:Number):void 
    {
        if (_verticalScrollPosition == value)
            return;
        
		const gridLayout:GridLayout = layout as GridLayout;
		const leftGridView:GridView = gridLayout.leftGridView;
		const centerGridView:GridView = gridLayout.centerGridView;	
		
        if (centerGridView)
        {
            const gridViewLayout:GridViewLayout = centerGridView.gridViewLayout;
            const gridMaxVSP:Number = contentHeight - height;
            const centerContentHeight:Number = Math.ceil(gridViewLayout.gridDimensionsView.getContentHeight());
            const centerMaxVSP:Number = centerContentHeight - centerGridView.height;
            const vsp:Number = (gridMaxVSP > 0) ? (centerMaxVSP / gridMaxVSP) * value : 0;
            
            centerGridView.verticalScrollPosition = vsp;
            
            if (leftGridView)
                leftGridView.verticalScrollPosition = vsp;
        }
        
        _verticalScrollPosition = value;
    }
    
    //----------------------------------
    //  hoverIndicator
    //----------------------------------
    
    private var _hoverIndicator:IFactory = null;
    
    [Bindable("hoverIndicatorChanged")]
    
    /**
     *  If <code>selectionMode</code> is
     *  <code>GridSelectionMode.SINGLE_ROW</code> or
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>. 
     *  a single visual element displayed for the row under the mouse.
     *  If <code>selectionMode</code> is
     *  <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>,
     *  the visual element for the cell.
     * 
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get hoverIndicator():IFactory
    {
        return _hoverIndicator;
    }
    
    /**
     *  @private
     */
    public function set hoverIndicator(value:IFactory):void
    {
        if (_hoverIndicator == value)
            return;
        
        _hoverIndicator = value;
        invalidateDisplayListFor("hoverIndicator");
        dispatchChangeEvent("hoverIndicatorChanged");
    }    
    
    //----------------------------------
    //  hoverColumnIndex 
    //----------------------------------
    
    private var _hoverColumnIndex:int = -1;
    
    [Bindable("hoverColumnIndexChanged")]
    
    /**
     *  If <code>showHoverIndicator</code> is <code>true</code>,  
     *  Specifies column index of the <code>hoverIndicator</code>.
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> or
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, then the indicator
     *  occupies the entire row and <code>hoverColumnIndex</code> is ignored. 
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code> then the <code>hoverIndicator</code>
     *  occupies the specified cell.
     *  
     *  <p>Setting <code>hoverColumnIndex</code> to -1 (the default) means 
     *  that the column index is undefined and a cell hover indicator is not displayed.</p>
     * 
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get hoverColumnIndex():int
    {
        return _hoverColumnIndex;
    }
    
    /**
     *  @private
     */
    public function set hoverColumnIndex(value:int):void
    {
        if (_hoverColumnIndex == value)
            return;
        
        _hoverColumnIndex = value;

        // Unconditionally invalidate because renderers may depend on
        // hoverColumnIndex even when the hoverIndicator doesn't exist.
        invalidateDisplayListFor("hoverIndicator");
        dispatchChangeEvent("hoverColumnIndexChanged");
    }
    
    //----------------------------------
    //  hoverRowIndex
    //----------------------------------
    
    private var _hoverRowIndex:int = -1;

    [Bindable("hoverRowIndexChanged")]
    
    /**
     *  If <code>showHoverIndicator</code> is <code>true</code>,  
     *  specifies the column index of the <code>hoverIndicator</code>.
     *  If <code>selectionMode</code> is
     *  <code>GridSelectionMode.SINGLE_ROW</code> or
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, then the indicator
     *  occupies the entire row and <code>hoverColumnIndex</code> is ignored.   
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code> then the <code>hoverIndicator</code>
     *  occupies the specified cell.
     * 
     *  <p>Setting <code>hoverRowIndex</code> to -1,the default, means that 
     *  the row index is undefined and a hover indicator is not displayed.</p>
     * 
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get hoverRowIndex():int
    {
        return _hoverRowIndex;
    }
    
    /**
     *  @private
     */
    public function set hoverRowIndex(value:int):void
    {
        if (_hoverRowIndex == value)
            return;
        
        _hoverRowIndex = value;

        // Unconditionally invalidate because renderers may depend on
        // hoverRowIndex even when the hoverIndicator doesn't exist.
        invalidateDisplayListFor("hoverIndicator");           
        dispatchChangeEvent("hoverRowIndexChanged");
    }
    
    //----------------------------------
    //  columns
    //----------------------------------    
    
    private var _columns:IList = null;
    private var columnsChanged:Boolean = false;
    
    [Bindable("columnsChanged")]
    [Inspectable(category="General")]
    
    /**
     *  The list of GridColumn objectss displayed by this grid.  
     *  Each column selects different data provider item properties 
     *  to display.
     *  
     *  <p>GridColumn objects can only appear in the <code>columns</code> 
     *  for a single Grid control.</p> 
     *  
     *  @default null
     * 
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get columns():IList
    {
        return _columns;
    }
    
    /**
     *  @private
     */
    public function set columns(value:IList):void
    {
        if (_columns == value)
            return;
        
        // Remove the old column listener, and set each column's grid=null, columnIndex=-1.
        
        const oldColumns:IList = _columns;
        if (oldColumns)
        {
            oldColumns.removeEventListener(CollectionEvent.COLLECTION_CHANGE, columns_collectionChangeHandler);
            for (var index:int = 0; index < oldColumns.length; index++)
            {
                var oldColumn:GridColumn = GridColumn(oldColumns.getItemAt(index));
                oldColumn.setGrid(null);
                oldColumn.setColumnIndex(-1);
            }
        }
        
        _columns = value; 
        
        // Add the new columns listener, and set their grid,columnIndex properties.
        // The listener is a local method, so creating a weak reference to it (last 
        // addEventListener parameter) is safe, since the listener's lifetime is the 
        // same as this object.        
        
        const newColumns:IList = _columns;
        if (newColumns)
        {
            newColumns.addEventListener(CollectionEvent.COLLECTION_CHANGE, columns_collectionChangeHandler, false, 0, true);
            for (index = 0; index < newColumns.length; index++)
            {
                var newColumn:GridColumn = GridColumn(newColumns.getItemAt(index));
                newColumn.setGrid(this);
                newColumn.setColumnIndex(index);
            }
        }
                                   
        columnsChanged = true;
        generatedColumns = false;        
        invalidateProperties();
        invalidateSize();
        invalidateDisplayList();
        
        dispatchChangeEvent("columnsChanged");             
    }
    
    /**
     *  @private
     */
    private function getColumnsLength():uint
    {
        const columns:IList = columns;
        return (columns) ? columns.length : 0;
    }
    
    /**
     *  @private
     *  This method is similar to mx.controls.DataGrid/ls().
     */
    private function generateColumns():IList
    {
        var item:Object = typicalItem;
        if (!item && dataProvider && (dataProvider.length > 0))
            item = dataProvider.getItemAt(0);
        
        var itemColumns:IList = null;
        if (item)
        {
            itemColumns = new ArrayList();
            const classInfo:Object = ObjectUtil.getClassInfo(item, ["uid", "mx_internal_uid"]);
            if (classInfo)
            {
                for each (var property:QName in classInfo.properties)
                {
                    var column:GridColumn = new GridColumn();
                    column.dataField = property.localName;
                    itemColumns.addItem(column);                        
                }
            }
        }
        
        return itemColumns;
    }
    
    //----------------------------------
    //  dataProvider
    //----------------------------------
    
    private var _dataProvider:IList = null;
    private var dataProviderChanged:Boolean;
    
    [Bindable("dataProviderChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  A list of data items that correspond to the rows in the grid.   
     *  Each grid column is associated with a property of the 
     *  data items to display that property in the grid <i>cells</i>.
     * 
     *  @default null
     * 
     *  @see spark.components.Grid#columns
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get dataProvider():IList
    {
        return _dataProvider;
    }
    
    /**
     *  @private
     */
    public function set dataProvider(value:IList):void
    {
        if (_dataProvider == value)
            return;
        
        const oldDataProvider:IList = dataProvider;
        if (oldDataProvider)
            oldDataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler);
        
        _dataProvider = value;
        
        // The listener is a local method, so creating a weak reference to it (last addEventListener 
        // parameter) is safe, since the listener's lifetime is the same as this object.
        
        const newDataProvider:IList = dataProvider;
        if (newDataProvider)
            newDataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, dataProvider_collectionChangeHandler, false, 0, true);        
       
        dataProviderChanged = true;
        invalidateProperties();
        invalidateSize();
        invalidateDisplayList();
        
        dispatchChangeEvent("dataProviderChanged");
    }
    
    //----------------------------------
    //  dataTipField
    //----------------------------------
    
    private var _dataTipField:String = null;
    
    [Bindable("dataTipFieldChanged")]
    [Inspectable(category="Data", defaultValue="null")]
    
    /**
     *  @copy spark.components.gridClasses.GridColumn#dataTipField
     * 
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get dataTipField():String
    {
        return _dataTipField;
    }
    
    /**
     *  @private
     */
    public function set dataTipField(value:String):void
    {
        if (_dataTipField == value)
            return;
        
        _dataTipField = value;
        invalidateDisplayList();
        dispatchChangeEvent("dataTipFieldChanged");
    }
    
    //----------------------------------
    //  dataTipFunction
    //----------------------------------
    
    private var _dataTipFunction:Function = null;
    
    [Bindable("dataTipFunctionChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.gridClasses.GridColumn#dataTipFunction
     *
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get dataTipFunction():Function
    {
        return _dataTipFunction;
    }
    
    /**
     *  @private
     */
    public function set dataTipFunction(value:Function):void
    {
        if (_dataTipFunction == value)
            return;
        
        _dataTipFunction = value;
        invalidateDisplayList();        
        dispatchChangeEvent("dataTipFunctionChanged");
    }    


    //----------------------------------
    //  doubleClickMode
    //----------------------------------
    private var _doubleClickMode:String = GridDoubleClickMode.ROW;

    [Bindable("doubleClickModeChanged")]
    [Inspectable(category="General", enumeration="cell,grid,row", defaultValue="row")]
    
    /**
     *  The doubleClick mode of the control.  Possible values are:
     *  <code>GridDoubleClickMode.CELL</code>, 
     *  <code>GridDoubleClickMode.GRID</code>, 
     *  <code>GridDoubleClickMode.ROW</code>, 
     * 
     *  <p>Changing the doubleClickMode changes the double click
     *  criteria for firing the doubleClick event</p>
     *
     *  @default GridDoubleClickMode.ROW
     * 
     *  @see spark.components.gridClasses.GridDoubleClickMode
     * 
     *  @langversion 3.0
     *  @playerversion Flash 11.1
     *  @playerversion AIR 3.4
     *  @productversion Flex 4.10
     */
    public function get doubleClickMode():String
    {
        return _doubleClickMode;
    }

    /**
    *  @private
    */
    public function set doubleClickMode(newValue:String):void
    {
        if (newValue == _doubleClickMode)
        {
            return;
        }

        switch(newValue)
        {
            case GridDoubleClickMode.CELL:
            case GridDoubleClickMode.GRID:
            case GridDoubleClickMode.ROW:
            {
                _doubleClickMode = newValue;

                dispatchChangeEvent("doubleClickModeChanged");

                break;
            }
        }
    }


    //----------------------------------
    //  gridDimensions (mx_internal)
    //----------------------------------
    
    private var _gridDimensions:GridDimensions = null;
    
    mx_internal function get gridDimensions():GridDimensions
    {
        if (!_gridDimensions)
            _gridDimensions = new GridDimensions();
        
        return _gridDimensions;
    }
    
    //----------------------------------
    //  itemRenderer
    //----------------------------------
    
    private var _itemRenderer:IFactory = null;
    private var itemRendererChanged:Boolean = false;
    
    [Bindable("itemRendererChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  The item renderer that's used for columns that do not specify one.
     * 
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get itemRenderer():IFactory
    {
        return _itemRenderer;
    }
    
    /**
     *  @private
     */
    public function set itemRenderer(value:IFactory):void
    {
        if (_itemRenderer == value)
            return;
        
        _itemRenderer = value;
        
        itemRendererChanged = true;
        invalidateProperties();
        invalidateSize();
        invalidateDisplayList();
        
        dispatchChangeEvent("itemRendererChanged");
    }    
    
    //----------------------------------
    //  columnSeparator
    //----------------------------------
    
    private var _columnSeparator:IFactory = null;
    
    [Bindable("columnSeparatorChanged")]
    
    /**
     *  A visual element displayed between each column.
     * 
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get columnSeparator():IFactory
    {
        return _columnSeparator;
    }
    
    /**
     *  @private
     */
    public function set columnSeparator(value:IFactory):void
    {
        if (_columnSeparator == value)
            return;
        
        _columnSeparator = value;
        invalidateDisplayList();
        dispatchChangeEvent("columnSeparatorChanged");
    }    
    
    //----------------------------------
    //  gridSelection (mx_internal)
    //----------------------------------
    
    private var _gridSelection:GridSelection;
    
    /**
     *  @private
     */
    mx_internal function get gridSelection():GridSelection
    {
        if (!_gridSelection)
            _gridSelection = createGridSelection();
        
        return _gridSelection;
    }
    
    /**
     *  @private
     *  If this Grid is serving as a DataGrid skin part, then this property is created 
     *  by DataGrid/partAdded() and then set here.   It is only set once, unless that 
     *  "grid" part is removed, at which point it's set to null.
     */
    mx_internal function set gridSelection(value:GridSelection):void
    {
        _gridSelection = value;
    }
    
    //----------------------------------
    //  dataGrid
    //----------------------------------
    
    private var _dataGrid:DataGrid = null;
    
    [Bindable("dataGridChanged")]
    
    /**
     *  The DataGrid control for which this Grid is used as the grid skin part.
     * 
     *  @default null
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get dataGrid():DataGrid
    {
        return _dataGrid;
    }
    
    /**
     *  @private
     */
    public function set dataGrid(value:DataGrid):void
    {
        if (_dataGrid == value)
            return;
        
        _dataGrid = value;
        dispatchChangeEvent("dataGridChanged");
    }
	
    //----------------------------------
    //  lockedColumnCount
    //----------------------------------
    
    private var _lockedColumnCount:int = 0;
    
    [Bindable("lockedColumnCountChanged")]
	[Inspectable(category="General", defaultValue="0", minValue="0")]	
    
    /**
     *  The first lockedColumnCount columns are "locked", i.e. they do not scroll horizontally. 
	 *  If lockedColumnCount is zero (the default) then changes to the horizontalScrollPosition
	 *  affect all columns.
	 * 
	 *  <p>The locked columns are displayed in the topGridView and, if lockedRowCount is also
	 *  greater than zero, the topLeftGridView.  The locked columns are separated from the remaining 
	 *  columns by a lockedColumnSeparator.</p>
     * 
     *  @default 0
	 * 
	 *  @see spark.components.gridClasses.GridColumn#topGridView 
	 *  @see spark.components.gridClasses.GridColumn#topLeftGridView
	 * 	@see spark.components.gridClasses.GridColumn#lockedColumnSeparator
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public function get lockedColumnCount():int
    {
        return _lockedColumnCount;
    }
    
    /**
     *  @private
     */
    public function set lockedColumnCount(value:int):void
    {
        if (_lockedColumnCount == value)
            return;
        
		invalidateProperties();
        invalidateSize();
        invalidateDisplayList();
        
        _lockedColumnCount = value;
        dispatchChangeEvent("lockedColumnCountChanged");
    }
    
    //----------------------------------
    //  lockedColumnsSeparator
    //----------------------------------
    
    private var _lockedColumnsSeparator:IFactory = null;
    
    [Bindable("lockedColumnsSeparatorChanged")]
    
    /**
     *  A visual element displayed between the locked and unlocked columns.  The factory value of this
	 *  property is used to create the lockedColumnsSeparatorElement.
	 * 
	 *  @see spark.components.Grid#lockedRowsSeparatorElement	
	 * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     * 
     *  @default null
     */
    public function get lockedColumnsSeparator():IFactory
    {
        return _lockedColumnsSeparator;
    }
    
    /**
     *  @private
     */
    public function set lockedColumnsSeparator(value:IFactory):void
    {
        if (_lockedColumnsSeparator == value)
            return;
        
        _lockedColumnsSeparator = value;
        invalidateDisplayList();
        dispatchChangeEvent("lockedColumnsSeparatorChanged");
    } 
    
    //----------------------------------
    //  lockedRowCount
    //----------------------------------
    
    private var _lockedRowCount:int = 0;
    
    [Bindable("lockedRowCountChanged")]
	[Inspectable(category="General", defaultValue="0", minValue="0")]	
    
    /**
     *  The first lockedRowCount rows are "locked", i.e. they do not scroll vertically. 
	 *  If lockedRowCount is zero (the default) then changes to the verticalScrollPosition
	 *  affect all rows.
	 * 
	 *  <p>The locked rows are displayed in the leftGridView and, if lockedColumnCount is also
	 *  greater than zero, the topLeftGridView.  The locked rows are separated from the remaining 
	 *  rows by a lockedRowSeparator.</p>
     * 
     *  @default 0
	 * 
	 *  @see spark.components.gridClasses.GridColumn#leftGridView 
	 *  @see spark.components.gridClasses.GridColumn#topLeftGridView
	 * 	@see spark.components.gridClasses.GridColumn#lockedRowSeparator
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public function get lockedRowCount():int
    {
        return _lockedRowCount;
    }
    
    /**
     *  @private
     */
    public function set lockedRowCount(value:int):void
    {
        if (_lockedRowCount == value)
            return;
        
		invalidateProperties();
        invalidateSize();
        invalidateDisplayList();
        
        _lockedRowCount = value;
        dispatchChangeEvent("lockedRowCountChanged");
    }
    
    //----------------------------------
    //  lockedRowsSeparator
    //----------------------------------
    
    private var _lockedRowsSeparator:IFactory = null;
    
    [Bindable("lockedRowsSeparatorChanged")]
    
    /**
     *  A visual element displayed between the locked and unlocked rows.   The factory value of this
	 *  property is used to create the lockedRowsSeparatorElement.
     * 
     *  @default null
	 * 
	 *  @see spark.components.Grid#lockedRowsSeparatorElement
	 * 
	 *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public function get lockedRowsSeparator():IFactory
    {
        return _lockedRowsSeparator;
    }
    
    /**
     *  @private
     */
    public function set lockedRowsSeparator(value:IFactory):void
    {
        if (_lockedRowsSeparator == value)
            return;
        
        _lockedRowsSeparator = value;
        invalidateDisplayList();
        dispatchChangeEvent("lockedRowsSeparatorChanged");
    }	
    
    //----------------------------------
    //  preserveSelection (delegates to gridSelection.preserveSelection)
    //----------------------------------
    
    [Inspectable(category="General", defaultValue="true")]
    
    /**
     *  If <code>true</code>, the selection is preserved when the data provider 
     *  refreshes its collection. 
     *  Because this refresh requires each item in the selection to be saved, 
     *  this action is not desirable if the selection is large.
     *
     *  @default true
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get preserveSelection():Boolean
    {
        return gridSelection.preserveSelection;
    }
    
    /**
     *  @private
     */    
    public function set preserveSelection(value:Boolean):void
    {
        gridSelection.preserveSelection = value;
    }
    
    //----------------------------------
    //  requestedMaxRowCount
    //----------------------------------
    
    private var _requestedMaxRowCount:int = 10;
    
    [Inspectable(category="General", defaultValue="10", minValue="-1")]
    
    /**
     *  The measured height of the grid is large enough to display 
     *  no more than <code>requestedMaxRowCount</code> rows.
     * 
     *  <p>This property has no effect if any of the following are true;
     *  <ul>
     *      <li><code>requestedRowCount</code> is set.</li>
     *      <li>The actual size of the grid has been explicitly set.</li>
     *  </ul>
     *  </p>
     * 
     *  @default 10
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedMaxRowCount():int
    {
        return _requestedMaxRowCount;
    }
    
    /**
     *  @private
     */
    public function set requestedMaxRowCount(value:int):void
    {
        if (_requestedMaxRowCount == value)
            return;
        
        _requestedMaxRowCount = value;
        invalidateSize();
    }      
    
    //----------------------------------
    //  requestedMinRowCount
    //----------------------------------
    
    private var _requestedMinRowCount:int = -1;
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  The measured height of this grid is large enough to display 
     *  at least <code>requestedMinRowCount</code> rows.
     * 
     *  <p>This property has no effect if any of the following are true;
     *  <ul>
     *      <li><code>requestedRowCount</code> is set.</li>
     *      <li>The actual size of the grid has been explicitly set.</li>
     *  </ul>
     *  </p>
     * 
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedMinRowCount():int
    {
        return _requestedMinRowCount;
    }
    
    /**
     *  @private
     */
    public function set requestedMinRowCount(value:int):void
    {
        if (_requestedMinRowCount == value)
            return;
        
        _requestedMinRowCount = value;
        invalidateSize();
    }    
    
    //----------------------------------
    //  requestedRowCount
    //----------------------------------
    
    private var _requestedRowCount:int = -1;
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  The measured height of this grid is large enough to display 
     *  the first <code>requestedRowCount</code> rows. 
     * 
     *  <p>If <code>requestedRowCount</code> is -1, then the measured
     *  size will be big enough for all of the layout elements.</p>
     * 
     *  <p>If the actual size of the grid has been explicitly set,
     *  then this property has no effect.</p>
     * 
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4
     */
    public function get requestedRowCount():int
    {
        return _requestedRowCount;
    }
    
    /**
     *  @private
     */
    public function set requestedRowCount(value:int):void
    {
        if (_requestedRowCount == value)
            return;
        
        _requestedRowCount = value;
        invalidateSize();
    }
    
    //----------------------------------
    //  requestedMinColumnCount
    //----------------------------------
    
    private var _requestedMinColumnCount:int = -1;
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  The measured width of this grid is large enough to display 
     *  at least <code>requestedMinColumnCount</code> columns.
     * 
     *  <p>This property has no effect if any of the following are true;
     *  <ul>
     *      <li><code>requestedColumnCount</code> is set.</li>
     *      <li>The actual size of the grid has been explicitly set.</li>
     *      <li>The grid is inside a Scroller component.</li>
     *  </ul>
     *  </p>
     *  
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedMinColumnCount():int
    {
        return _requestedMinColumnCount;
    }
    
    /**
     *  @private
     */
    public function set requestedMinColumnCount(value:int):void
    {
        if (_requestedMinColumnCount == value)
            return;
        
        _requestedMinColumnCount = value;
        invalidateSize();
    }   
    
    //----------------------------------
    //  requestedColumnCount
    //----------------------------------
    
    private var _requestedColumnCount:int = -1;
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  The measured width of this grid is large enough to display 
     *  the first <code>requestedColumnCount</code> columns. 
     *  If <code>requestedColumnCount</code> is -1, then the measured
     *  width is big enough for all of the columns.
     * 
     *  <p>If the actual size of the grid has been explicitly set,
     *  then this property has no effect.</p>
     * 
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedColumnCount():int
    {
        return _requestedColumnCount;
    }
    
    /**
     *  @private
     */
    public function set requestedColumnCount(value:int):void
    {
        if (_requestedColumnCount == value)
            return;
        
        _requestedColumnCount = value;
        invalidateSize();
    }    
    
    //----------------------------------
    //  requireSelection
    //----------------------------------
    
    [Inspectable(category="General", defaultValue="false")]
    
    /**
     *  If <code>true</code> and the <code>selectionMode</code> property is not 
     *  <code>GridSelectionMode.NONE</code>, an item must always be selected 
     *  in the grid.
     *
     *  @default false
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requireSelection():Boolean
    {
        return gridSelection.requireSelection;
    }
    
    /**
     *  @private
     */    
    public function set requireSelection(value:Boolean):void
    {
        gridSelection.requireSelection = value;
        
        if (value)
            invalidateDisplayListFor("selectionIndicator");
    }
 
    //----------------------------------
    //  resizableColumns
    //----------------------------------
    
    private var _resizableColumns:Boolean = true;
    
    [Bindable("resizableColumnsChanged")]
    [Inspectable(category="General", defaultValue="true")]
    
    /**
     *  Indicates whether the user can change the size of the columns.
     *  If <code>true</code>, the user can stretch or shrink the columns of 
     *  the DataGrid control by dragging the grid lines between the header cells.
     *  If <code>true</code>, individual columns must also have their 
     *  <code>resizable</code> properties set to <code>false</code> to 
     *  prevent the user from resizing a particular column.  
     *
     *  @default true
     *    
     *  @see spark.components.gridClasses.GridColumn
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get resizableColumns():Boolean
    {
        return _resizableColumns;
    }
    
    /**
     *  @private
     */        
    public function set resizableColumns(value:Boolean):void
    {
        if (value == resizableColumns)
            return;
        
        _resizableColumns = value;        
        dispatchChangeEvent("resizableColumnsChanged");            
    }
    
    //----------------------------------
    //  rowBackground
    //----------------------------------
    
    private var _rowBackground:IFactory = null;
    
    [Bindable("rowBackgroundChanged")]
    
    /**
     *  A visual element that's displays the background for each row.  
     * 
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get rowBackground():IFactory
    {
        return _rowBackground;
    }
    
    /**
     *  @private
     */
    public function set rowBackground(value:IFactory):void
    {
        if (_rowBackground == value)
            return;
        
        _rowBackground = value;
        invalidateDisplayList();
        dispatchChangeEvent("rowBackgroundChanged");
    }
    
    //----------------------------------
    //  rowHeight
    //----------------------------------
    
    private var _rowHeight:Number = NaN;
    private var rowHeightChanged:Boolean;
    
    [Bindable("rowHeightChanged")]
    [Inspectable(category="General", minValue="0.0")]
    
    /**
     *  If <code>variableRowHeight</code> is <code>false</code>, then 
     *  this property specifies the actual height of each row, in pixels.
     * 
     *  <p>If <code>variableRowHeight</code> is <code>true</code>, 
     *  the value of this property is used as the estimated
     *  height for rows that haven't been scrolled into view yet, rather
     *  than the preferred height of renderers configured with the <code>typicalItem</code>.
     *  Similarly, when the Grid pads its display with empty rows, this property
     *  specifies the empty rows' height.</p>
     * 
     *  <p>If <code>variableRowHeight</code> is <code>false</code>, 
     *  the default value of this property is the maximum preferred height
     *  of the per-column renderers created for the <code>typicalItem</code>.</p>
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get rowHeight():Number
    {
        return _rowHeight;
    }
    
    /**
     *  @private
     */
    public function set rowHeight(value:Number):void
    {
        if (_rowHeight == value)
            return;
        
        _rowHeight = value;
        rowHeightChanged = true;        
        invalidateProperties();

        dispatchChangeEvent("rowHeightChanged");            
    }
	
	/**
	 *  @private
	 */	
	private function setFixedRowHeight(value:Number):void
	{
		if (_rowHeight == value)
			return;
		
		_rowHeight = value;
		dispatchChangeEvent("rowHeightChanged");		
	}
    
    //----------------------------------
    //  rowSeparator
    //----------------------------------
    
    private var _rowSeparator:IFactory = null;
    
    [Bindable("rowSeparatorChanged")]
    
    /**
     *  A visual element that's displayed in between each row.
     * 
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get rowSeparator():IFactory
    {
        return _rowSeparator;
    }
    
    /**
     *  @private
     */
    public function set rowSeparator(value:IFactory):void
    {
        if (_rowSeparator == value)
            return;
        
        _rowSeparator = value;
        invalidateDisplayList();
        dispatchChangeEvent("rowSeparatorChanged");
    }    
    
    //----------------------------------
    //  selectedCell
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]

    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> 
     *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns the first
     *  selected cell starting at row 0 column 0 and progressing through each
     *  column in a row before moving to the next row.
     * 
     *  <p>When the user changes the selection by interacting with the 
     *  control, the control dispatches the <code>selectionChange</code> 
     *  event. When the user changes the selection programmatically, the 
     *  control dispatches the <code>valueCommit</code> event.</p>
     * 
     *  <p> This property is intended to be used to initialize or bind to the
     *  selection in MXML markup.  The <code>setSelectedCell()</code> method 
     *  should be used for programatic selection updates, for example 
     *  when writing a keyboard or mouse event handler. </p> 
     *
     *  @default null
     * 
     *  @return CellPosition of the first selected cell or null if there is
     *  no cell selection.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedCell():CellPosition
    {
        var selectedCells:Vector.<CellPosition> = gridSelection.allCells();
        return selectedCells.length ? selectedCells[0] : null;
    }
    
    /**
     *  @private
     */
    public function set selectedCell(value:CellPosition):void
    {
        const rowIndex:int = (value) ? value.rowIndex : -1;
        const columnIndex:int = (value) ? value.columnIndex : -1;
        
        // Defer the selection change if we haven't been initialized
        
        if (!initialized)
        {
            // Append a deferred operation function that selects the specified cell
            
            var f:Function = function():void
            {
                if ((rowIndex != -1) && (columnIndex != -1))
                    setSelectedCell(rowIndex, columnIndex);
                else
                    clearSelection();
            }
                
            deferredOperations.push(f);  // function f() to be called by commitProperties()
            invalidateProperties();
        }
        else
        {
            if ((rowIndex != -1) && (columnIndex != -1))
                setSelectedCell(rowIndex, columnIndex);
            else
                clearSelection();            
        }
    }        
                   
    //----------------------------------
    //  selectedCells
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]

    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code> 
     *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns a Vector
     *  of CellPosition objects representing the positions of the selected
     *  cells in the grid.
     * 
     *  <p>When the user changes the selection by interacting with the 
     *  control, the control dispatches the <code>selectionChange</code> 
     *  event. When the user changes the selection programmatically, the 
     *  control dispatches the <code>valueCommit</code> event.</p>
     * 
     *  <p> This property is intended to be used to initialize or bind to the
     *  selection in MXML markup.  The <code>setSelectedCell()</code> method 
     *  should be used for programatic selection updates, for example when 
     *  writing a keyboard or mouse event handler. </p> 
     * 
     *  <p>The default value is an empty <code>Vector.&lt;CellPosition&gt;</code></p>
     * 
     *  @return Vector of CellPosition objects where each element represents
     *  a selected cell.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedCells():Vector.<CellPosition>
    {
        return gridSelection.allCells();
    }
    
    /**
     *  @private
     */
    public function set selectedCells(value:Vector.<CellPosition>):void
    {
        // Defensively deep-copy the incoming value; tolerate value=null

        var valueCopy:Vector.<CellPosition> = new Vector.<CellPosition>(0);
        if (value)
        {
            for each (var cell:CellPosition in value)
                valueCopy.push(new CellPosition(cell.rowIndex, cell.columnIndex));
        }
        
        // Defer the selection change if we haven't been initialized
        
        if (!initialized)
        {        
            // Append a deferred operation function that selects the specified cells
            
            var f:Function = function():void
            {
                doSetSelectedCells(valueCopy);
            }
            deferredOperations.push(f);  // function f() to be called by commitProperties()
            invalidateProperties();
        }
        else
        {
            doSetSelectedCells(valueCopy);
        }
    }          

    //----------------------------------
    //  selectedIndex
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General", defaultValue="-1")]

    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns the
     *  rowIndex of the first selected row. 
     * 
     *  <p>When the user changes the selection by interacting with the 
     *  control, the control dispatches the <code>selectionChange</code> 
     *  event. When the user changes the selection programmatically, the 
     *  control dispatches the <code>valueCommit</code> event.</p>
     * 
     *  <p> This property is intended to be used to initialize or bind to the
     *  selection in MXML markup.  The <code>setSelectedCell()</code> method should be used
     *  for programatic selection updates, for example when writing a keyboard
     *  or mouse event handler. </p> 
     *
     *  @default -1
     * 
     *  @return rowIndex of first selected row or -1 if there are no
     *  selected rows.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedIndex():int
    {
        var selectedRows:Vector.<int> = gridSelection.allRows();
        return (selectedRows.length > 0) ? selectedRows[0] : -1;
    }
    
    /**
     *  @private
     */
    public function set selectedIndex(value:int):void
    {
        // Defer the selection change if we haven't been initialized
        
        if (!initialized)
        {        
            // Append a deferred operation function that selects the specified index
            
            var f:Function = function():void
            {
                if (value != -1)
                    setSelectedIndex(value);
                else
                    clearSelection();
            }
            deferredOperations.push(f);  // function f() to be called by commitProperties()
            invalidateProperties();
        }
        else
        {
            if (value != -1)
                setSelectedIndex(value);
            else
                clearSelection();
        }
    }
    
    //----------------------------------
    //  selectedIndices
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General")]

    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns a Vector of 
     *  the selected rows indices.  For all other selection modes, this 
     *  method has no effect.
     * 
     *  <p>When the user changes the selection by interacting with the 
     *  control, the control dispatches the <code>selectionChange</code> 
     *  event. When the user changes the selection programmatically, the 
     *  control dispatches the <code>valueCommit</code> event.</p>
     * 
     *  <p> This property is intended to be used to initialize or bind to the
     *  selection in MXML markup.  The setSelectedCell() method should be used
     *  for programatic selection updates, for example when writing a keyboard
     *  or mouse event handler. </p> > 
     *
     *  <p>The default value is an empty <code>Vector.&lt;int&gt;</code></p>
     * 
     *  @return Vector of ints where each element is the index in 
     *  data provider of the selected row.
     *  
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedIndices():Vector.<int>
    {
        return gridSelection.allRows();
    }
    
    /**
     *  @private
     */
    public function set selectedIndices(value:Vector.<int>):void
    {
        // Defensively copy the incoming value; tolerate value=null
        
        const valueCopy:Vector.<int> = (value) ? value.concat() : new Vector.<int>(0);
        
        // Defer the selection change if we haven't been initialized
        
        if (!initialized)
        {        
            // Append a deferred operation function that selects the specified indices
        
            var f:Function = function():void
            {
                doSetSelectedIndices(valueCopy);
            }
            deferredOperations.push(f);  // function f() to be called by commitProperties()
            invalidateProperties();
        }
        else
        {
            doSetSelectedIndices(valueCopy);
        }
    }        
    
    //----------------------------------
    //  selectedItem
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General", defaultValue="null")]
    
    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns the 
     *  item in the the data provider that is currently selected or
     *  <code>undefined</code> if no rows are selected.  
     * 
     *  <p>When the user changes the selection by interacting with the 
     *  control, the control dispatches the <code>selectionChange</code> 
     *  event. When the user changes the selection programmatically, the 
     *  control dispatches the <code>valueCommit</code> event.</p>
     * 
     *  <p> This property is intended to be used to initialize or bind to the
     *  selection in MXML markup.  The <code>setSelectedCell()</code> method should be used
     *  for programatic selection updates, for example when writing a keyboard
     *  or mouse event handler. </p> 
     *  
     *  @default null
     * 
     *  @return Vector of data provider items.
     *  
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedItem():Object
    {
        var rowIndex:int = selectedIndex;
        if (rowIndex == -1)
            return undefined;
        
        return getDataProviderItem(rowIndex);           
    }
    
    /**
     *  @private
     */
    public function set selectedItem(value:Object):void
    {
        // Defer the selection change if we haven't been initialized
        
        if (!initialized)
        {        
            // Append a deferred operation function that selects the specified item
            
            var f:Function = function():void
            {
                if (!dataProvider)
                    return;
    
                const rowIndex:int = dataProvider.getItemIndex(value);
                if (rowIndex == -1)
                    clearSelection();
                else
                    setSelectedIndex(rowIndex);
            }
            deferredOperations.push(f);  // function f() to be called by commitProperties()
            invalidateProperties();
        }
        else
        {
            if (!dataProvider)
                return;
            
            const rowIndex:int = dataProvider.getItemIndex(value);
            if (rowIndex == -1)
                clearSelection();
            else
                setSelectedIndex(rowIndex);            
        }
    }        
    
    //----------------------------------
    //  selectedItems
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General")]

    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns a Vector of 
     *  the dataProvider items that are currently selected.
     * 
     *  <p>When the user changes the selection by interacting with the 
     *  control, the control dispatches the <code>selectionChange</code> 
     *  event. When the user changes the selection programmatically, the 
     *  control dispatches the <code>valueCommit</code> event.</p>
     * 
     *  <p> This property is intended to be used to initialize or bind to the
     *  selection in MXML markup.  The setSelectedCell() method should be used
     *  for programatic selection updates, for example when writing a keyboard
     *  or mouse event handler. </p> 
     *  
     *  <p>The default value is an empty <code>Vector.&lt;Object&gt;</code></p>
     * 
     *  @return Vector of data provider items.
     *  
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedItems():Vector.<Object>
    {
        var rowIndices:Vector.<int> = selectedIndices;
        if (rowIndices.length == 0)
            return undefined;
        
        var items:Vector.<Object> = new Vector.<Object>();
        
        for each (var rowIndex:int in rowIndices)        
            items.push(dataProvider.getItemAt(rowIndex));
       
        return items;
    }
    
    /**
     *  @private
     */
    public function set selectedItems(value:Vector.<Object>):void
    {
        // Defensively copy the incoming value; tolerate value=null
        
        const valueCopy:Vector.<Object> = (value) ? value.concat() : new Vector.<Object>(0);
        
        // Defer the selection change if we haven't been initialized
        
        if (!initialized)
        {        
            // Append a deferred operation function that selects the specified items        
            
            var f:Function = function():void
            {
                doSetSelectedItems(valueCopy);
            }
            deferredOperations.push(f);  // function f() to be called by commitProperties()
            invalidateProperties();
        }
        else
        {
            doSetSelectedItems(valueCopy);
        }
    }        
    
    //----------------------------------
    //  selectionIndicator
    //----------------------------------
    
    private var _selectionIndicator:IFactory = null;
    
    [Bindable("selectionIndicatorChanged")]
    
    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> or
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
     *  a visual element that's displayed for each selected row, 
     *  If <code>selectionMode</code> is
     *  <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>,
     *  a visual element displayed for each selected cell.
     *  
     *  @default null
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectionIndicator():IFactory
    {
        return _selectionIndicator;
    }
    
    /**
     *  @private
     */
    public function set selectionIndicator(value:IFactory):void
    {
        if (_selectionIndicator == value)
            return;
        
        _selectionIndicator = value;
        invalidateDisplayListFor("selectionIndicator");
        dispatchChangeEvent("selectionIndicatorChanged");
    }    
    
    //----------------------------------
    //  selectionLength (delegates to gridSelection.selectionLength)
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    
    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code> 
     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
     *  returns the number of selected rows. 
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELLS</code> 
     *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, 
     *  returns the number of selected cells.
     * 
     *  @default 0
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectionLength():int
    {
        return gridSelection.selectionLength;   
    }
    
    //----------------------------------
    //  selectionMode (delegates to gridSelection.selectionMode)
    //----------------------------------
    
    [Bindable("selectionModeChanged")]
    [Inspectable(category="General", enumeration="none,singleRow,multipleRows,singleCell,multipleCells", defaultValue="singleRow")]
    
    /**
     *  The selection mode of the control.  Possible values are:
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, 
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, 
     *  <code>GridSelectionMode.NONE</code>, 
     *  <code>GridSelectionMode.SINGLE_CELL</code>, and 
     *  <code>GridSelectionMode.SINGLE_ROW</code>.
     * 
     *  <p>Changing the selectionMode causes the current selection to be 
     *  cleared and the caretRowIndex and caretColumnIndex to be set to -1.</p>
     *
     *  @default GridSelectionMode.SINGLE_ROW
     * 
     *  @see spark.components.gridClasses.GridSelectionMode
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectionMode():String
    {
        return gridSelection.selectionMode;
    }
    
    /**
     *  @private
     */
    public function set selectionMode(value:String):void
    {
        if (selectionMode == value)
            return;
        
        gridSelection.selectionMode = value;
        if (selectionMode != value) // value wasn't a valid GridSelectionMode constant
            return;
        
        initializeAnchorPosition();
        if (!requireSelection)
            initializeCaretPosition();
        
        invalidateDisplayListFor("selectionIndicator");
        
        dispatchChangeEvent("selectionModeChanged");
    }
    
    //----------------------------------
    //  showCaret
    //----------------------------------
    
    /**
     *  @private
     */
    private var _showCaret:Boolean = false;
    
    [Bindable("showCaretChanged")]    
    
    /**
     *  Determines if the caret is visible.
     *  TBD: when is this property automatically set?
     */
    public function get showCaret():Boolean
    {
        return _showCaret;
    }
    
    /**
     *  @private
     */
    public function set showCaret(value:Boolean):void
    {
        if (_showCaret == value)
            return;
        
        _showCaret = value;
        invalidateDisplayListFor("caretIndicator");        
        dispatchChangeEvent("showCaretChanged");       
    }    
    
    //----------------------------------
    //  showDataTips
    //----------------------------------
    
    private var _showDataTips:Boolean = false;
    
    [Bindable("showDataTipsChanged")]
    [Inspectable(category="Data", defaultValue="false")]
    
    /**
     *  If <code>true</code> then a dataTip is displayed for all visible cells.  
     *  If <code>false</code>, the default,
     *  then a dataTip is only displayed if the column's 
     *  <code>showDataTips</code> property is <code>true</code>.
     * 
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get showDataTips():Boolean
    {
        return _showDataTips;
    }
    
    /**
     *  @private
     */
    public function set showDataTips(value:Boolean):void
    {
        if (_showDataTips == value)
            return;
        
        _showDataTips = value;
        invalidateDisplayList();
        dispatchChangeEvent("showDataTipsChanged");
    }
	
    //----------------------------------
    //  typicalItem
    //----------------------------------
    
    private var _typicalItem:Object = null;
    private var typicalItemChanged:Boolean = false;
    
    [Bindable("typicalItemChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  The grid's layout ensures that columns whose width is not specified are wide
     *  enough to display an item renderer for this default data provider item.  
     *  If a typical item is not specified, then the first data provider item is used.
     * 
     *  <p>Restriction: if the <code>typicalItem</code> is an IVisualItem, it must not 
     *  also be a member of the data provider.</p>
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get typicalItem():Object
    {
        return _typicalItem;
    }
    
    /**
     *  @private
     */
    public function set typicalItem(value:Object):void
    {
        if (_typicalItem == value)
            return;
        
        _typicalItem = value;
        invalidateTypicalItemRenderer();
        dispatchChangeEvent("typicalItemChanged");
    }

    /**
     *  Clears cached column width data that had been based on the 
     *  <code>typicalItem</code> property, and requests a new layout pass.   
     *  Call this method if some aspect of the <code>typicalItem</code> 
     *  has changed that should be reflected by the Grid's layout.  
     * 
     *  <p>This method is called automatically if the <code>typicalItem</code> 
     *  is changed directly. That means if the property is set to a new value 
     *  that is not "==" to current value.</p>
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4.5 
     */
    public function invalidateTypicalItemRenderer():void
    {
        typicalItemChanged = true;       
        invalidateProperties();
        invalidateSize();
        invalidateDisplayList();
    }
    
    //----------------------------------
    //  variableRowHeight
    //----------------------------------

    private var _variableRowHeight:Boolean = false;
    private var variableRowHeightChanged:Boolean = false;
    
    [Bindable("variableRowHeightChanged")]
    [Inspectable(category="General", defaultValue="false")]
    
    /**
     *  If <code>true</code>, each row's height is the maximum of 
     *  preferred heights of the cells displayed so far.
     * 
     *  <p>If <code>false</code>, the height of each row is just 
     *  the value of the <code>rowHeight</code> property.
     *  If <code>rowHeight</code> isn't specified, then the height of 
     *  each row is defined by the <code>typicalItem</code> property.</p>
     * 
     *  @default false
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @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;        
        variableRowHeightChanged = true;        
        invalidateProperties();
        
        dispatchChangeEvent("variableRowHeightChanged");            
    }
    
    //----------------------------------
    //  gridView
    //----------------------------------
    
    private var _gridView:IFactory = null;
    
    [Bindable("gridViewChanged")]
    
    /**
	 *  Used to initialize this grid's gridViews: centerGridView, leftGridView, topGridView, topLeftGridView. 
	 *  GridViews are created as needed, depending on the values of lockedRowCount and lockedColumnCount.
	 * 
	 *  @default null.
	 * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public function get gridView():IFactory
    {
        return _gridView;
    }
    
    /**
     *  @private
     */        
    public function set gridView(value:IFactory):void
    {
        if (value == _gridView)
            return;
        
        _gridView = value;
        invalidateProperties();
        
        // TBD clear everything
        
        dispatchChangeEvent("gridViewChanged");            
    }

    //--------------------------------------------------------------------------
    //
    //  GridSelection Cover Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  If <code>selectionMode</code> is 
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, selects all rows and
     *  removes the caret or if <code>selectionMode</code> is 
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code> selects all cells  
     *  and removes the caret.  For all other selection modes, this method 
     *  has no effect.
     *
     *  <p>If items are added to the <code>dataProvider</code> or 
     *  <code>columns</code> are added after this method is called, the
     *  new rows or cells in the new column will be selected.</p>
     * 
     *  <p>This implicit "selectAll" mode ends when any of the following occur:
     *  <ul>
     *    <li>selection is cleared using <code>clearSelection</code></li>
     *    <li>selection reset using one of <code>setSelectedCell</code>, 
     *    <code>setSelectedCells</code>, <code>setSelectedIndex</code>, 
     *    <code>selectIndices</code></li>
     *    <li><code>dataProvider</code> is refreshed and <code>preserveSelection</code> is false</li>
     *    <li><code>dataProvider</code> is reset</li>
     *    <li><code>columns</code> is refreshed, 
     *    <code>preserveSelection</code> is <code>false</code> and 
     *    <code>selectionMode</code> is 
     *    <code>GridSelectionMode.MULTIPLE_CELLS</code></li>
     *    <li><code>columns</code> is reset and <code>selectionMode</code> is 
     *    <code>GridSelectionMode.MULTIPLE_CELLS</code></li> 
     *  </ul></p>
     * 
     *  @return <code>true</code> if the selection changed.
     *    
     *  @see spark.components.Grid#clearSelection
     *  @see spark.components.Grid#selectIndices
     *  @see spark.components.Grid#setSelectedCell
     *  @see spark.components.Grid#setSelectedCells
     *  @see spark.components.Grid#setSelectedIndex
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectAll():Boolean
    {           
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        const selectionChanged:Boolean = gridSelection.selectAll();
        if (selectionChanged)
        {               
            initializeCaretPosition();               
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
 
        return selectionChanged;
    }
    
    /**
     *  Removes all of the selected rows and cells, if <code>selectionMode</code>  
     *  is not <code>GridSelectionMode.NONE</code>.  Removes the caret and
     *  sets the anchor to the initial item.
     *
     *  @return <code>true</code> if the selection changed.
     *  <code>false</code> if there was nothing previously selected.
     *    
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function clearSelection():Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);

        const selectionChanged:Boolean = gridSelection.removeAll();
        if (selectionChanged)
        {
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        // Remove caret and reset the anchor.
        initializeCaretPosition();
        initializeAnchorPosition();
        
        return selectionChanged;
    }
    
    //----------------------------------
    //  selection for rows
    //----------------------------------    
    
    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_ROW</code>
     *  or <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns <code>true</code> 
     *  if the row at <code>index</code> is in the current selection.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider
     *  of the item containing the selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the row.
     * 
     *  @return <code>true</code> if the selection contains the row.
     *    
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectionContainsIndex(rowIndex:int):Boolean 
    {
        return gridSelection.containsRow(rowIndex);
    }
    
    /**
     *  If <code>selectionMode</code> is 
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, returns <code>true</code> 
     *  if the rows in <code>indices</code> are in the current selection.
     * 
     *  @param rowIndices Vector of 0-based row indices to include in selection. 
     * 
     *  @return <code>true</code> if the current selection contains these rows.
     *    
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectionContainsIndices(rowIndices:Vector.<int>):Boolean 
    {
        return gridSelection.containsRows(rowIndices);
    }
    
    /**
     *  If <code>selectionMode</code>
     *  is <code>GridSelectionMode.SINGLE_ROW</code> or 
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, sets the selection and 
     *  the caret position to this row.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider
     *  of the item containing the selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @return <code>true</code> if if no errors.
     *  <code>false</code> if <code>index</code> is invalid, or
     *  the <code>selectionMode</code> is invalid. 
     *    
     *  @see spark.components.Grid#caretColumnIndex
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function setSelectedIndex(rowIndex:int):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
                
        const selectionChanged:Boolean = gridSelection.setRow(rowIndex);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex;
            caretColumnIndex = -1;
            
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  If <code>selectionMode</code>
     *  is <code>GridSelectionMode.MULTIPLE_ROWS</code>, adds this row to
     *  the selection and sets the caret position to this row.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider 
     *  of the item containing the selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @return <code>true</code> if no errors.
     *  <code>false</code> if <code>index</code> is invalid or
     *  the <code>selectionMode</code> is invalid. 
     *    
     *  @see spark.components.Grid#caretColumnIndex
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function addSelectedIndex(rowIndex:int):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
                
        const selectionChanged:Boolean = gridSelection.addRow(rowIndex);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex;
            caretColumnIndex = -1;                

            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  If <code>selectionMode</code>
     *  is <code>GridSelectionMode.SINGLE_ROW</code> or 
     *  <code>GridSelectionMode.MULTIPLE_ROWS</code>, removes this row
     *  from the selection and sets the caret position to this row.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider 
     *  of the item containing the selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @return <code>true</code> if no errors.
     *  <code>false</code> if <code>index</code> is invalid or
     *  the <code>selectionMode</code> is invalid. 
     *       
     *  @see spark.components.Grid#caretColumnIndex
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function removeSelectedIndex(rowIndex:int):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        const selectionChanged:Boolean = gridSelection.removeRow(rowIndex);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex;
            caretColumnIndex = -1;
            
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_ROWS</code>,
     *  sets the selection to the specfied rows and the caret position to
     *  <code>endRowIndex</code>.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>Each index represents an item in the data provider  
     *  to include in the selection.</p>
     *
     *  @param rowIndex 0-based row index of the first row in the selection.
     * 
     *  @param rowCount Number of rows in the selection.
     * 
     *  @return <code>true</code> if no errors.
     *  <code>false</code> if any of the indices are invalid, 
     *  if <code>startRowIndex</code> is not less than or equal to 
     *  <code>endRowIndex</code>, or the <code>selectionMode</code> is invalid. 
     *    
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectIndices(rowIndex:int, rowCount:int):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        const selectionChanged:Boolean = gridSelection.setRows(rowIndex, rowCount);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex + rowCount - 1;
            caretColumnIndex = -1;
            
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }

    //----------------------------------
    //  selection for cells
    //----------------------------------    
    
    /**
     *  If <code>selectionMode</code> is <code>GridSelectionMode.SINGLE_CELL</code>
     *  or <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns <code>true</code> 
     *  if the cell is in the current selection.
     * 
     *  <p>The <code>rowIndex</code> must be between 0 and the
     *  length of the data provider.  The <code>columnIndex</code>
     *  must be between 0 and the length of <code>columns</code>. </p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @param columnIndex The 0-based column index of the cell.
     *  
     *  @return <code>true</code> if the current selection contains the cell.
     * 
     *  @see spark.components.Grid#columns
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectionContainsCell(rowIndex:int, columnIndex:int):Boolean
    {
        return gridSelection.containsCell(rowIndex, columnIndex);
    }
    
    /**
     *  If <code>selectionMode</code> is 
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, returns <code>true</code> 
     *  if the cells in the cell region are in the current selection.
     * 
     *  <p>The <code>rowIndex</code> must be between 0 and the
     *  length of the data provider.  The <code>columnIndex</code>
     *  must be between 0 and the length of <code>columns</code>. </p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @param columnIndex The 0-based column index of the cell.
     *  
     *  @param rowCount Number of rows, starting at <code>rowIndex</code> to 
     *  include in the cell region.
     *
     *  @param columnCount Number of columns, starting at 
     *  <code>columnIndex</code> to include in the cell region.
     * 
     *  @return <code>true</code> if the current selection contains all 
     *  the cells in the cell region.
     * 
     *  @see spark.components.Grid#columns
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectionContainsCellRegion(rowIndex:int, columnIndex:int, 
                                                rowCount:int, columnCount:int):Boolean
    {
        return gridSelection.containsCellRegion(rowIndex, columnIndex, 
            rowCount, columnCount);
    }
    
    /**
     *  If <code>selectionMode</code>
     *  is <code>GridSelectionMode.SINGLE_CELL</code> or 
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, sets the selection
     *  and the caret position to this cell.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider 
     *  of the item containing the selected cell.  The <code>columnIndex</code>
     *  is the index in <code>columns</code> of the column containing the
     *  selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @param columnIndex The 0-based column index of the cell.
     * 
     *  @return <code>true</code> if no errors.
     *  <code>false</code> if <code>rowIndex</code> 
     *  or <code>columnIndex</code> is invalid or the <code>selectionMode</code> 
     *  is invalid.     
     *  
     *  @see spark.components.Grid#caretColumnIndex
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#columns
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function setSelectedCell(rowIndex:int, columnIndex:int):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        const selectionChanged:Boolean = gridSelection.setCell(rowIndex, columnIndex);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex;
            caretColumnIndex = columnIndex;
            
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  If <code>selectionMode</code>
     *  is <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, adds the cell to
     *  the selection and sets the caret position to the cell.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider 
     *  of the item containing the selected cell.  The <code>columnIndex</code>
     *  is the index in <code>columns</code> of the column containing the
     *  selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @param columnIndex The 0-based column index of the cell.
     * 
     *  @return <code>true</code> if no errors.
     *  <code>false</code> if <code>rowIndex</code> 
     *  or <code>columnIndex</code> is invalid, or the <code>selectionMode</code> 
     *  is invalid.     
     *  
     *  @see spark.components.Grid#caretColumnIndex
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#columns
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function addSelectedCell(rowIndex:int, columnIndex:int):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        const selectionChanged:Boolean = gridSelection.addCell(rowIndex, columnIndex);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex;
            caretColumnIndex = columnIndex;
            
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  If <code>selectionMode</code>
     *  is <code>GridSelectionMode.SINGLE_CELL</code> or
     *  <code>GridSelectionMode.MULTIPLE_CELLS</code>, removes the cell
     *  from the selection and sets the caret position to the cell.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider 
     *  of the item containing the selected cell.  The <code>columnIndex</code>
     *  is the index in <code>columns</code> of the column containing the
     *  selected cell.</p>
     *
     *  @param rowIndex The 0-based row index of the cell.
     *
     *  @param columnIndex The 0-based column index of the cell.
     * 
     *  @return <code>true</code> if no errors.
     *  <code>false</code> if <code>rowIndex</code> 
     *  or <code>columnIndex</code> is invalid or the <code>selectionMode</code> 
     *  is invalid.     
     *  
     *  @see spark.components.Grid#caretColumnIndex
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#columns
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function removeSelectedCell(rowIndex:int, columnIndex:int):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        const selectionChanged:Boolean = gridSelection.removeCell(rowIndex, columnIndex);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex;
            caretColumnIndex = columnIndex;
            
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /** 
     *  If <code>selectionMode</code> is <code>GridSelectionMode.MULTIPLE_CELLS</code>,
     *  sets the selection to all the cells in the cell region and the
     *  caret position to the last cell in the cell region.
     *  For all other selection modes, this method has no effect.
     * 
     *  <p>The <code>rowIndex</code> is the index in the data provider 
     *  of the item containing the origin of the cell region.  
     *  The <code>columnIndex</code>
     *  is the index in <code>columns</code> of the column containing the
     *  origin of the cell region.</p>
     *
     *  <p>This method has no effect if the cell region is not wholly
     *  contained within the grid.</p>
     * 
     *  @param rowIndex The 0-based row index of the origin of the cell region.
     *
     *  @param columnIndex The 0-based column index of the origin of the cell 
     *  region.
     *  
     *  @param rowCount Number of rows, starting at <code>rowIndex</code> to 
     *  include in the cell region.
     *
     *  @param columnCount Number of columns, starting at 
     *  <code>columnIndex</code> to include in the cell region.
     * 
     *  @return <code>true</code> if no errors.
     *  <code>false</code> if the cell region is invalid or 
     *  the <code>selectionMode</code> is invalid.     
     *  
     *  @see spark.components.Grid#caretColumnIndex
     *  @see spark.components.Grid#caretRowIndex
     *  @see spark.components.Grid#columns
     *  @see spark.components.Grid#dataProvider
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectCellRegion(rowIndex:int, columnIndex:int, 
                                     rowCount:uint, columnCount:uint):Boolean
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        const selectionChanged:Boolean = gridSelection.setCellRegion(
            rowIndex, columnIndex, 
            rowCount, columnCount);
        if (selectionChanged)
        {
            caretRowIndex = rowIndex + rowCount - 1;
            caretColumnIndex = columnIndex + columnCount - 1;
                
            invalidateDisplayListFor("selectionIndicator");
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
      
    //--------------------------------------------------------------------------
    //
    //  Selection API Helper Methods
    //
    //-------------------------------------------------------------------------- 

    /**
     * For performance reasons, make sure validateClient, anchor and caret updates,
     * and selectionIndicator and VALUE_COMMIT updates are only done once.
     */
    private function doSetSelectedCells(valueCopy:Vector.<CellPosition>):void
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        gridSelection.removeAll();
        for each (var cell:CellPosition in valueCopy)
        {
            gridSelection.addCell(cell.rowIndex, cell.columnIndex);
        }
        
        doFinalizeSetSelection(cell ? cell.rowIndex : -1, 
                               cell ? cell.columnIndex : -1);
    }
    
    /**
     * For performance reasons, make sure validateClient, anchor and caret updates,
     * and selectionIndicator and VALUE_COMMIT updates are only done once.
     */
    private function doSetSelectedIndices(valueCopy:Vector.<int>):void
    {
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        var newRowIndex:int = -1;
        gridSelection.removeAll();
        for each (newRowIndex in valueCopy)
        {
            gridSelection.addRow(newRowIndex);
        }
        
        doFinalizeSetSelection(newRowIndex, -1);
    }

    /**
     * For performance reasons, make sure validateClient, anchor and caret updates,
     * and selectionIndicator and VALUE_COMMIT updates are only done once.
     */
    private function doSetSelectedItems(valueCopy:Vector.<Object>):void
    {
        if (!dataProvider)
            return;
        
        // Need to apply pending dataProvider and column changes so selection
        // isn't reset after it is set here.
        if (invalidatePropertiesFlag)
            UIComponentGlobals.layoutManager.validateClient(this, false);
        
        var newRowIndex:int = -1;        
        gridSelection.removeAll();
        for each (var item:Object in valueCopy)
        {
            newRowIndex = dataProvider.getItemIndex(item);
            gridSelection.addRow(newRowIndex);
        }
        
        doFinalizeSetSelection(newRowIndex, -1);
    }
    
    /**
     * Finished selection operations so update the anchor, caret, selection indicators and
     * trigger the selection bindings.
     */
    private function doFinalizeSetSelection(rowIndex:int, columnIndex:int):void
    {
        initializeAnchorPosition();       
        caretRowIndex = rowIndex
        caretColumnIndex = columnIndex
        
        invalidateDisplayListFor("selectionIndicator");
        dispatchFlexEvent(FlexEvent.VALUE_COMMIT);      
    }
    
    //--------------------------------------------------------------------------
    //
    //  GridViewLayout Cover Methods, Properties
    //
    //-------------------------------------------------------------------------- 
    
    /** 
     *  @private
     *  Update the scroll position so that the virtual Grid element at the specified
     *  index is visible.   Note that getScrollPositionDeltaToElement() is only 
     *  approximate when variableRowHeight=true, so calling this method once will
     *  not necessarily scroll far enough to expose the specified element.
     * 
     *  @returns True if either the horizontalScrollPosition or verticalScrollPosition changed.
     */
    private function scrollToIndex(view:GridView, elementIndex:int, scrollHorizontally:Boolean, scrollVertically:Boolean):Boolean
    {
        var spDelta:Point = view.gridViewLayout.getScrollPositionDeltaToElement(elementIndex);
        
        // The cell is completely visible or the specified index is no longer valid so punt.
		
        if (!spDelta)
            return false; 
		
		// If the required scroll is locked then punt
		
		if ((spDelta.y != 0) && view.gridViewLayout.verticalScrollingLocked)
			return false;
		
		if ((spDelta.x != 0) && view.gridViewLayout.horizontalScrollingLocked)
			return false;
		
		// Update the scroll positions

        var scrollChanged:Boolean = false;
        
        if (scrollHorizontally)
        {
            horizontalScrollPosition += spDelta.x;
            scrollChanged = spDelta.x != 0;
        }
        
        if (scrollVertically)
        {
            verticalScrollPosition += spDelta.y;
            scrollChanged = scrollChanged || spDelta.y != 0;
        }
        
        return scrollChanged;
    }
    
    /**
     *  If necessary, set the <code>verticalScrollPosition</code> and 
     *  <code>horizontalScrollPosition</code> properties so that the 
     *  specified cell is completely visible. 
     *  If <code>rowIndex</code> is -1 and <code>columnIndex</code> is specified, 
     *  then just adjust the <code>horizontalScrollPosition</code>
     *  so that the specified column is visible. 
     *  If <code>columnIndex</code> is -1 and <code>rowIndex</code>
     *  is specified, then just adjust the <code>verticalScrollPosition</code> 
     *  so that the specified row is visible.
     * 
     *  @param rowIndex The 0-based row index of the item renderer's cell, or -1 to specify a column.
     *  
     *  @param columnIndex The 0-based column index of the item renderer's cell, or -1 to specify a row.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function ensureCellIsVisible(rowIndex:int = -1, columnIndex:int = -1):void
    {
        const columns:IList = this.columns;
        
        // Check that each index is within range.
        if (!columns || columnIndex < -1 || columnIndex >= columns.length || 
            !dataProvider || rowIndex < -1 || rowIndex >= dataProvider.length || 
            (columnIndex == -1 && rowIndex == -1))
            return;
        
        // Check to see if any columns are visible or specified column is visible.
        if ((columnIndex == -1 && getNextVisibleColumnIndex(-1) == -1) || 
            (columnIndex != -1 && !(GridColumn(columns.getItemAt(columnIndex)).visible)))
            return;
        
        const scrollHorizontally:Boolean = columnIndex != -1;
        const scrollVertically:Boolean = rowIndex != -1;
         
        // If the row, column, or cell is locked, then there's nothing to do.
        
		if ((columnIndex < lockedColumnCount) && (rowIndex < lockedRowCount))
			return;
		
        if (!scrollVertically && (columnIndex < lockedColumnCount)) 
            return;

        if (!scrollHorizontally && (rowIndex < lockedRowCount))
            return;        
        
        // If called after the layout cache is cleared, need to rebuild the cache
        // before accessing visible rows/columns and attempting to scroll.
        if (getVisibleRowIndices().length == 0 || getVisibleColumnIndices().length == 0)
            validateNow();
        
        // When not scrolling horizontally, columnIndex can just be 0.
        if (!scrollHorizontally)
            columnIndex = 0;
		
		// Find the GridView the specified cell is contained by and punt if it's not visible
		
		const cellGridView:GridView = getGridViewAt(rowIndex, columnIndex);	
		if (!cellGridView || 
			(cellGridView.getLayoutBoundsX() >= getLayoutBoundsWidth()) || 
			(cellGridView.getLayoutBoundsY() >= getLayoutBoundsHeight()))
			return;
		
        // If the row index isn't specified, use the first one that's visible.
        if (!scrollVertically)
        {
            const visibleRowIndices:Vector.<int> = cellGridView.gridViewLayout.getVisibleRowIndices();
            rowIndex = (visibleRowIndices.length > 0) ?  visibleRowIndices[0] : 0;
        }

        // A cell's index as defined by LayoutBase it's just its position
        // in the row-major linear ordering of the grid's cells.
        
        const gridViewLayout:GridViewLayout = cellGridView.gridViewLayout;
		const cellViewRowIndex:int = rowIndex - gridViewLayout.viewRowIndex;
		const cellViewColumnIndex:int  = columnIndex - gridViewLayout.viewColumnIndex;
        const cellElementIndex:int = (cellViewRowIndex * gridViewLayout.columnsView.length) + cellViewColumnIndex;
        
        var scrollChanged:Boolean = false;
        var firstScroll:Boolean = true;
        
        // Iterate until we've scrolled elementIndex at least partially into view.
        do
        {
            scrollChanged = scrollToIndex(cellGridView, cellElementIndex, scrollHorizontally, scrollVertically);
            
            // Fixed row heights, and we're only scrolling vertically.
            if (!variableRowHeight && !scrollHorizontally)
                return;
            
            // Bail. This could indicate there is a bug but it avoids an infinite loop.
            // scrollToIndex() then validateNow() then scrollToIndex() again and
            // no changes in scroll position.
            if (!firstScroll && !scrollChanged)
                return;
            
            validateNow();
                        
            firstScroll = false;
        }
        while (!isCellVisible(scrollVertically ? rowIndex : -1, scrollHorizontally ? columnIndex : -1));
        
        // At this point we've only ensured that the requested cell is at least 
        // partially visible.  Ensure that it's completely visible.
      
        scrollToIndex(cellGridView, cellElementIndex, scrollHorizontally, scrollVertically);
    }        
    
    /**
     *  Return the data provider indices and padding indices of the 
     *  currently visible rows.  
     *  Indices which are greater than or equal to the 
     *  <code>dataProvider</code> length represent padding rows.
     *  Note that the item renderers for the first and last rows 
     *  may only be partially visible. 
     *  The returned vector's contents are in the order they're displayed.
     * 
     *  @return A vector of the visible row indices.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */ 
    public function getVisibleRowIndices():Vector.<int>
    {
		const gridLayout:GridLayout = layout as GridLayout;
		const topGridView:GridView = gridLayout.topGridView;        
		const centerGridView:GridView = gridLayout.centerGridView;
        
        if (!centerGridView)
            return new Vector.<int>(0);
		
		const centerRowIndices:Vector.<int> = centerGridView.gridViewLayout.getVisibleRowIndices();
		if (!topGridView)
			return centerRowIndices;
		
        const topRowIndices:Vector.<int> = topGridView.gridViewLayout.getVisibleRowIndices();
        return topRowIndices.concat(centerRowIndices);
    }
    
    /**
     *  Return the indices of the currently visible columns.  Note that the 
     *  item renderers for the first and last columns may only be partially visible.  
     *  The returned vector's contents are in the order they're displayed.
     * 
     *  <p>The following example function uses this method to compute a vector of 
     *  visible GridColumn objects.</p>
     *  <pre>
     *  function getVisibleColumns():Vector.&lt;GridColumn&gt;
     *  {
     *      var visibleColumns = new Vector.&lt;GridColumn&gt;;
     *      for each (var columnIndex:int in grid.getVisibleColumnIndices())
     *          visibleColumns.push(grid.columns.getItemAt(columnIndex));
     *      return visibleColumns;
     *  }
     *  </pre> 
     * 
     *  @return A vector of the visible column indices.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */ 
    public function getVisibleColumnIndices():Vector.<int>
    {
		const gridLayout:GridLayout = layout as GridLayout;
		const leftGridView:GridView = gridLayout.leftGridView;        
		const centerGridView:GridView = gridLayout.centerGridView;
		
		const centerColumnIndices:Vector.<int> = centerGridView.gridViewLayout.getVisibleColumnIndices();
		if (!leftGridView)
			return centerColumnIndices;
		
		const leftColumnIndices:Vector.<int> = leftGridView.gridViewLayout.getVisibleColumnIndices();
		return leftColumnIndices.concat(centerColumnIndices);
    }
    
    /**
     *  Returns the current pixel bounds of the specified cell, or null if no such cell exists.
     *  Cell bounds are reported in grid coordinates.
     * 
     *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
     *  it have not yet been scrolled into view, the returned bounds may only be an approximation, 
     *  based on all of the columns' <code>typicalItem</code>s.</p>
     * 
     *  @param rowIndex The 0-based index of the row.
     *
     *  @param columnIndex The 0-based index of the column. 
     *
     *  @return A <code>Rectangle</code> that represents the cell's pixel bounds, or null.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */ 
    public function getCellBounds(rowIndex:int, columnIndex:int):Rectangle
    {
        return gridDimensions.getCellBounds(rowIndex, columnIndex);
    }
    
    /**
     *  Returns the current pixel bounds of the specified row, or null if no such row exists.
     *  Row bounds are reported in grid coordinates.
     *
     *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
     *  it have not yet been scrolled into view, the returned bounds may only be an approximation, 
     *  based on all of the columns' <code>typicalItem</code>s.</p>
     * 
     *  @param rowIndex The 0-based index of the row.
     * 
     *  @return A <code>Rectangle</code> that represents the row's pixel bounds, or null.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getRowBounds(rowIndex:int):Rectangle
    {
        return gridDimensions.getRowBounds(rowIndex);      
    }
    
    /**
     *  Returns the current pixel bounds of the specified column, or null if no such column exists.
     *  Column bounds are reported in grid coordinates.
     * 
     *  <p>If all of the cells in the specified column have not yet been scrolled into view, the 
     *  returned bounds may only be an approximation, based on the column's <code>typicalItem</code>.</p>
     *  
     *  @param columnIndex The 0-based index of the column. 
     *
     *  @return A <code>Rectangle</code> that represents the column's pixel bounds, or null.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getColumnBounds(columnIndex:int):Rectangle
    {
        return gridDimensions.getColumnBounds(columnIndex);
    }
    
    /**
     *  Returns the row index corresponding to the specified grid coordinates,
     *  or -1 if the coordinates are out of bounds. 
     * 
     *  <p>If all of the columns or rows for the grid have not yet been scrolled
     *  into view, the returned index may only be an approximation, 
     *  based on all of the columns' <code>typicalItem</code>s.</p>
     *  
     *  @param x The x coordinate.
     * 
     *  @param y The y coordinate.
     *
     *  @return The index of the row corresponding to the specified coordinates.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getRowIndexAt(x:Number, y:Number):int
    {
        return gridDimensions.getRowIndexAt(x, y);
    }
    
    /**
     *  Returns the column index corresponding to the specified grid coordinates,
     *  or -1 if the coordinates are out of bounds. 
     * 
     *  <p>If all of the columns or rows for the grid have not yet been scrolled
     *  into view, the returned index may only be an approximation, 
     *  based on all of the columns' <code>typicalItem</code>s.</p>
     *  
     *  @param x The pixel's x coordinate relative to the grid.
     *
     *  @param y The pixel's y coordinate relative to the grid.
     *
     *  @return The index of the column, or -1 if the coordinates are out of bounds. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getColumnIndexAt(x:Number, y:Number):int
    {
        return gridDimensions.getColumnIndexAt(x, y); 
    }
    
    /**
     *  Return the width of the specified column.  If the cell's entire bounds
     *  aren't needed, this method is more efficient than <code>getColumnBounds().width</code>.
     * 
     *  <p>If the specified column's width property isn't defined, then the returned value 
     *  may only be an approximation.  The actual column width is only computed after the column
     *  has been scrolled into view.</p>
     * 
     *  @param columnIndex The 0-based index of the column. 
     *  @return The width of the specified column.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getColumnWidth(columnIndex:int):Number
    {
        const column:GridColumn = getGridColumn(columnIndex);
        return (column && !isNaN(column.width)) ? column.width : gridDimensions.getColumnWidth(columnIndex);
    }

    /**
     *  Return the row and column indices of the cell that overlaps the pixel at the 
     *  specified grid coordinate.
     *  If no such cell exists, null is returned.
     * 
     *  <p>The example function below uses this method to compute the value of the 
     *  <code>dataField</code> for a grid cell.</p> 
     *  <pre>
     *  function getCellData(x:Number, y:Number):Object
     *  {
     *      var cell:CellPosition = getCellAt(x, y);
     *      if (!cell)
     *          return null;
     *      var GridColumn:column = grid.columns.getItemAt(cell.columnIndex);
     *      return grid.dataProvider.getItemAt(cell.rowIndex)[column.dataField];
     *  }
     *  </pre> 
     * 
     *  @param x The pixel's x coordinate relative to the grid.
     *
     *  @param y The pixel's y coordinate relative to the grid.
     *
     *  @return The cell position, or null. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getCellAt(x:Number, y:Number):CellPosition
    {
        const rowIndex:int = gridDimensions.getRowIndexAt(x, y);
        const columnIndex:int = gridDimensions.getColumnIndexAt(x, y);
        if ((rowIndex == -1) || (columnIndex == -1))
            return null;
        return new CellPosition(rowIndex, columnIndex);
    }
    
    /**
     *  Returns a vector of CellPosition objects whose 
     *  <code>rowIndex</code> and <code>columnIndex</code> properties specify the 
     *  row and column indices of the cells that overlap the specified grid region.  
     *  If no such cells exist, an empty vector is returned.
     *  
     *  @param x The x coordinate of the pixel at the origin of the region, relative to the grid.
     * 
     *  @param x The x coordinate of the pixel at the origin of the region, relative to the grid. 
     * 
     *  @param w The width of the region, in pixels. 
     * 
     *  @param h The height of the region, in pixels. 
     *  
     *  @return A vector of objects like <code>Vector.&lt;Object&gt;([{rowIndex:0, columnIndex:0}, ...])</code>. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getCellsAt(x:Number, y:Number, w:Number, h:Number):Vector.<CellPosition>
    { 
        var cells:Vector.<CellPosition> = new Vector.<CellPosition>;
        
        if (w <= 0 || h <= 0)
            return cells;
        
        // Get the row/column indexes of the corners of the region.
        var topLeft:CellPosition = getCellAt(x, y);
        var bottomRight:CellPosition = getCellAt(x + w, y + h);
        if (!topLeft || !bottomRight)
            return cells;
        
        for (var rowIndex:int = topLeft.rowIndex; 
            rowIndex <= bottomRight.rowIndex; rowIndex++)
        {
            for (var columnIndex:int = topLeft.columnIndex; 
                columnIndex <= bottomRight.columnIndex; columnIndex++)
            {
                cells.push(new CellPosition(rowIndex, columnIndex));
            }
        }
        
        return cells;
    }
    
    /**
     *  Return the X coordinate of the specified cell's origin.  If the cell's entire bounds
     *  aren't needed, this method is more efficient than <code>getCellBounds().x</code>.
     * 
     *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
     *  it have not yet been scrolled into view, the returned value may only be an approximation, 
     *  based on all of the columns' <code>typicalItem</code>s.</p>
     * 
     *  @param rowIndex The 0-based index of the row.
     *  @param columnIndex The 0-based index of the column. 
     *  @return The x coordindate of the specified cell's origin.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getCellX(rowIndex:int, columnIndex:int):Number
    { 
        return gridDimensions.getCellX(rowIndex, columnIndex);
    }
    
    /**
     *  Return the Y coordinate of the specified cell's origin.  If the cell's entire bounds
     *  aren't needed, this method is more efficient than <code>getCellBounds().y</code>.
     * 
     *  <p>If all of the columns for the the specfied row and all of the rows preceeding 
     *  it have not yet been scrolled into view, the returned value may only be an approximation, 
     *  based on all of the columns' <code>typicalItem</code>s.</p>
     * 
     *  @param rowIndex The 0-based index of the row.
     *  @param columnIndex The 0-based index of the column. 
     *  @return The y coordindate of the specified cell's origin.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getCellY(rowIndex:int, columnIndex:int):Number
    { 
        return gridDimensions.getCellY(rowIndex, columnIndex);
    }      
    
    /**
     *  If the requested item renderer is visible, returns a reference to 
     *  the item renderer currently displayed at the specified cell.  
     *  Note that once the returned item renderer is no longer visible it may be 
     *  recycled and its properties reset.  
     * 
     *  <p>If the requested item renderer is not visible. then 
     *  each time this method is called, a new item renderer is created.  
     *  The new item renderer is not visible</p>
     * 
     *  <p>If the specified column does not have an explicit width, then the width
     *  of this cell is based on the <code>typicalItem</code>.  
     *  If a <code>typicalItem</code> was not specified or has not been measured yet, 
     *  then the item renderer's width defaults to <code>150</code>.</p>
     * 
     *  <p>If the grid property <code>variableRowHeight</code> is 
     *  <code>true</code> (the default) and an overall row height hasn't been 
     *  cached for the specified row, then the item renderer's height is based 
     *  on the <code>typicalItem</code>.  
     *  If the <code>typicalItem</code> was not 
     *  specified or has not been measured yet, then the item renderer's height 
     *  defaults to its preferred height.</p>
     *  
     *  @param rowIndex The 0-based row index of the item renderer's cell.
     * 
     *  @param columnIndex The 0-based column index of the item renderer's cell.
     * 
     *  @return The item renderer or null if the cell location is invalid.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function getItemRendererAt(rowIndex:int, columnIndex:int):IGridItemRenderer
    {
        const view:GridView = getGridViewAt(rowIndex, columnIndex);
		if (!view)
			return null;
		
        return view.gridViewLayout.getItemRendererAt(rowIndex, columnIndex);
    }    
    
    /**
     *  Returns <code>true</code> if the specified cell is at least partially visible. 
     *  If <code>columnIndex == -1</code>, then return 
     *  <code>true</code> if the specified row is at least partially visible. 
     *  If <code>rowIndex == -1</code>, then return <code>true</code> 
     *  if the specified column is at least partially visible. 
     *  If both <code>columnIndex</code> and <code>rowIndex</code> are -1, 
     *  then return <code>false</code>.
     *  
     *  @param rowIndex The 0-based row index of the item renderer's cell.
     * 
     *  @param columnIndex The 0-based column index of the item renderer's cell.
     * 
     *  @return True if the specified cell (or row if columnIndex == -1) is at least partially visible
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */        
    public function isCellVisible(rowIndex:int = -1, columnIndex:int = -1):Boolean
    {
        const view:GridView = getGridViewAt(rowIndex, columnIndex);
        return view && view.gridViewLayout.isCellVisible(rowIndex, columnIndex);
    }
    
    //--------------------------------------------------------------------------
    //
    //  Tracking Grid invalidateDisplayList() "reasons", invalid cells
    //
    //-------------------------------------------------------------------------- 
    
    /**
     *  @private
     *  Low cost "list" of invalidateDisplayList() reasons.
     */
    private var invalidateDisplayListReasonsMask:uint = 0;
    
    /**
     *  @private
     *  This flag makes it possible to defer clearing the invalidateDisplayListReasonsMask
     *  until after the Grid's subtree has been redisplayed.   It's set by updateDisplayList()
     *  and not cleared until the next invalidateDisplayListFor() call, on the assumption
     *  that the Grid subtree's updateDisplayList() methods will not reset any Grid properties
     *  (that call invalidateDisplayListFor()).
     */
    private var clearInvalidateDisplayListReasons:Boolean = false;
    
    /**
     *  @private
     *  Table that maps from reason names to bit fields.
     */
    private static const invalidateDisplayListReasonBits:Object = {
        verticalScrollPosition: uint(1 << 0),
        horizontalScrollPosition: uint(1 << 1),
        bothScrollPositions: (uint(1 << 0) | uint(1 << 1)),
        hoverIndicator: uint(1 << 2),
        caretIndicator: uint(1 << 3),
        selectionIndicator: uint(1 << 4),
        editorIndicator: uint(1 << 5),
        none: uint(~0)
    };
    
    /**
     *  @private
     *  Set the bit that corresponds to reason.  Only used by invalidateDisplayListFor().
     */
    private function setInvalidateDisplayListReason(reason:String):void
    {
        if (clearInvalidateDisplayListReasons)
        {
            invalidateDisplayListReasonsMask = 0;
            clearInvalidateDisplayListReasons = false;
        }
        
        invalidateDisplayListReasonsMask |= invalidateDisplayListReasonBits[reason];
    }
    
    /**
     *  @private
     *  Return true if invalidateDisplayListFor() was called with the specified reason
     *  since the last updateDisplayList() pass.
     */
    mx_internal function isInvalidateDisplayListReason(reason:String):Boolean
    {
        const bit:uint = invalidateDisplayListReasonBits[reason];
        return (invalidateDisplayListReasonsMask & bit) == bit;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Method Overrides
    //
    //--------------------------------------------------------------------------  
    
    /**
     *  @private
     */
    override public function getHorizontalScrollPositionDelta(navigationUnit:uint):Number
    {
		const gridLayout:GridLayout = layout as GridLayout;
		const centerGridView:GridView = gridLayout.centerGridView;			
        return (centerGridView) ? centerGridView.getHorizontalScrollPositionDelta(navigationUnit) : 0;     
    }
    
    /**
     *  @private
     */
    override public function getVerticalScrollPositionDelta(navigationUnit:uint):Number
    {
		const gridLayout:GridLayout = layout as GridLayout;
		const centerGridView:GridView = gridLayout.centerGridView;			
        return (centerGridView) ? centerGridView.getVerticalScrollPositionDelta(navigationUnit) : 0;     
    }
        
    
    /**
     *  @private
     *  During virtual layout updateDisplayList() eagerly validates lazily
     *  created (or recycled) IRs.   We don't want changes to those IRs to
     *  invalidate the size of the grid.
     * 
     *  This method also dispatches an invalidateSize event that's used 
     *  by the DataGrid to invalidate IDataGridElements.
     */
    override public function invalidateSize():void
    {
        if (!inUpdateDisplayList)
        {
            super.invalidateSize();
			
			for each (var view:GridView in allGridViews)
			{
				if (!view)
					continue;
				view.invalidateSize();    
			}
            
            dispatchChangeEvent("invalidateSize");            
        }
    }
    
    /**
     *  @private
     *  During virtual layout updateDisplayList() eagerly validates lazily
     *  created (or recycled) IRs.  Calls to invalidateDisplayList() eventually
     *  short-circuit but doing so early saves a few percent.
     * 
     *  This method also dispatches an invalidateDisplayList event that's used 
     *  by the DataGrid to invalidate IDataGridElements.
     */
    override public function invalidateDisplayList():void
    {
        if (!inUpdateDisplayList)
        {
            setInvalidateDisplayListReason("none");            
            super.invalidateDisplayList();
            
			for each (var view:GridView in allGridViews)
			{
				if (!view)
					continue;
				view.invalidateDisplayList();    
			}
			
			dispatchChangeEvent("invalidateDisplayList");
        }
    }
	
	private function get allGridViews():Array
	{
		const gridLayout:GridLayout = layout as GridLayout;
		return gridLayout ? [gridLayout.topLeftGridView, gridLayout.topGridView, gridLayout.leftGridView, gridLayout.centerGridView] : [];
	}
    
    private function createGridView():GridView
    {
        const elt:GridView = gridView.newInstance() as GridView;
        addElement(elt);
        return elt;
    }
    
	private function configureGridView(gv:GridView, viewRowIndex:int, viewColumnIndex:int, viewRowCount:int, viewColumnCount:int):void
	{
        const gridViewLayout:GridViewLayout = gv.gridViewLayout;
        gridViewLayout.grid = this;
		gridViewLayout.viewRowIndex = viewRowIndex;
		gridViewLayout.viewColumnIndex = viewColumnIndex;
		gridViewLayout.viewRowCount = viewRowCount;
		gridViewLayout.viewColumnCount = viewColumnCount;
	}
	
    /**
     *  Create and/or configure this Grid's GridViews.  We're assuming that the
     *  Grid's viewFactory, columns and dataProvider are specified.
	 * 
	 *  If GridVeiws are added or removed, a "gridViewsChanged" event is dispatched.
     */
    private function configureGridViews():void
    {
        const columnCount:int = columns.length;
        const rowCount:int = (dataProvider) ? dataProvider.length : 0;
		
		lockedColumnCount = Math.min(lockedColumnCount, columnCount);
		lockedRowCount = Math.min(lockedRowCount, rowCount);
		
		const centerRowCount:int = Math.max(0, rowCount - lockedRowCount);
        const centerColumnCount:int = Math.max(0, columnCount - lockedColumnCount); 
		
		const gridLayout:GridLayout = layout as GridLayout;
		var topLeftGridView:GridView = gridLayout.topLeftGridView;    
		var topGridView:GridView = gridLayout.topGridView;        
		var leftGridView:GridView = gridLayout.leftGridView;
		var centerGridView:GridView = gridLayout.centerGridView;
		var lockedRowsSeparatorElement:IVisualElement = gridLayout.lockedRowsSeparatorElement;
		var lockedColumnsSeparatorElement:IVisualElement = gridLayout.lockedColumnsSeparatorElement;
		
		var gridViewsChanged:Boolean = false;

        // Unconditionally create and configure the "center" GridView
        
        if (centerGridView == null)
		{
            gridLayout.centerGridView = centerGridView = createGridView();
			gridViewsChanged = true;
		}
        
        configureGridView(centerGridView, lockedRowCount, lockedColumnCount, -1, -1);
        
        centerGridView.gridViewLayout.requestedRowCount = requestedRowCount - lockedRowCount;
        centerGridView.gridViewLayout.requestedColumnCount = requestedColumnCount - lockedColumnCount; 
		
		// Remove or create/configure the topLeftGridView
		
		if ((lockedRowCount > 0) && (lockedColumnCount > 0))
		{
			if (!topLeftGridView)
			{
				gridLayout.topLeftGridView = topLeftGridView = createGridView();
				topLeftGridView.gridViewLayout.verticalScrollingLocked = true;
				topLeftGridView.gridViewLayout.horizontalScrollingLocked = true;
				gridViewsChanged = true;
			}
			
		}
		else if (topLeftGridView)
		{
			removeElement(topLeftGridView);
			gridLayout.topLeftGridView = topLeftGridView = null;
			gridViewsChanged = true;
		}
		
		if (topLeftGridView)
			configureGridView(topLeftGridView, 0, 0, lockedRowCount, lockedColumnCount);
		
        // Remove or create/configure the topGridView
        
        if (lockedRowCount > 0)
        {
            if (!topGridView)
			{
                gridLayout.topGridView = topGridView = createGridView();
				topGridView.gridViewLayout.verticalScrollingLocked = true;
				gridViewsChanged = true;
			}
            
            if (lockedRowsSeparator && !lockedRowsSeparatorElement)
            {
                gridLayout.lockedRowsSeparatorElement = lockedRowsSeparatorElement = lockedRowsSeparator.newInstance() as IVisualElement;
                addElement(lockedRowsSeparatorElement);
            }
        }
        else
        {
            if (topGridView)
            {
                removeElement(topGridView);
                gridLayout.topGridView = topGridView = null;
				gridViewsChanged = true;
            }

            if (lockedRowsSeparatorElement)
            {
                removeElement(lockedRowsSeparatorElement);
				gridLayout.lockedRowsSeparatorElement = lockedRowsSeparatorElement = null;
            }
        }

        if (topGridView)
            configureGridView(topGridView, 0, lockedColumnCount, lockedRowCount, centerColumnCount);
        
        // Remove or create/configure the leftGridView
        
        if (lockedColumnCount > 0)
        {
            if (!leftGridView)
			{
                gridLayout.leftGridView = leftGridView = createGridView();
				leftGridView.gridViewLayout.horizontalScrollingLocked = true;
				gridViewsChanged = true;
			}
            
            if (lockedColumnsSeparator && !lockedColumnsSeparatorElement)
            {
                gridLayout.lockedColumnsSeparatorElement = lockedColumnsSeparatorElement = lockedColumnsSeparator.newInstance() as IVisualElement;
                addElement(lockedColumnsSeparatorElement);
            }
        }
        else
        {
            if (leftGridView)
            {
                removeElement(leftGridView);
                gridLayout.leftGridView = leftGridView = null;
				gridViewsChanged = true;
            }
            
            if (lockedColumnsSeparatorElement)
            {
                removeElement(lockedColumnsSeparatorElement);
				gridLayout.lockedColumnsSeparatorElement = lockedColumnsSeparatorElement = null;
            }
        }
        
        if (leftGridView)
            configureGridView(leftGridView, lockedRowCount, 0, centerRowCount, lockedColumnCount);
		
		if (gridViewsChanged)
			dispatchChangeEvent("gridViewsChanged");
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        // rowHeight and variableRowHeight can be set in either order
        if (variableRowHeightChanged || rowHeightChanged)
        {
            if (rowHeightChanged)
                gridDimensions.defaultRowHeight = _rowHeight;
            gridDimensions.variableRowHeight = variableRowHeight;
            
            if ((!variableRowHeight && rowHeightChanged) || variableRowHeightChanged)
            {
                clearGridLayoutCache(false);
                invalidateSize();
                invalidateDisplayList();
            }
            
            rowHeightChanged = false;
            variableRowHeightChanged = false;
        }

        // item renderer changed or typical item changed
        if (itemRendererChanged || typicalItemChanged)
        {
            clearGridLayoutCache(true);
            itemRendererChanged = false;
        }
        
        // Try to generate columns if there aren't any or there are generated
        // ones which need to be regenerated because the typicalItem or 
        // dataProvider changed.
        if (!columns || (generatedColumns && 
            (typicalItemChanged || (!typicalItem && dataProviderChanged))))
        {
            const oldColumns:IList = columns;
            columns = generateColumns();
            generatedColumns = (columns != null);
            columnsChanged = columns != oldColumns;
        }
        typicalItemChanged = false;
        
        // If the dataProvider or columns change, reset the selection and 
        // the grid dimensions.  This has to be done here rather than in the 
        // setters because the gridSelection and gridDimensions might not 
        // be set yet, depending on the order they are initialized when the 
        // grid skin part is added to the data grid.
        
        if (dataProviderChanged || columnsChanged)
        {
            
            // Remove the current selection and, if requireSelection, make
            // sure the selection is reset to row 0 or cell 0,0.
            if (gridSelection)
            {
                var savedRequireSelection:Boolean = gridSelection.requireSelection;
                gridSelection.requireSelection = false;
                gridSelection.removeAll();
                gridSelection.requireSelection = savedRequireSelection;
            } 
            
           // make sure we have the right number of columns.
            if (columnsChanged)
                gridDimensions.columnCount = _columns ? _columns.length : 0;
           
           // Keep typical item size cache only when the typical item is still valid
           // and the columns haven't changed.
           if (typicalItem != null && !columnsChanged)
               clearGridLayoutCache(false);
           else
               clearGridLayoutCache(true);
            
            if (!caretChanged)
                initializeCaretPosition();

            if (!anchorChanged)
                initializeAnchorPosition();
            
            dataProviderChanged = false;
            columnsChanged = false;
        }
        
        anchorChanged = false;
        
        // Create or reconfigure the Grid's GridViews
        
        if (gridView && columns)
            configureGridViews();
		
        // Deferred selection operations
        
        if (dataProvider)
        {
            for each (var deferredOperation:Function in deferredOperations)
                deferredOperation();
            deferredOperations.length = 0;                
        }
        
        // Only want one event if both caretRowIndex and caretColumnIndex changed

        if (caretChanged)
        {
            // Validate values now.  Need to let caret be set in the same
            // update as the dp and/or columns.  -1 is a valid value.            
            if (_dataProvider && caretRowIndex >= _dataProvider.length)
                _caretRowIndex = _dataProvider.length - 1;
            if (_columns && caretColumnIndex >= _columns.length)
                _caretColumnIndex = getPreviousVisibleColumnIndex(_columns.length - 1);

            caretSelectedItem = 
                _dataProvider && _caretRowIndex >= 0 ?
                _dataProvider.getItemAt(_caretRowIndex) : null;

            dispatchCaretChangeEvent();
            
            // Last reported values.
            _oldCaretRowIndex = _caretRowIndex;
            _oldCaretColumnIndex = _caretColumnIndex;
            
            caretChanged = false;        
         }

        if (updateCaretForDataProviderChanged)
        {
            updateCaretForDataProviderChanged = false;
            updateCaretForDataProviderChange(updateCaretForDataProviderChangeLastEvent);
            updateCaretForDataProviderChangeLastEvent = null;
        }
    }
    
    
    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        inUpdateDisplayList = true;
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        inUpdateDisplayList = false;
		
        clearInvalidateDisplayListReasons = true;
		
		if (!variableRowHeight)
			setFixedRowHeight(gridDimensions.getRowHeight(0));
	}
        
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------      
    
    /**
     *  @private
     *  This version of invlaidateDisplayList() stores the "reason" for the invalidate
     *  request so that GridLayout/updateDisplayList() can do its job more efficiently.
     *  GridLayout tests the accumulated invalidateDisplayList reasons with 
     *  isInvalidateDisplayListReason() and they're automatically cleared by 
     *  updateDisplayList() here.
     * 
     *  Note that if invalidateDisplayList() is called directly, all possible 
     *  invalidateDispayList reasons are implicitly specified, in other words if
     *  no reason is specified then they all are (see invalidateDisplayListReasonBits.none).
     *  That way, callers need not be aware of this internal API.
     * 
     *  Also: most reason="selectionIndicator" calls also change the caret index which
     *  in turn adds reason="caretIndicator" to the invalidateDisplayList reasons, if the
     *  caret index actually changed.
     */
    mx_internal function invalidateDisplayListFor(reason:String):void
    {
        if (!inUpdateDisplayList)
        {
            setInvalidateDisplayListReason(reason);          
            super.invalidateDisplayList();

			// Minor optimization: if the reason for this invalidation is a 
			// scroll, don't invalidate GridViews that can't change. 
			
			const vspReason:Boolean = reason == "verticalScrollPosition";
			const hspReason:Boolean = reason == "horizontalScrollPosition";
			const bothReason:Boolean = reason == "bothScrollPositions";
			
			const gridLayout:GridLayout = layout as GridLayout;
			const topLeftGridView:GridView = gridLayout.topLeftGridView;    
			const topGridView:GridView = gridLayout.topGridView;        
			const leftGridView:GridView = gridLayout.leftGridView;
			const centerGridView:GridView = gridLayout.centerGridView;			
			
			if (topLeftGridView && !vspReason && !hspReason && !bothReason)
				topLeftGridView.invalidateDisplayList();
			
			if (topGridView && !vspReason)
                topGridView.invalidateDisplayList();
			
			if (leftGridView && !hspReason)
				leftGridView.invalidateDisplayList();			
			
            if (centerGridView)  
                centerGridView.invalidateDisplayList();
            
            dispatchChangeEvent("invalidateDisplayList");
        }
    }
    
    /**
     *  If the specified cell is visible, it is redisplayed.  
     *  If <code>variableRowHeight=true</code>, 
     *  then doing so may cause the height of the corresponding row to change.
     * 
     *  <p>If columnIndex is -1, then the entire row is invalidated.  
     *  Similarly if <code>rowIndex is -1</code>, then the entire column is invalidated.</p>
     * 
     *  <p>This method should be called when there is a change to any aspect of 
     *  the data provider item at <code>rowIndex</code> that might have some 
     *  impact on the way the  specified cell is displayed. 
     *  Calling this method is similar to calling the
     *  <code>dataProvider.itemUpdated()</code> method, which advises the Grid that all rows
     *  displaying the specified item should be redisplayed.  
     *  Using this method can be relatively efficient, since it narrows 
     *  the scope of the change to a single cell.</p>
     * 
     *  @param rowIndex The 0-based row index of the cell that changed, or -1.
     *
     *  @param columnIndex The 0-based column index of the cell that changed or -1.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function invalidateCell(rowIndex:int, columnIndex:int):void
    {
        if ((rowIndex == -1) && (columnIndex == -1))
        {
			invalidateDisplayList();
            return;
        }
        
        const view:GridView = getGridViewAt(rowIndex, columnIndex);
        if (!dataProvider || !view)
            return;
        
        const gridLayout:GridViewLayout = view.gridViewLayout;
        const dataProviderLength:int = dataProvider.length;
        if (!gridLayout || (rowIndex >= dataProvider.length))
            return;
        
        if (!isCellVisible(rowIndex, columnIndex))
            return;

        if (invalidateDisplayListFlag || invalidateSizeFlag)
            return;        
        
        if ((rowIndex >= 0) && (columnIndex >= 0))
        {
            gridLayout.invalidateCell(rowIndex, columnIndex);
        }
        else if (rowIndex >= 0)  // invalidate a row
        {
            const visibleColumnIndices:Vector.<int> = getVisibleColumnIndices();
            for each (var visibleColumnIndex:int in visibleColumnIndices)
            {
                gridLayout.invalidateCell(rowIndex, visibleColumnIndex);
                
                // If invalidating the cell caused the entire grid to be invalid, punt 
                if (invalidateDisplayListFlag || invalidateSizeFlag)
                    break;                
            }
        }
        else if (columnIndex >= 0)  // invalidate a column
        {
            const visibleRowIndices:Vector.<int> = getVisibleRowIndices();
            for each (var visibleRowIndex:int in visibleRowIndices)
            {
                // If there are any padding rows, skip them.
                if (visibleRowIndex >= dataProviderLength)
                    break;
                
                gridLayout.invalidateCell(visibleRowIndex, columnIndex);

                // If invalidating the cell caused the entire grid to be invalid, punt 
                if (invalidateDisplayListFlag || invalidateSizeFlag)
                    break;
            }
        }
    }
    
    /**
     *  Creates a grid selection object to use to manage selection. Override this method if you have a custom grid 
     *  selection that you want to use in place of the default and this grid is not a skin part for DataGrid.  
     *  This method is not used when this grid is a skin part for DataGrid.
     *
     *  @see spark.components.DataGrid.createGridSelection
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    mx_internal function createGridSelection():GridSelection
    {
        return new GridSelection();    
    }


    /**
    *  This will search through a dataprovider checking the given field and for the given value and return the index for the match.
    *  It can start the find from a given startingIndex;
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function findRowIndex(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):int
    {
        var pattern:RegExp; 
        var currentObject:Object = null;
        var dataProviderTotal:int = 0;
        var loopingIndex:int = startingIndex;

        
        pattern = RegExPatterns.createRegExp(value, patternType);


        if (dataProvider && dataProvider.length > 0)
        {
            dataProviderTotal = dataProvider.length;

            if (startingIndex >= dataProviderTotal)
            {
                return -1;
            }


            for (loopingIndex; loopingIndex < dataProviderTotal; loopingIndex++)
            {
                currentObject = dataProvider.getItemAt(loopingIndex);

                if (currentObject.hasOwnProperty(field) == true && currentObject[field].search(pattern) != -1)
                {
                    return loopingIndex;
                }
            }

        }

        return -1;
    }


    /**
    *  This will search through a dataprovider checking the given field and for the given values and return an array of indices that matched.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function findRowIndices(field:String, values:Array, patternType:String = RegExPatterns.EXACT):Array
    {
        var currentObject:Object = null;
        var regexList:Array = [];
        var matchedIndices:Array = [];
        var dataProviderTotal:uint = 0;
        var valuesTotal:uint = 0;
        var loopingDataProviderIndex:uint = 0;
        var loopingValuesIndex:uint = 0;


        if (dataProvider != null && dataProvider.length > 0 && values != null && values.length > 0)
        {
            dataProviderTotal = dataProvider.length;
            valuesTotal = values.length;


            //Set the regex patterns in an array once.
            for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
            {
                regexList.push(RegExPatterns.createRegExp(values[loopingValuesIndex], patternType));
            }


            //Loop through dataprovider
            for (loopingDataProviderIndex; loopingDataProviderIndex < dataProviderTotal; loopingDataProviderIndex++)
            {
                currentObject = dataProvider.getItemAt(loopingDataProviderIndex);

                if (currentObject.hasOwnProperty(field) == false)
                {
                    continue;
                }

                //Loop through regex patterns from the values array.
                for (loopingValuesIndex = 0; loopingValuesIndex < valuesTotal; loopingValuesIndex++)
                {
                    if (currentObject[field].search(regexList[loopingValuesIndex]) != -1)
                    {
                        matchedIndices.push(loopingDataProviderIndex);

                        break;
                    }
                }
            }

        }


        return matchedIndices;
    }


    /**
    *  This will search through a dataprovider checking the given field and will set the selectedIndex to a matching value.
    *  It can start the search from the startingIndex;
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    *
    */
    public function moveIndexFindRow(field:String, value:String, startingIndex:int = 0, patternType:String = RegExPatterns.EXACT):Boolean
    {
        var indexFound:int = -1;

        indexFound = findRowIndex(field, value, startingIndex, patternType);

        if (indexFound != -1)
        {
            selectedIndex = indexFound;

            return true;
        }

        return false;
    }


    /**
    *  Changes the selectedIndex to the first row of the dataProvider.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexFirstRow():void
    {
        if (dataProvider && dataProvider.length > 0)
        {
            selectedIndex = 0;
        }
    }


    /**
    *  Changes the selectedIndex to the last row of the dataProvider.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexLastRow():void
    {
        if (dataProvider && dataProvider.length > 0)
        {
            selectedIndex = dataProvider.length - 1;
        }
    }


    /**
    *  Changes the selectedIndex to the next row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
    *  If the selectedIndex is on the first row, it does not wrap around.  However the <code>isFirstRow</code> property returns true.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexNextRow():void
    {
        if (dataProvider && dataProvider.length > 0 && selectedIndex >= 0)
        {
            if (isLastRow == false)
            {
                selectedIndex += 1;
            }
        }
    }


    /**
    *  Changes the selectedIndex to the previous row of the dataProvider.  If there isn't a current selectedIndex, it silently returns.
    *  If the selectedIndex is on the last row, it does not wrap around.  However the <code>isLastRow</code> property returns true.
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexPreviousRow():void
    {
        if (dataProvider && dataProvider.length > 0 && selectedIndex >= 0)
        {
            if (isFirstRow == false)
            {
                selectedIndex -= 1;
            }
        }
    }


    //--------------------------------------------------------------------------
    //
    //  Methods: Internal Grid Access
    //
    //--------------------------------------------------------------------------      
    
    /**
     *  @private
     */
    private function getGridColumn(columnIndex:int):GridColumn
    {
        const columns:IList = columns;
        if ((columns == null) || (columnIndex < 0) || (columnIndex >= columns.length))
            return null;
        
        return columns.getItemAt(columnIndex) as GridColumn;
    }
    
    /**
     *  @private
     */
    mx_internal function getDataProviderItem(rowIndex:int):Object
    {
        const dataProvider:IList = dataProvider;
        if ((dataProvider == null) || (rowIndex >= dataProvider.length))
            return null;
        
        return dataProvider.getItemAt(rowIndex);
    }
    
    /**
     *  @private
     */
    private function getVisibleItemRenderer(rowIndex:int, columnIndex:int):IGridItemRenderer
    {
		const view:GridView = getGridViewAt(rowIndex, columnIndex);
		if (!view)
			return null;
        
        const gridViewLayout:GridViewLayout = view.gridViewLayout;
		const viewRowIndex:int = rowIndex - gridViewLayout.viewRowIndex;
		const viewColumnIndex:int = columnIndex - gridViewLayout.viewColumnIndex;
        return gridViewLayout.getVisibleItemRenderer(viewRowIndex, viewColumnIndex);
    }
    
    //--------------------------------------------------------------------------
    //
    //  GridEvents
    //
    //--------------------------------------------------------------------------  
    
    private var rollRowIndex:int = -1;
    private var rollColumnIndex:int = -1;
    private var mouseDownRowIndex:int = -1;
    private var mouseDownColumnIndex:int = -1;
    private var lastClickedColumnIndex:int = -1;
    private var lastClickedRowIndex:int = -1;
    private var lastClickTime:Number;
    
    // default max time between clicks for a double click is 480ms.
    mx_internal var DOUBLE_CLICK_TIME:Number = 480;

    /** 
     *  @private
     *  Return the GridView whose bounds contain the MouseEvent, or null.  Note that the 
     *  comparison is based strictly on the event's location and the GridViews' bounds.
     *  The event's target can be anything.
     */
    private function mouseEventGridView(event:MouseEvent):GridView
    {
        const gridLayout:GridLayout = layout as GridLayout;

        const centerGridView:GridView = gridLayout.centerGridView;
        if (centerGridView && centerGridView.containsMouseEvent(event))
            return centerGridView;

        const leftGridView:GridView = gridLayout.leftGridView;
        if (leftGridView && leftGridView.containsMouseEvent(event))
            return leftGridView;
        
        const topGridView:GridView = gridLayout.topGridView;
        if (topGridView && topGridView.containsMouseEvent(event))
            return topGridView;

        const topLeftGridView:GridView = gridLayout.topLeftGridView;
        if (topLeftGridView && topLeftGridView.containsMouseEvent(event))
            return topLeftGridView;

        return null;
    }
    
    /** 
     *  @private
     *  Return the Grid-relative row,column (gridCP) and X,Y location (gridXY) of the MouseEvent.
     */    
    private function eventToGridLocations(event:MouseEvent, gridCP:CellPosition, gridXY:Point):void
    {
        const stageXY:Point = new Point(event.stageX, event.stageY);
        const localXY:Point = globalToLocal(stageXY);
        gridXY.x = localXY.x;  // event may not have targeted the Grid
        gridXY.y = localXY.y;
        
        const view:GridView = mouseEventGridView(event);
        if (view)
        {
            const viewXY:Point = view.globalToLocal(stageXY);
            const gridViewLayout:GridViewLayout = view.gridViewLayout;
            const gdv:GridDimensionsView = gridViewLayout.gridDimensionsView;

            
            gridCP.rowIndex = gdv.getRowIndexAt(viewXY.x, viewXY.y) + gridViewLayout.viewRowIndex;
            gridCP.columnIndex = gdv.getColumnIndexAt(viewXY.x, viewXY.y) + gridViewLayout.viewColumnIndex;

            gridXY.x = viewXY.x + gdv.viewOriginX;
            gridXY.y = viewXY.y + gdv.viewOriginY;
        }
        else
        {
            gridCP.rowIndex = -1;
            gridCP.columnIndex = -1;
        }
    }
    
    /**
     *  @private
     *  This method is called when a MOUSE_DOWN event occurs within the grid and 
     *  for all subsequent MOUSE_MOVE events until the button is released (even if the 
     *  mouse leaves the grid).  The last event in such a "down drag up" gesture is 
     *  always a MOUSE_UP.  By default this method dispatches GRID_MOUSE_DOWN, 
     *  GRID_MOUSE_DRAG, or a GRID_MOUSE_UP event in response to the the corresponding
     *  mouse event.  The GridEvent's rowIndex, columnIndex, column, item, and itemRenderer 
     *  properties correspond to the grid cell under the mouse.  
     * 
     *  @param event A MOUSE_DOWN, MOUSE_MOVE, or MOUSE_UP MouseEvent from a down/move/up gesture initiated within the grid.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */    
    protected function grid_mouseDownDragUpHandler(event:MouseEvent):void
    {
        const eventGridCP:CellPosition = new CellPosition();
        const eventGridXY:Point = new Point();
        eventToGridLocations(event, eventGridCP, eventGridXY);
        
        const eventRowIndex:int = eventGridCP.rowIndex;
        const eventColumnIndex:int = eventGridCP.columnIndex;
        
        var gridEventType:String;
        switch(event.type)
        {
            case MouseEvent.MOUSE_MOVE: 
            {
                gridEventType = GridEvent.GRID_MOUSE_DRAG; 
                break;
            }
            case MouseEvent.MOUSE_UP: 
            {
                gridEventType = GridEvent.GRID_MOUSE_UP;
                break;
            }
            case MouseEvent.MOUSE_DOWN:
            {
                gridEventType = GridEvent.GRID_MOUSE_DOWN;
                mouseDownRowIndex = eventRowIndex;
                mouseDownColumnIndex = eventColumnIndex;
                dragInProgress = true;
                break;
            }
        }
        
        dispatchGridEvent(event, gridEventType, eventGridXY, eventRowIndex, eventColumnIndex);
        if (gridEventType == GridEvent.GRID_MOUSE_UP)
            dispatchGridClickEvents(event, eventGridXY, eventRowIndex, eventColumnIndex);        
    }
    
    /**
     *  @private
     *  This method is called whenever a MOUSE_MOVE event occurs within the grid
     *  without the button pressed.  By default it dispatches a GRID_ROLL_OVER for the
     *  first MOUSE_MOVE GridEvent whose location is within a grid cell, and a 
     *  GRID_ROLL_OUT GridEvent when the mouse leaves a cell.  Listeners are guaranteed
     *  to receive a GRID_ROLL_OUT event for every GRID_ROLL_OVER event.
     * 
     *  @param event A MOUSE_MOVE MouseEvent within the grid, without the button pressed.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */    
    protected function grid_mouseMoveHandler(event:MouseEvent):void
    {
        const eventGridCP:CellPosition = new CellPosition();
        const eventGridXY:Point = new Point();
        eventToGridLocations(event, eventGridCP, eventGridXY);

        const eventRowIndex:int = eventGridCP.rowIndex;
        const eventColumnIndex:int = eventGridCP.columnIndex;
        
        if ((eventRowIndex != rollRowIndex) || (eventColumnIndex != rollColumnIndex))
        {
            if ((rollRowIndex != -1) || (rollColumnIndex != -1))
                dispatchGridEvent(event, GridEvent.GRID_ROLL_OUT, eventGridXY, rollRowIndex, rollColumnIndex);
            if ((eventRowIndex != -1) && (eventColumnIndex != -1))
                dispatchGridEvent(event, GridEvent.GRID_ROLL_OVER, eventGridXY, eventRowIndex, eventColumnIndex);
            rollRowIndex = eventRowIndex;
            rollColumnIndex = eventColumnIndex;
        }
    }
    
    /**
     *  @private
     *  This method is called whenever a ROLL_OUT occurs on the grid.
     *  By default it dispatches a GRID_ROLL_OUT event.
     * 
     *  @param event A ROLL_OUT MouseEvent from the grid.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */       
    protected function grid_mouseRollOutHandler(event:MouseEvent):void
    {
        if ((rollRowIndex != -1) || (rollColumnIndex != -1))
        {
            const eventStageXY:Point = new Point(event.stageX, event.stageY);
            const eventGridXY:Point = globalToLocal(eventStageXY);      
            
            dispatchGridEvent(event, GridEvent.GRID_ROLL_OUT, eventGridXY, rollRowIndex, rollColumnIndex);
            rollRowIndex = -1;
            rollColumnIndex = -1;
        }
    }
    
    /**
     *  @private
     *  This method is called whenever a GRID_MOUSE_UP occurs on the grid.
     *  By default it dispatches a GRID_MOUSE_UP event.
     * 
     *  @param event A GRID_MOUSE_UP MouseEvent from the grid.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */       
    protected function grid_mouseUpHandler(event:MouseEvent):void 
    {
        if (dragInProgress)
        {
            // drag handler has already dispatched a mouse up event, don't do so again here
            dragInProgress = false;
            return;
        }
        
        const eventGridCP:CellPosition = new CellPosition();
        const eventGridXY:Point = new Point();
        eventToGridLocations(event, eventGridCP, eventGridXY);
        
        const eventRowIndex:int = eventGridCP.rowIndex;
        const eventColumnIndex:int = eventGridCP.columnIndex;        
        
        dispatchGridEvent(event, GridEvent.GRID_MOUSE_UP, eventGridXY, eventRowIndex, eventColumnIndex);
        dispatchGridClickEvents(event, eventGridXY, eventRowIndex, eventColumnIndex);
    }
    
    /**
     *  @private
     *  This method is called after we dispatch a GRID_MOUSE_UP.
     *  It determines whether to dispatch a GRID_CLICK or GRID_DOUBLE_CLICK
     *  event following a GRID_MOUSE_UP.
     * 
     *  A GRID_CLICK event is dispatched when the mouse up event happens in
     *  the same cell as the mouse down event.
     * 
     *  A GRID_DOUBLE_CLICK event is dispatched in place of the GRID_CLICK
     *  event when the last click event happened within DOUBLE_CLICK_TIME.
     */       
    private function dispatchGridClickEvents(mouseEvent:MouseEvent, gridXY:Point, rowIndex:int, columnIndex:int):void
    {
        const dispatchGridClick:Boolean = ((rowIndex == mouseDownRowIndex) && (columnIndex == mouseDownColumnIndex));
        const newClickTime:Number = getTimer();
        var isDoubleClick:Boolean = false;

        // In the case that we dispatched a click last time, check if we
        // should dispatch a double click this time.  The type of check will be based on the double click mode.
        if (doubleClickEnabled && dispatchGridClick && !isNaN(lastClickTime) &&
            (newClickTime - lastClickTime <= DOUBLE_CLICK_TIME))
        {
            switch(_doubleClickMode)
            {
                case GridDoubleClickMode.CELL:
                {
                    if (rowIndex != -1 && columnIndex != -1 && rowIndex == lastClickedRowIndex && columnIndex == lastClickedColumnIndex)
                    {
                        isDoubleClick = true;
                    }

                    break;
                }

                case GridDoubleClickMode.GRID:
                {
                    isDoubleClick = true;

                    break;
                }

                case GridDoubleClickMode.ROW:
                {
                    if (rowIndex != -1 && rowIndex == lastClickedRowIndex)
                    {
                        isDoubleClick = true;
                    }

                    break;
                }
            }

            if (isDoubleClick == true)
            {
                dispatchGridEvent(mouseEvent, GridEvent.GRID_DOUBLE_CLICK, gridXY, rowIndex, columnIndex);
                lastClickTime = NaN;
                lastClickedColumnIndex = -1;
                lastClickedRowIndex = -1;
                isDoubleClick = false;

                return;
            }
        }
        
        // Otherwise, just dispatch the click event.
        if (dispatchGridClick)
        {
            dispatchGridEvent(mouseEvent, GridEvent.GRID_CLICK, gridXY, rowIndex, columnIndex);
            lastClickTime = newClickTime;
            lastClickedColumnIndex = columnIndex;
            lastClickedRowIndex = rowIndex;
            isDoubleClick = false;
        }
    }
    
    /**
     *  @private
     */
    private function dispatchGridEvent(mouseEvent:MouseEvent, type:String, gridXY:Point, rowIndex:int, columnIndex:int):void
    {
        const column:GridColumn = columnIndex >= 0 ? getGridColumn(columnIndex) : null;
        const item:Object = rowIndex >= 0 ? getDataProviderItem(rowIndex) : null;
        const itemRenderer:IGridItemRenderer = getVisibleItemRenderer(rowIndex, columnIndex);
        const bubbles:Boolean = mouseEvent.bubbles;
        const cancelable:Boolean = mouseEvent.cancelable;
        const relatedObject:InteractiveObject = mouseEvent.relatedObject;
        const ctrlKey:Boolean = mouseEvent.ctrlKey;
        const altKey:Boolean = mouseEvent.altKey;
        const shiftKey:Boolean = mouseEvent.shiftKey;
        const buttonDown:Boolean = mouseEvent.buttonDown;
        const delta:int = mouseEvent.delta;        

        const event:GridEvent = new GridEvent(
            type, bubbles, cancelable, 
            gridXY.x, gridXY.y, 
            relatedObject, ctrlKey, altKey, shiftKey, buttonDown, delta,
            rowIndex, columnIndex, column, item, itemRenderer);
        dispatchEvent(event);
    }
        
    //--------------------------------------------------------------------------
    //
    //  IList listeners: columns, dataProvider
    //
    //--------------------------------------------------------------------------  

    /**
     *  @private
     *  Update caretRowIndex if necessary.  This method should only be called when 
     *  caretRowIndex is valid, i.e. != -1.
     */
    private function updateCaretForDataProviderChange(event:CollectionEvent):void
    {
        const oldCaretRowIndex:int = caretRowIndex;
        const location:int = event.location;
        const itemsLength:int = event.items ? event.items.length : 0;                
        var newCaretRowIndex:int; 
        
        switch (event.kind)
        {
            case CollectionEventKind.ADD:
                if (oldCaretRowIndex >= location)
                    caretRowIndex += event.items.length;
                break;
           
            case CollectionEventKind.REMOVE:
                if (oldCaretRowIndex >= location)
                {
                    // ToDo(cframpto):  If the caret is on an item that is deleted, rather than
                    // removing the caret, which is what we do now, it is preferable
                    // to have the caret "stick" to the same position.  There is some complexity 
                    // to picking a row/cell based on what’s currently visible or partially 
                    // visible – after – the delete operation.
                    if (oldCaretRowIndex < (location + itemsLength))
                        caretRowIndex = -1; 
                    else
                        caretRowIndex -= itemsLength;    
                }
                
                break;
            
            case CollectionEventKind.MOVE:
                {
                    const oldLocation:int = event.oldLocation;
                    if ((oldCaretRowIndex >= oldLocation) && (oldCaretRowIndex < (oldLocation + itemsLength)))
                    {
                        caretRowIndex += location - oldLocation;
                        ensureCellIsVisible(caretRowIndex, -1);
                    }
                }
                break;                        
                
            case CollectionEventKind.REPLACE:
            case CollectionEventKind.UPDATE:
                break;
                        
            case CollectionEventKind.REFRESH:
            {
                newCaretRowIndex = 
                            caretSelectedItem ?
                            _dataProvider.getItemIndex(caretSelectedItem) : -1; 
                         
                // Caret sticks to item if possible and ensure it is totally 
                // visible by scrolling vertically if necessary.
                if (newCaretRowIndex != -1)
                {
                    caretRowIndex = newCaretRowIndex;
                    ensureCellIsVisible(caretRowIndex, -1);
                }
                else
                {
                    // No caret.  Maintain the existing scroll position if
                    // within the current data.
                    
                    var oldVsp:int = verticalScrollPosition;
                    
                    validateNow();
                    
                    // If variable row heights the height is 
                    // approximate so the scroll position may not be
                    // in exactly the same place.
                    
                    const cHeight:Number = Math.ceil(gridDimensions.getContentHeight());
                    const maximum:int = Math.max(cHeight - height, 0);
                    verticalScrollPosition = (oldVsp > maximum) ? maximum : oldVsp;                        
                }
                break;
            }
        
            case CollectionEventKind.RESET:
            {
                newCaretRowIndex = 
                    caretSelectedItem ?
                    _dataProvider.getItemIndex(caretSelectedItem) : -1; 
                
                // Caret sticks to item if possible and ensure it is totally 
                // visible by scrolling vertically if necessary.
                if (newCaretRowIndex != -1)
                {
                    caretRowIndex = newCaretRowIndex;
                    ensureCellIsVisible(caretRowIndex, -1);
                }
                
                // No caret item so reset caret and vsp.
                else 
                {
                    caretRowIndex = _dataProvider.length > 0 ? 0 : -1;
                    // we need to call validateSize() to force computing maxTypicalCellHeight  or verticalScrollPosition will fail
                   GridLayout(layout).centerGridView.validateSize();
                   verticalScrollPosition = 0;
                }
                
                break;
            }
        }   
        
    }
    
    /**
     *  @private
     *  Update caretColumnIndex if necessary.  This method should only be 
     *  called when caretColumnIndex is valid, i.e. != -1.
     */
    private function updateCaretForColumnsChange(event:CollectionEvent):void
    {
        const oldCaretColumnIndex:int = caretColumnIndex;
        const location:int = event.location;
        const itemsLength:int = event.items ? event.items.length : 0;
        
        switch (event.kind)
        {
            case CollectionEventKind.ADD:
                if (oldCaretColumnIndex >= location)
                    caretColumnIndex += itemsLength;
                break;
            
            case CollectionEventKind.REMOVE:
                if (oldCaretColumnIndex >= location)
                {
                    if (oldCaretColumnIndex < (location + itemsLength))
                        caretColumnIndex = _columns.length > 0 ? 0 : -1; 
                    else
                        caretColumnIndex -= itemsLength;    
                }                   
                break;
            
            case CollectionEventKind.MOVE:
                const oldLocation:int = event.oldLocation;
                if ((oldCaretColumnIndex >= oldLocation) && (oldCaretColumnIndex < (oldLocation + itemsLength)))
                    caretColumnIndex += location - oldLocation;
                break;                        
            
            case CollectionEventKind.REPLACE:
                break;
            
            case CollectionEventKind.UPDATE:
                // column may have changed visiblity which matters if cell 
                // selection mode.
                var pe:PropertyChangeEvent;
                
                if (selectionMode == GridSelectionMode.SINGLE_CELL || 
                    selectionMode == GridSelectionMode.MULTIPLE_CELLS)
                {
                    for (var i:int = 0; i < itemsLength; i++)
                    {
                        pe = event.items[i] as PropertyChangeEvent;
                        if (pe && pe.property == "visible")
                        {
                            const column:GridColumn = pe.source as GridColumn;
                            if (!column || column.visible)
                                continue;
                            
                            if (column.columnIndex == caretColumnIndex)
                                initializeCaretPosition(true);  // column only
                            if (column.columnIndex == anchorColumnIndex)
                                initializeAnchorPosition(true);  // column only
                        }
                    }
                }
                break;
            
            case CollectionEventKind.REFRESH:
            case CollectionEventKind.RESET:
                initializeCaretPosition(true);  // column only
                horizontalScrollPosition = 0;
                break;
        }            
    }

    /**
     *  @private
     *  Update hoverRowIndex if necessary.  This method should only be called when 
     *  hoverRowIndex is valid, i.e. != -1.
     */
    private function updateHoverForDataProviderChange(event:CollectionEvent):void
    {
        const oldHoverRowIndex:int = hoverRowIndex;
        const location:int = event.location;
        
        switch (event.kind)
        {
            case CollectionEventKind.ADD:
            case CollectionEventKind.REMOVE:
            case CollectionEventKind.REPLACE:
            case CollectionEventKind.UPDATE:
            case CollectionEventKind.MOVE:
                if (oldHoverRowIndex >= location)
                    hoverRowIndex = gridDimensions.getRowIndexAt(mouseX, mouseY);
                break;
                           
            case CollectionEventKind.REFRESH:
            case CollectionEventKind.RESET:
                hoverRowIndex = gridDimensions.getRowIndexAt(mouseX, mouseY);
                break;
        }                        
    }
    
    /**
     *  @private
     *  Update hoverColumnIndex if necessary.  This method should only be called when 
     *  hoverColumnIndex is valid, i.e. != -1.
     */
    private function updateHoverForColumnsChange(event:CollectionEvent):void
    {
        switch (event.kind)
        {
            case CollectionEventKind.ADD:
            case CollectionEventKind.REMOVE:
            case CollectionEventKind.REPLACE:
            case CollectionEventKind.UPDATE:
            case CollectionEventKind.MOVE:
                if (hoverColumnIndex >= event.location)
                    hoverColumnIndex = gridDimensions.getColumnIndexAt(mouseX, mouseY);
                break;
                            
            case CollectionEventKind.REFRESH:
            case CollectionEventKind.RESET:
                hoverColumnIndex = gridDimensions.getColumnIndexAt(mouseX, mouseY);
                break;
        }
    }

    /**
     *  @private
     */
    private function dataProvider_collectionChangeHandler(event:CollectionEvent):void
    {
        var selectionChanged:Boolean = false;


        // If no columns exist, we should try to generate them.
        if (!columns && dataProvider.length > 0)
        {
            columns = generateColumns();
            generatedColumns = (columns != null);
            this.gridDimensions.columnCount = generatedColumns ? columns.length : 0;
        }

        const gridDimensions:GridDimensions = this.gridDimensions;
        if (gridDimensions)
        {
            gridDimensions.dataProviderCollectionChanged(event);
            gridDimensions.rowCount = dataProvider.length;
        }
        
        for each (var view:GridView in allGridViews)
        {
            if (!view)
                continue;
            view.gridViewLayout.dataProviderCollectionChanged(event);      
        }
        
        if (gridSelection)
            selectionChanged = gridSelection.dataProviderCollectionChanged(event);            
        
        if (gridDimensions && hoverRowIndex != -1)
            updateHoverForDataProviderChange(event);
        
        // The data has changed so need to do this here so the grid dimensions
        // will be accurate if setting the caret requires scrolling.
        invalidateSize();
        invalidateDisplayList();
        
        if (caretRowIndex != -1)  {
            if (event.kind == CollectionEventKind.RESET){
                // defer for reset events 
                updateCaretForDataProviderChanged = true;
                updateCaretForDataProviderChangeLastEvent = event;
                invalidateProperties();
            }
            else {
                updateCaretForDataProviderChange(event);
            }         
        }

        
        // Trigger bindings to selectedIndex/selectedCell/selectedItem and the plurals of those.
        if (selectionChanged)
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
    }
    
    /**
     *  @private
     */
    private function columns_collectionChangeHandler(event:CollectionEvent):void
    {
        var column:GridColumn;
        var columnIndex:int = event.location;
        var i:int;
        var selectionChanged:Boolean = false;
        
        switch (event.kind)
        {
            case CollectionEventKind.ADD: 
            {
                // Note: multiple columns may be added.
                while (columnIndex < columns.length)
                {
                    column = GridColumn(columns.getItemAt(columnIndex));
                    column.setGrid(this);
                    column.setColumnIndex(columnIndex);
                    columnIndex++;
                }                  
                break;
            }
                
            case CollectionEventKind.MOVE:
            {
                // All columns between the old and new locations need to 
                // have their index updated.
                columnIndex = Math.min(event.oldLocation, event.location);
                var maxIndex:int = Math.max(event.oldLocation, event.location);
                while (columnIndex <= maxIndex)
                {
                    column = GridColumn(columns.getItemAt(columnIndex));
                    column.setColumnIndex(columnIndex);
                    columnIndex++;
                }                
                break;
            }
                
            case CollectionEventKind.REPLACE:
            {
                var items:Array = event.items;                   
                var length:int = items.length;
                for (i = 0; i < length; i++)
                {
                    if (items[i].oldValue is GridColumn)
                    {
                        column = GridColumn(items[i].oldValue);
                        column.setGrid(null);
                        column.setColumnIndex(-1);
                    }
                    if (items[i].newValue is GridColumn)
                    {
                        column = GridColumn(items[i].newValue);
                        column.setGrid(this);
                        column.setColumnIndex(columnIndex);
                    }
                }
                break;
            }
                
            case CollectionEventKind.UPDATE:
            {
                break;
            }
                
            case CollectionEventKind.REFRESH:
            {
                for (columnIndex = 0; columnIndex < columns.length; columnIndex++)
                {
                    column = GridColumn(columns.getItemAt(columnIndex));
                    column.setColumnIndex(columnIndex);
                }                
                break;
            }
                
            case CollectionEventKind.REMOVE:
            {
                // Note: multiple columns may be removed.
                var count:int = event.items.length;
                
                for (i = 0; i < count; i++)
                {
                    column = GridColumn(event.items[i]);
                    column.setGrid(null);
                    column.setColumnIndex(-1);
                }
                
                // Renumber the columns which follow the removed columns.
                while (columnIndex < columns.length)
                {
                    column = GridColumn(columns.getItemAt(columnIndex));
                    column.setColumnIndex(columnIndex);
                    columnIndex++;
                }                  
                
                break;
            }
                
            case CollectionEventKind.RESET:
            {
                for (columnIndex = 0; columnIndex < columns.length; columnIndex++)
                {
                    column = GridColumn(columns.getItemAt(columnIndex));
                    column.setGrid(this);
                    column.setColumnIndex(columnIndex);
                }                     
                break;
            }                                
        }

        if (gridDimensions)
            gridDimensions.columnsCollectionChanged(event);
        
        for each (var view:GridView in allGridViews)
        {
            if (!view)
                continue;
            view.gridViewLayout.columnsCollectionChanged(event);      
        }
        
        
        if (gridSelection)
            selectionChanged = gridSelection.columnsCollectionChanged(event);
        
        if (caretColumnIndex != -1)
            updateCaretForColumnsChange(event);                
        
        if (gridDimensions && hoverColumnIndex != -1)
            updateHoverForColumnsChange(event); 

        invalidateSize();
        invalidateDisplayList(); 
        
        // Trigger bindings to selectedCell/selectedItem and the plurals of those.
        if (selectionChanged)
            dispatchFlexEvent(FlexEvent.VALUE_COMMIT);

    } 
    
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------  
    
    /**
     *  @private
     *  Clears the layout's renderers and cached sizes. Also clears
     *  the typical item's size if clearTypicalSizes is true.
     */
    mx_internal function clearGridLayoutCache(clearTypicalSizes:Boolean):void
    {
        for each (var view:GridView in allGridViews)
        {
            if (!view)
                continue;
            view.gridViewLayout.clearVirtualLayoutCache();
        }

        const gridDimensions:GridDimensions = this.gridDimensions;
        if (gridDimensions)
        {
            if (clearTypicalSizes)
			{
                gridDimensions.clearTypicalCellWidthsAndHeights();
				gridDimensions.clearColumns(0, gridDimensions.columnCount);
			}
			
            gridDimensions.clearHeights();
            
            // Reset row count because dataProvider length may have changed.
            gridDimensions.rowCount = _dataProvider ? _dataProvider.length : 0;
        }
        
        // Reset content size so scroller's viewport can be resized.  There
        // is loop-prevention logic in the scroller which may not allow the
        // width/height to be reduced if there are automatic scrollbars.
        // See ScrollerLayout/measure().
        setContentSize(0, 0);
    }
    
    /**
     *  @private
     *  Returns the index of the next GridColumn.visible==true column
     *  after index.
     *  Returns -1 if there are no more visible columns.
     *  To find the first GridColumn.visible==true column index, use
     *  getNextVisibleColumnIndex(-1).
     */
    mx_internal function getNextVisibleColumnIndex(index:int=-1):int
    {
        if (index < -1)
            return -1;
        
        const columns:IList = this.columns;
        const columnsLength:int = (columns) ? columns.length : 0;
                
        for (var i:int = index + 1; i < columnsLength; i++)
        {
            var column:GridColumn = columns.getItemAt(i) as GridColumn;
            if (column && column.visible)
                return i;
        }
        
        return -1;
    }
    
    /**
     *  @private
     *  Returns the index of the previous GridColumn.visible==true column
     *  before index.
     *  Returns -1 if there are no more visible columns.
     *  To find the last GridColumn.visible==true column index, use
     *  getPreviousVisibleColumnIndex(columns.length).
     */
    mx_internal function getPreviousVisibleColumnIndex(index:int):int
    {
        const columns:IList = this.columns;
        if (!columns || index > columns.length)
            return -1;
        
        for (var i:int = index - 1; i >= 0; i--)
        {
            var column:GridColumn = columns.getItemAt(i) as GridColumn;
            if (column && column.visible)
                return i;
        }
        
        return -1;
    }
    
    /**
     *  @private
     */
    private function initializeAnchorPosition(columnOnly:Boolean=false):void
    {
        if (!columnOnly)
            anchorRowIndex = _dataProvider && _dataProvider.length > 0 ? 0 : -1; 

        // First visible column, or -1, if there are no columns or none are visible.
        anchorColumnIndex = getNextVisibleColumnIndex(); 
    }
    
    /**
     *  @private
     */
    private function initializeCaretPosition(columnOnly:Boolean=false):void
    {
        if (!columnOnly)
            caretRowIndex = _dataProvider && _dataProvider.length > 0 ? 0 : -1;
        
        // First visible column, or -1, if there are no columns or none are visible.
        caretColumnIndex = getNextVisibleColumnIndex();
    }
    
    /**
     *  @private
     *  The caret change has already been comitted.  Dispatch the "caretChange"
     *  event.
     */
    private function dispatchCaretChangeEvent():void
    {
        if (hasEventListener(GridCaretEvent.CARET_CHANGE))
        {
            const caretChangeEvent:GridCaretEvent = 
                new GridCaretEvent(GridCaretEvent.CARET_CHANGE);
            caretChangeEvent.oldRowIndex = _oldCaretRowIndex;
            caretChangeEvent.oldColumnIndex = _oldCaretColumnIndex;
            caretChangeEvent.newRowIndex = _caretRowIndex;
            caretChangeEvent.newColumnIndex = _caretColumnIndex;
            dispatchEvent(caretChangeEvent);
        }
    }
    
    
    /**
     *  @private
     *  Renders a background for the container, if necessary.  It is used to fill in
     *  a transparent background fill as necessary to support the _mouseEnabledWhereTransparent flag.  It 
     *  is also used in ItemRenderers when handleBackgroundColor is set to true.
     *  We assume for now that we are the first layer to be rendered into the graphics
     *  context.
     * 
     *  This is mostly copied from GroupBase, but always chooses the virtualLayout path.  The Grid's
     *  layout has useVirtualLayout=false but the Grid's GridView always has useVirtualLayout=true
     *  which causes the GroupBase logic to go down the wrong path.  It also always positions at 0,0
     *  because the grid itself doesn't scroll, it scrols the layers
     */
    override mx_internal function drawBackground():void
    {
        if (!mouseEnabledWhereTransparent || !hasMouseListeners)
            return;
        
        var w:Number = (resizeMode == ResizeMode.SCALE) ? measuredWidth : unscaledWidth;
        var h:Number = (resizeMode == ResizeMode.SCALE) ? measuredHeight : unscaledHeight;
        
        if (isNaN(w) || isNaN(h))
            return;
        
        graphics.clear();
        graphics.beginFill(0xFFFFFF, 0);
        
        graphics.drawRect(0, 0, w, h);
        
        graphics.endFill();
    }

}
}