////////////////////////////////////////////////////////////////////////////////
//
//  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.DisplayObject;
    import flash.display.Graphics;
    import flash.events.Event;
    import flash.events.FocusEvent;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.ui.Keyboard;

    import mx.collections.ArrayCollection;
    import mx.collections.ComplexFieldChangeWatcher;
    import mx.collections.ICollectionView;
    import mx.collections.IComplexSortField;
    import mx.collections.IList;
    import mx.collections.ISort;
    import mx.collections.ISortField;
    import mx.collections.ListCollectionView;
    import mx.core.DragSource;
    import mx.core.EventPriority;
    import mx.core.IFactory;
    import mx.core.IFlexDisplayObject;
    import mx.core.IIMESupport;
    import mx.core.IUID;
    import mx.core.IVisualElement;
    import mx.core.InteractionMode;
    import mx.core.LayoutDirection;
    import mx.core.ScrollPolicy;
    import mx.core.UIComponent;
    import mx.core.mx_internal;
    import mx.events.DragEvent;
    import mx.events.FlexEvent;
    import mx.events.SandboxMouseEvent;
    import mx.events.TouchInteractionEvent;
    import mx.managers.CursorManager;
    import mx.managers.CursorManagerPriority;
    import mx.managers.DragManager;
    import mx.managers.IFocusManagerComponent;
    import mx.styles.IAdvancedStyleClient;
    import mx.utils.ObjectUtil;
    import mx.utils.UIDUtil;

    import spark.collections.Sort;
    import spark.components.gridClasses.CellPosition;
    import spark.components.gridClasses.CellRegion;
    import spark.components.gridClasses.DataGridEditor;
    import spark.components.gridClasses.GridColumn;
    import spark.components.gridClasses.GridItemEditorActivationMouseEvent;
    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.IGridItemEditor;
    import spark.components.supportClasses.IDataProviderEnhance;
    import spark.components.supportClasses.RegExPatterns;
    import spark.components.supportClasses.SkinnableContainerBase;
    import spark.core.NavigationUnit;
    import spark.events.GridCaretEvent;
    import spark.events.GridEvent;
    import spark.events.GridSelectionEvent;
    import spark.events.GridSelectionEventKind;
    import spark.events.GridSortEvent;
    import spark.layouts.supportClasses.DropLocation;

    use namespace mx_internal;

//--------------------------------------
//  Styles
//--------------------------------------

/**
 *  Used to initialize the DataGrid's <code>rowBackground</code> skin part.   
 *  If the <code>alternatingRowColors</code> style is specified, 
 *  then use the <code>alternatingRowColorsBackground</code> skin part 
 *  as the value of the <code>rowBackground</code> skin part.  
 *  The alternating colors for the grid rows are defined by 
 *  successive entries in the Array value of this style.
 *
 *  <p>If you want to change how this style is rendered, 
 *  replace the <code>alternatingRowColorsBackground</code> skin part
 *  in the DataGridSkin class.   
 *  If you want to specify the background for each row, then 
 *  initialize the <code>rowBackground</code> skin part directly.</p>
 * 
 *  @default undefined
 *
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="alternatingRowColors", type="Array", arrayType="uint", format="Color", inherit="no", theme="spark")]

/**
 *  The alpha value of the border for this component.
 *  Valid values are 0.0 to 1.0. 
 *
 *  @default 1.0
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="borderAlpha", type="Number", inherit="no", theme="spark", minValue="0.0", maxValue="1.0")]

/**
 *  The color of the border for this component.
 *
 *  @default #696969
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="borderColor", type="uint", format="Color", inherit="no", theme="spark")]

/**
 *  Controls the visibility of the border for this component.
 *
 *  @default true
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="borderVisible", type="Boolean", inherit="no", theme="spark")]

/**
 *  Color of the caret indicator when navigating the Grid.
 *
 *  @default 0x0167FF
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.0
 *  @productversion Flex 4.5
 */
[Style(name="caretColor", type="uint", format="Color", inherit="yes", theme="spark")]

/**
 *  The alpha of the content background for this component.
 *  Valid values are 0.0 to 1.0. 
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="contentBackgroundAlpha", type="Number", inherit="yes", theme="spark", minValue="0.0", maxValue="1.0")]

/**
 *  @copy spark.components.supportClasses.GroupBase#style:contentBackgroundColor
 *   
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="contentBackgroundColor", type="uint", format="Color", inherit="yes", theme="spark")]

/**
 *  @copy spark.components.supportClasses.GroupBase#style:rollOverColor
 *   
 *  @default 0xCEDBEF
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.0
 *  @productversion Flex 4.5
 */
[Style(name="rollOverColor", type="uint", format="Color", inherit="yes", theme="spark")]

/**
 *  @copy spark.components.List#style:selectionColor
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.0
 *  @productversion Flex 4.5
 */
[Style(name="selectionColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]

/**
 *  The class to use as the skin for the cursor that indicates that a column
 *  can be resized.
 *  The default value is the <code>cursorStretch</code> symbol from the Assets.swf file.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="stretchCursor", type="Class", inherit="no")]

/**
 *  @copy spark.components.supportClasses.GroupBase#style:symbolColor
 *   
 *  @default 0x000000
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.0
 *  @productversion Flex 4.5
 */ 
[Style(name="symbolColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]

include "../styles/metadata/BasicInheritingTextStyles.as"

/**
 *  The class to use as the item editor, if one is not
 *  specified by a column.  
 *  This style property lets you set
 *  an item editor for a group of DataGrid controls instead of having to
 *  set each one individually.  
 *  The <code>DataGridColumn.itemEditor</code> property supercedes this value.
 *  
 *  @default null
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="defaultDataGridItemEditor", type="Class", inherit="no")]

/**
 *  Indicates the conditions for which the horizontal scroll bar is displayed.
 * 
 *  <ul>
 *  <li>
 *  <code>ScrollPolicy.ON</code> ("on") - The scroll bar is always displayed.
 *  </li> 
 *  <li>
 *  <code>ScrollPolicy.OFF</code> ("off") - The scroll bar is never displayed.
 *  The viewport can still be scrolled programmatically, by setting its
 *  <code>horizontalScrollPosition</code> property.
 *  </li>
 *  <li>
 *  <code>ScrollPolicy.AUTO</code> ("auto") - The scroll bar is displayed when 
 *  the viewport's <code>contentWidth</code> is larger than its width.
 *  </li>
 *  </ul>
 * 
 *  <p>
 *  The scroll policy affects the measured size of the scroller skin part.  
 *  This style is a reference to the scroller skin part's 
 *  <code>horizontalScrollPolicy</code> style.  
 *  It is not an inheriting style 
 *  Therefor, for example, it will not affect item renderers. </p>
 * 
 *  @default ScrollPolicy.AUTO
 *
 *  @see mx.core.ScrollPolicy
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */ 
[Style(name="horizontalScrollPolicy", type="String", inherit="no", enumeration="off,on,auto")]

/**
 *  Indicates under what conditions the vertical scroll bar is displayed.
 * 
 *  <ul>
 *  <li>
 *  <code>ScrollPolicy.ON</code> ("on") - The scroll bar is always displayed.
 *  </li> 
 *  <li>
 *  <code>ScrollPolicy.OFF</code> ("off") - The scroll bar is never displayed.
 *  The viewport can still be scrolled programmatically, by setting its
 *  <code>verticalScrollPosition</code> property.
 *  </li>
 *  <li>
 *  <code>ScrollPolicy.AUTO</code> ("auto") - The scroll bar is displayed when 
 *  the viewport's <code>contentHeight</code> is larger than its height.
 *  </li>
 *  </ul>
 * 
 *  <p>
 *  The scroll policy affects the measured size of the scroller skin part.  
 *  This style is a reference to the scroller skin part's 
 *  <code>verticalScrollPolicy</code> style.  
 *  It is not an inheriting style 
 *  Therefor, for example, it will not affect item renderers. </p>
 * 
 *  @default ScrollPolicy.AUTO
 *
 *  @see mx.core.ScrollPolicy
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */ 
[Style(name="verticalScrollPolicy", type="String", inherit="no", enumeration="off,on,auto")]

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

/**
 *  Dispatched by the <code>grid</code> skin part when the caret position, size, or
 *  visibility has changed due to user interaction or being programmatically set.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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")]

/**
 *  Dispatched by the <code>grid</code> skin part when the mouse button 
 *  is pressed over a grid cell.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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 by the <code>grid</code> skin part after a <code>gridMouseDown</code> event 
 *  if the mouse moves before the button is released.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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 by the <code>grid</code> skin part after a <code>gridMouseDown</code> event 
 *  when the mouse button is released, even if the mouse is no longer within the grid.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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 by the <code>grid</code> skin part when the mouse enters a grid cell.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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 by the <code>grid</code> skin part when the mouse leaves a grid cell.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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 by the <code>grid</code> skin part when the mouse is clicked over a cell.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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 by the <code>grid</code> skin part when the mouse is double-clicked over a cell.
 *
 *  <p>To handle this event, assign an event handler to the <code>grid</code> skin part 
 *  of the DataGrid control.</p>
 *
 *  @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 when the selection is going to change.
 *  Calling the <code>preventDefault()</code> method
 *  on the event prevents the selection from changing.
 *  
 *  <p>This event is dispatched when the user interacts with the control.
 *  When you change the selection programmatically, 
 *  the component does not dispatch the <code>selectionChanging</code> event. </p>
 *
 *  @eventType spark.events.GridSelectionEvent.SELECTION_CHANGING
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="selectionChanging", type="spark.events.GridSelectionEvent")]

/**
 *  Dispatched when the selection has changed. 
 *  
 *  <p>This event is dispatched when the user interacts with the control.
 *  When you change the selection programmatically, 
 *  the component does not dispatch the <code>selectionChange</code> event. 
 *  In either case it dispatches the <code>valueCommit</code> event as well.</p>
 *
 *  @eventType spark.events.GridSelectionEvent.SELECTION_CHANGE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="selectionChange", type="spark.events.GridSelectionEvent")]

/**
 *  Dispatched before the sort has been applied to the data provider's collection.
 *  Typically this is when the user releases the mouse button on a column header
 *  to request the control to sort the grid contents based on the contents of the column.
 *  Only dispatched if the column is sortable and the data provider supports sorting.
 *  
 *  <p>The DataGrid control has a default handler for this event that implements
 *  a single-column sort and updates the <code>visibleSortIndices</code> in the grid's
 *  <code>columnHeaderGroup</code> with the <code>columnIndices</code>.</p>
 * 
 *  <p>Multiple-column sort can be implemented by calling the <code>preventDefault()</code> method 
 *  to prevent the single column sort and setting the <code>columnIndices</code> and 
 *  <code>newSortFields</code> parameters of the event to change the default behavior.
 *  <code>newSortFields</code> should be set to the desired sort fields.
 *  <code>columnIndices</code> should be set to the indices of the columns that should
 *  have a visible sort indicator in the column header bar.</p>
 *   
 *  <p>This event is dispatched when the user interacts with the control.
 *  When you sort the data provider's collection programmatically, 
 *  the component does not dispatch the <code>sortChanging</code> event. </p>
 *
 *  @eventType spark.events.GridSortEvent.SORT_CHANGING
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="sortChanging", type="spark.events.GridSortEvent")]

/**
 *  Dispatched after the sort has been applied to the data provider's collection. 
 *  Typically this is after the user releases the mouse button on a column header and 
 *  the sort has been applied to the data provider's collection. 
 *  
 *  <p>This event is dispatched when the user interacts with the control.
 *  When you sort the data provider's collection programmatically, 
 *  the component does not dispatch the <code>sortChanging</code> event.</p>
 *
 *  @eventType spark.events.GridSortEvent.SORT_CHANGE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="sortChange", type="spark.events.GridSortEvent")]

//--------------------------------------
//  Edit Events
//--------------------------------------

/**
 *  Dispatched when a new item editor session has been requested. A listener can
 *  dynamically determine if a cell is editable and cancel the edit (by calling
 *  the <code>preventDefault()</code> method) if it is not. 
 *  A listener may also dynamically change the editor used by assigning a 
 *  different item editor to a column.
 * 
 *  <p>If this event is canceled the item editor will not be created.</p>
 *
 *  @eventType spark.events.GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_STARTING
 *  
 *  @see spark.components.DataGrid.itemEditorInstance
 *  @see flash.events.Event
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridItemEditorSessionStarting", type="spark.events.GridItemEditorEvent")]

/**
 *  Dispatched immediately after an item editor has been opened. 
 *
 *  @eventType spark.events.GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_START
 *  
 *  @see spark.components.DataGrid.itemEditorInstance
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridItemEditorSessionStart", type="spark.events.GridItemEditorEvent")]

/**
 *  Dispatched after the data in item editor has been saved into the data provider
 *  and the editor has been closed.  
 *
 *  @eventType spark.events.GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE
 *  
 *  @see spark.components.DataGrid.itemEditorInstance
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridItemEditorSessionSave", type="spark.events.GridItemEditorEvent")]

/**
 *  Dispatched after the item editor has been closed without saving its data.  
 *
 *  @eventType spark.events.GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_CANCEL
 *  
 *  @see spark.components.DataGrid.itemEditorInstance
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Event(name="gridItemEditorSessionCancel", type="spark.events.GridItemEditorEvent")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[AccessibilityClass(implementation="spark.accessibility.DataGridAccImpl")]

[DefaultProperty("dataProvider")]

[DefaultTriggerEvent("selectionChange")]

[DiscouragedForProfile("mobileDevice")]

[IconFile("DataGrid.png")]

/**
 *  The DataGrid displays a row of column headings above a scrollable grid. 
 *  The grid is arranged as a collection of individual cells arranged 
 *  in rows and columns. 
 *  The DataGrid control is designed to support smooth scrolling through 
 *  large numbers of rows and columns.
 *
 *  <p>The Spark DataGrid control is implemented as a skinnable wrapper 
 *  around the Spark Grid control. 
 *  The Grid control defines the columns of the data grid, and much of 
 *  the functionality of the DataGrid control itself.</p>
 *
 *  <p>The DataGrid skin is responsible for laying out the grid, column header, and scroller. 
 *  The skin also configures the graphic elements used to render visual elements 
 *  used as indicators, separators, and backgrounds. 
 *  The DataGrid skin also defines a default item renderer, 
 *  used to display the contents of each cell.  
 *  Please see the documentation for the renderer class for the list of supported styles.</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:DataGrid&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:DataGrid 
 *    <strong>Properties</strong>
 *    columns="null"
 *    dataProvider="null"  
 *    dataTipField="null"  
 *    dataTipFunction="null"
 *    doubleClickMode="row"
 *    editable="false"
 *    editorColumnIndex="-1"
 *    editorRowIndex="-1"
 *    imeMode="null"
 *    itemEditor="null"
 *    itemRenderer="<i>DefaultGridItemRenderer</i>" 
 *    preserveSelection="true"
 *    requestedColumnCount="-1"
 *    requestedMaxRowCount="-1"
 *    requestedMinColumnCount="-1"
 *    requestedMinRowCount="-1"
 *    requestedRowCount="-1"
 *    requireSelection="false"
 *    resizeableColumns="true"
 *    rowHeight="<i>Calculated default</i>"
 *    selectedCell="null"
 *    selectedCells="<i>empty Vector.&lt;CellPosition&gt</i>"
 *    selectedIndex="null"
 *    selectedIndices="<i>empty Vector.&lt;CellPosition&gt</i>"
 *    selectedItem="null"
 *    selectedItems="<i>empty Vector.&lt;Object&gt</i>"
 *    selectionMode="singleRow"
 *    showDataTips="false"
 *    sortableColumns="true"
 *    typicalItem="null"
 *    variableRowHeight="false" 
 * 
 *    <strong>Styles</strong>
 *    alignmentBaseline="useDominantBaseline"
 *    baselineShift="0.0"
 *    cffHinting="horizontalStem"
 *    color="0"
 *    defaultGridItemEditor="null"
 *    digitCase="default"
 *    digitWidth="default"
 *    direction="ltr"
 *    dominantBaseline="auto"
 *    fontFamily="Arial"
 *    fontLookup="device"
 *    fontSize="12"
 *    fontStyle="normal"
 *    fontWeight="normal"
 *    justificationRule="auto"
 *    justificationStyle="auto"
 *    kerning="auto"
 *    ligatureLevel="common"
 *    lineHeight="120%"
 *    lineThrough="false"
 *    locale="en"
 *    renderingMode="cff"
 *    stretchCursor="<i>cursorStretch symbol from Assets.swf</i>"
 *    textAlign="start"
 *    textAlignLast="start"
 *    textAlpha="1"
 *    textDecoration="none"
 *    textJustify="interWord"
 *    trackingLeft="0"
 *    trackingRight="0"
 *    typographicCase="default"
 *    verticalScrollPolicy="auto"
 *
 *    <strong>Styles for the Spark Theme</strong>
 *    alternatingRowColors="undefined"
 *    borderAlpha="1.0"
 *    borderColor="0x696969"
 *    borderVisible="true"
 *    caretColor="0x0167FF"
 *    contentBackgroundAlpha="1.0"
 *    contentBackgroundColor="0xFFFFFF"
 *    rollOverColor="0xCEDBEF"
 *    selectionColor="0xA8C6EE"
 *    symbolColor="0x000000"
 * 
 *    <strong>Styles for the Mobile Theme</strong>
 *    leading="0"
 *    letterSpacing="0"
 *    selectionColor="0xE0E0E0"
 *    symbolColor="0x000000"
 * 
 *    <strong>Events</strong>
 *    caretChange="<i>No default</i>"
 *    gridClick="<i>No default</i>"
 *    gridDoubleClick="<i>No default</i>"
 *    gridItemEditorSessionCancel="<i>No default</i>"
 *    gridItemEditorSessionSave="<i>No default</i>"
 *    gridItemEditorSessionStart="<i>No default</i>"
 *    gridItemEditorSessionStarting="<i>No default</i>"
 *    gridMouseDown="<i>No default</i>"
 *    gridMouseDrag="<i>No default</i>"
 *    gridMouseUp="<i>No default</i>"
 *    gridMouseRollOut="<i>No default</i>"
 *    gridMouseRollOver="<i>No default</i>"
 *    selectionChange="<i>No default</i>"
 *    selectionChanging="<i>No default</i>"
 *    sortChange="<i>No default</i>"
 *    sortChanging="<i>No default</i>" 
 *  /&gt;
 *  </pre>
 *
 *  @see spark.components.Grid
 *  @see spark.components.gridClasses.GridColumn
 *  @see spark.skins.spark.DataGridSkin
 *  @see spark.skins.spark.DefaultGridItemRenderer
 *  
 *  @includeExample examples/DataGridSimpleExample.mxml
 *  @includeExample examples/DataGridMasterDetailExample.mxml
 *  @includeExample examples/DataGridTypicalItemExample.mxml
 *  @includeExample examples/DataGridRowHeightExample.mxml
 *  @includeExample examples/DataGridSelectionExample.mxml
 *  @includeExample examples/DataGridInvalidateCellExample.mxml
 *  @includeExample examples/DataGridLockedRowsAndColumnsExample.mxml
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */  
public class DataGrid extends SkinnableContainerBase 
    implements IDataProviderEnhance, IFocusManagerComponent, IIMESupport
{
    include "../core/Version.as";
    
    //--------------------------------------------------------------------------
    //
    //  Class mixins
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  Placeholder for mixin by DataGridAccImpl.
     */
    mx_internal static var createAccessibilityImplementation:Function;
    
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Constructor. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function DataGrid()
    {
        super();
        
        addEventListener(Event.SELECT_ALL, selectAllHandler);
        addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, EventPriority.DEFAULT_HANDLER);        
    }
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  True, when the hover indicator should be updated on a ROLL_OVER event.
     *  If the mouse button is depressed while outside of the grid, the hover 
     *  indicator is not enabled again until MOUSE_UP or ROLL_OUT. 
     */
    private var updateHoverOnRollOver:Boolean = true;
    
    //--------------------------------------------------------------------------
    //
    //  Drag and Drop Variables
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  The point where the mouse down event was received.
     *  Used to track whether a drag operation should be initiated when the user
     *  drags further than a certain threshold. 
     */
    private var mouseDownPoint:Point;
    
    /**
     *  @private
     *  The index of the element the mouse down event was received for. Used to
     *  track which is the "focus item" for a drag and drop operation.
     */
    private var mouseDownRowIndex:int = -1;
    
    /**
     *  @private
     *  The index of the element the mouse down event was received for. Used to
     *  track which is the "focus item" for a drag and drop operation.
     */
    private var mouseDownColumnIndex:int = -1;
    
    /**
     *  @private
     *  The displayObject where the mouse down event was received.
     *  In touch interactionMode, used to track whether this item is 
     *  the one that is moused up on so we can possibly select it. 
     */
    private var mouseDownObject:DisplayObject;
    
    /**
     *  @private
     *  When dragging is enabled with multiple selection, the selection is not
     *  comitted immediately on mouse down, but we wait to see whether the user
     *  intended to start a drag gesture instead. In that case we postpone
     *  comitting the selection until mouse up.
     */
    private var pendingSelectionOnMouseUp:Boolean = false;

    
    //--------------------------------------------------------------------------
    //
    //  Skin Parts
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private 
     *  IFactory valued skin parts that require special handling, see findSkinParts().
     */
    private static const factorySkinPartNames:Array = [
        "alternatingRowColorsBackground",
        "caretIndicator",
        "columnSeparator",
        "headerColumnSeparator",        
        "hoverIndicator",
        "lockedRowsSeparator",
        "lockedColumnsSeparator",
        "rowBackground",
        "rowSeparator",
        "selectionIndicator"];
    
    //----------------------------------
    //  alternatingRowColorsBackground
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render the <code>alternatingRowColors</code> style.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var alternatingRowColorsBackground:IFactory;
    
    //----------------------------------
    //  caretIndicator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render the grid's caret indicator.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var caretIndicator:IFactory;
    
    //----------------------------------
    //  columnHeaderGroup
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false")]
    
    /**
     *  A reference to the GridColumnHeaderGroup object that displays the column headers.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var columnHeaderGroup:GridColumnHeaderGroup;    
    
    //----------------------------------
    //  columnSeparator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render the vertical separator between columns. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var columnSeparator:IFactory;
    
    //----------------------------------
    //  dropIndicator
    //----------------------------------
    
    [SkinPart(required="false", type="flash.display.DisplayObject")]
    
    /**
     *  The IVisualElement class that defines the appearance of the drop indicator. 
     *  The drop indicator is resized and positioned by the layout to indicate 
     *  in between which grid rows the drop will insert the drag source item.
     * 
     *  <p>This is a dynamic skin part: it's created as needed and then destroyed.</p>
     * 
     *  <p>The DataGrid will set the dropIndicator's height to its 
     *  preferred height bracketed by its minHeight and maxHeight values.
     *  Its width will be unconditionally set to the grid's visible width.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */    
    public var dropIndicator:IFactory; 
    
    //----------------------------------
    //  editorIndicator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render a background behind
     *  item renderers that are being edited. 
     *  Item renderers may only be edited
     *  when the data grid and the column are both editable and the
     *  column sets <code>rendererIsEditable</code> to <code>true</code>.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var editorIndicator:IFactory;
    
    //----------------------------------
    //  grid
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false")]
    
    /**
     *  A reference to the Grid control that displays row and columns.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var grid:Grid;
    
    //----------------------------------
    //  hoverIndicator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to provide hover feedback.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var hoverIndicator:IFactory;
    
    //----------------------------------
    //  lockedColumnsSeparator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render the vertical separator between locked and unlocked columns.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public var lockedColumnsSeparator:IFactory; 
    
    //----------------------------------
    //  lockedRowsSeparator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render the horizontal separator between locked and unlocked rows.
     */
    public var lockedRowsSeparator:IFactory;    
    
    //----------------------------------
    //  rowBackground
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render the background of each row.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var rowBackground:IFactory;        
    
    //----------------------------------
    //  rowSeparator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render the horizontal separator between header rows. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var rowSeparator:IFactory;
    
    //----------------------------------
    //  scroller
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false")]
    
    /**
     *  A reference to the Scroller control in the skin class 
     *  that adds scroll bars to the DataGrid control.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var scroller:Scroller;    
    
    //----------------------------------
    //  selectionIndicator
    //----------------------------------
    
    [Bindable]
    [SkinPart(required="false", type="mx.core.IVisualElement")]
    
    /**
     *  The IVisualElement class used to render selected rows or cells.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var selectionIndicator:IFactory;
    
    /**
     *  @private
     *  If the alternatingRowColors style is set AND the alternatingRowColorsBackground
     *  skin part has been added AND the grid skin part has been added, then set
     *  grid.rowBackground = alternatingRowColorsBackground here.   Otherwise just
     *  set it to the value of the rowBackground skin part (property).
     */
    private function initializeGridRowBackground():void
    {
        if (!grid)
            return;
        
        if ((getStyle("alternatingRowColors") as Array) && alternatingRowColorsBackground)
            grid.rowBackground = alternatingRowColorsBackground;
        else
            grid.rowBackground = rowBackground;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Skin Part Property Internals
    //
    //-------------------------------------------------------------------------- 
    
    /**
     *  @private
     *  A list of functions to be applied to the grid skin part at partAdded() time.
     *  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 deferredGridOperations:Vector.<Function> = new Vector.<Function>();
    
    /**
     *  @private
     *  Defines one bit for each skin part property that's covered by DataGrid.  Currently
     *  there are only grid properties.
     */
    private static const partPropertyBits:Object = {
        columns: uint(1 << 0),
        dataProvider: uint(1 << 1),
        itemRenderer: uint(1 << 2),
        requestedRowCount: uint(1 << 3),
        requestedColumnCount: uint(1 << 4),
        requestedMaxRowCount: uint(1 << 5),
        requestedMinRowCount: uint(1 << 6),
        requestedMinColumnCount: uint(1 << 7),
        rowHeight: uint(1 << 8),
        showDataTips: uint(1 << 9),
        typicalItem: uint(1 << 10),
        variableRowHeight: uint(1 << 11),
        dataTipField: uint(1 << 12),
        dataTipFunction: uint(1 << 13),
        resizableColumns: uint(1 << 14),
        lockedColumnCount: uint(1 << 15),
        lockedRowCount: uint(1 << 16)
    };
    
    /**
     *  @private
     *  If the grid skin part hasn't been added, this var is an object whose properties
     *  temporarily record the values of DataGrid properties that just "cover" grid skin
     *  part properties. 
     * 
     *  If the grid skin part has been added (is non-null), then this var has 
     *  a single is a uint bitmask property called propertyBits that's used
     *  used to track which grid properties have been explicitly set.
     *  
     *  See getPartProperty(), setPartProperty().
     */
    private var gridProperties:Object = {};
    
    /**
     *  @private
     *  The default values of the grid skin part properties covered by DataGrid.
     */
    private static const gridPropertyDefaults:Object = {
        columns: null,
        dataProvider: null,
        itemRenderer: null,
        resizableColumns: true,
        requestedRowCount: int(-1),
        requestedMaxRowCount: int(10),        
        requestedMinRowCount: int(-1),
        requestedColumnCount: int(-1),
        requestedMinColumnCount: int(-1),
        rowHeight: NaN,
        showDataTips: false,
        typicalItem: null,
        variableRowHeight: false,
        dataTipField: null,
        dataTipFunction: null,
        lockedColumnCount: int(0),
        lockedRowCount: int(0)
    };
    
    /** 
     *  @private
     *  A utility method for looking up a skin part property that accounts for the possibility that
     *  the skin part is null.  It's intended to be used in the definition of properties that just
     *  "cover" skin part properties.
     * 
     *  If part is non-null, then return part[propertyName].  Otherwise return the value
     *  of properties[propertyName], or defaults[propertyName] if the specified property's 
     *  value is undefined.
     */
    private static function getPartProperty(part:Object, properties:Object, propertyName:String, defaults:Object):*
    {
        if (part)
            return part[propertyName];
        
        const value:* = properties[propertyName];
        return (value === undefined) ? defaults[propertyName] : value;
    }
    
    /** 
     *  @private
     *  A utility method for setting a skin part property that accounts for the possibility that
     *  the skin part is null.  It's intended to be used in the definition of properties that just
     *  "cover" skin part properties.
     * 
     *  Return true if the property's value was changed.
     * 
     *  If part is non-null, then set part[propertyName], otherwise set properties[propertyName].  
     * 
     *  If part is non-null then we set the bit for this property on the properties.propertyBits, to record
     *  the fact that the DataGrid cover property was explicitly set.
     * 
     *  In either case we treat setting a property to its default value specially: the effect
     *  is as if the property was never set at all.
     */
    private static function setPartProperty(part:Object, properties:Object, propertyName:String, value:*, defaults:Object):Boolean
    {
        if (getPartProperty(part, properties, propertyName, defaults) === value)
            return false;
        
        const defaultValue:* = defaults[propertyName];
        
        if (part)
        {
            part[propertyName] = value;
            if (value === defaultValue)
                properties.propertyBits &= ~partPropertyBits[propertyName];
            else
                properties.propertyBits |= partPropertyBits[propertyName];
        }
        else
        {
            if (value === defaultValue)
                delete properties[propertyName];
            else
                properties[propertyName] = value;
        }
        
        return true;
    }
    
    /**
     *  @private
     *  Return the specified grid property.
     */
    private function getGridProperty(propertyName:String):*
    {
        return getPartProperty(grid, gridProperties, propertyName, gridPropertyDefaults);
    }
    
    /**
     *  @private
     *  Set the specified grid property and return true if the property actually changed.
     */
    private function setGridProperty(propertyName:String, value:*):Boolean
    {
        return setPartProperty(grid, gridProperties, propertyName, value, gridPropertyDefaults);
    }    
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------
    
    /** 
     *  @private
     *  Maximum time in milliseconds between a click and a double click.
     */ 
    mx_internal var doubleClickTime:Number = 620;
    
    /** 
     *  @private
     *  Key used to start editting a cell.
     */ 
    mx_internal var editKey:uint = Keyboard.F2;
    
    /** 
     *  @private
     *  A cell editor is initiated by a single click on a selected cell. 
     *  If this variable is true then also open an editor when a cell is 
     *  double clicked, otherwise cancel the edit.
     */ 
    mx_internal var editOnDoubleClick:Boolean = false;
    
    /** 
     *  @private
     *  Provides all the logic to start and end item
     *  editor sessions.
     *
     *  Create your own editor by overriding the <code>createEditor()</code> 
     *  method. 
     */ 
    mx_internal var editor:DataGridEditor;
    
    //--------------------------------------------------------------------------
    //
    //  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));
    }
    
    //----------------------------------
    //  columns (delegates to grid.columns)
    //----------------------------------
    
    [Bindable("columnsChanged")]
    [Inspectable(category="General")]
    
    /**
     *  @copy spark.components.Grid#columns
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get columns():IList
    {
        return getGridProperty("columns");
    }
    
    /**
     *  @private
     */
    public function set columns(value:IList):void
    {
        if (setGridProperty("columns", value))
        {
            if (columnHeaderGroup)
            {
                columnHeaderGroup.layout.clearVirtualLayoutCache();
                columnHeaderGroup.invalidateSize();
                columnHeaderGroup.invalidateDisplayList();
            }
            
            dispatchChangeEvent("columnsChanged");
        }
    }
    
    /**
     *  @private
     */
    private function getColumnAt(columnIndex:int):GridColumn
    {
        const grid:Grid = grid;
        if (!grid || !grid.columns)
            return null;
        
        const columns:IList = grid.columns;
        return ((columnIndex >= 0) && (columnIndex < columns.length)) ? columns.getItemAt(columnIndex) as GridColumn : null;
    }
    
    //----------------------------------
    //  columnsLength
    //---------------------------------- 
    
    /**
     *  Returns the value of <code>columns.length</code> if the columns IList
     *  was specified, otherwise 0.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5*
     */
    public function get columnsLength():int
    {
        const columns:IList = columns;
        return (columns) ? columns.length : 0;
    }    
    
    //----------------------------------
    //  dataProvider (delegates to grid.dataProvider)
    //----------------------------------
    
    [Bindable("dataProviderChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.Grid#dataProvider
     * 
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get dataProvider():IList
    {
        return getGridProperty("dataProvider");
    }
    
    /**
     *  @private
     */
    public function set dataProvider(value:IList):void
    {
        if (setGridProperty("dataProvider", value))
            dispatchChangeEvent("dataProviderChanged");
    }
    
    //----------------------------------
    //  dataProviderLength
    //---------------------------------- 
    
    /**
     *  Returns the value of <code>dataProvider.length</code> if the dataProvider IList
     *  was specified, otherwise 0.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get dataProviderLength():int
    {
        const dataProvider:IList = dataProvider;
        return (dataProvider) ? dataProvider.length : 0;
    }       
    
    //----------------------------------
    //  dataTipField (delegates to grid.dataTipField)
    //----------------------------------    
    
    [Bindable("dataTipFieldChanged")]
    [Inspectable(category="Data", defaultValue="null")]
    
    /**
     *  @copy spark.components.Grid#dataTipField
     *
     *  @default null
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get dataTipField():String
    {
        return getGridProperty("dataTipField");
    }
    
    /**
     *  @private
     */
    public function set dataTipField(value:String):void
    {
        if (setGridProperty("dataTipField", value))
            dispatchChangeEvent("dataTipFieldChanged");
    } 
    
    //----------------------------------
    //  dataTipFunction (delegates to grid.dataTipFunction)
    //----------------------------------    
    
    [Bindable("dataTipFunctionChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.Grid#dataTipFunction
     *
     *  @default null
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get dataTipFunction():Function
    {
        return getGridProperty("dataTipFunction");
    }
    
    /**
     *  @private
     */
    public function set dataTipFunction(value:Function):void
    {
        if (setGridProperty("dataTipFunction", value))
            dispatchChangeEvent("dataTipFunctionChanged");
    }


    //----------------------------------
    //  doubleClickMode
    //----------------------------------

    [Bindable("doubleClickModeChanged")]
    [Inspectable(category="General", enumeration="cell,grid,row", defaultValue="row")]

    /**
    *  @copy spark.components.Grid#doubleClickMode
    *
    *  @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 grid.doubleClickMode;
    }

    /**
    *  @private
    */
    public function set doubleClickMode(newValue:String):void
    {
        if (setGridProperty("doubleClickMode", newValue))
        {
            dispatchChangeEvent("doubleClickModeChanged");
        }
    }


    //----------------------------------
    //  draggableColumns
    //----------------------------------
    
    private var _draggableColumns:Boolean = false;
    
    [Inspectable(category="General", defaultValue="false")]
    [Bindable("draggableColumnsChanged")]    
    
    /**
     * 
     *  @langversion 3.0
     *  @playerversion Flash 1
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public function get draggableColumns():Boolean
    {
        return _draggableColumns;
    }
    
    /**
     *  @private
     */
    public function set draggableColumns(value:Boolean):void
    {
        if (value == _draggableColumns)
            return;
        
        _draggableColumns = value;
        dispatchChangeEvent("draggableColumnsChanged");        
    }
    
    //----------------------------------
    //  editable
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the editable property.
     */
    private var _editable:Boolean = false;
    
    [Inspectable(category="General", defaultValue="false")]
    
    /**
     *  A flag which enables editing the data items in the DataGrid.
     *  If <code>true</code> and <code>selectionMode</code> is not equal to "none", clicking on 
     *  a cell opens an item editor.
     *  
     *  <p>You can disable editing for individual columns of the DataGrid control using the
     *  GridColumn <code>editable</code> property.
     *  By default, all visible columns are editable.</p>
     * 
     *  <p>You can enable or disable editing per cell (rather than per column) 
     *  by handling the <code>startItemEditorSession</code> event.
     *  In the event handler, add the necessary logic to determine 
     *  if the cell should be editable.</p>  
     * 
     *  @default false
     *  
     *  @see #selectionMode
     *  @see spark.components.gridClasses.GridColumn#editable
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get editable():Boolean
    {
        return _editable;
    }
    
    /**
     *  @private
     */
    public function set editable(value:Boolean):void
    {
        _editable = value;
    }
    
    //----------------------------------
    //  editorActivationMouseEvent
    //----------------------------------
    
    private var _editorActivationMouseEvent:String = GridItemEditorActivationMouseEvent.SINGLE_CLICK_ON_SELECTED_CELL;
    
    [Bindable("editorActivationMouseEventChanged")]
    [Inspectable(category="General", enumeration="doubleClick,none,singleClick,singleClickOnSelectedCell", defaultValue="singleClickOnSelectedCell")]
    
    /**
     *  The type of mouse event that starts an editor session. Must be one of
     *  values in <code>GridItemEditorMouseEvent</code>. This value 
     *  provides a default value for each column of a DataGrid. A different
     *  value can be specified on a grid column to override the default.
     *       
     *  @default "singleClickOnSelectedCell"
     * 
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function get editorActivationMouseEvent():String
    {
        return _editorActivationMouseEvent;
    }
    
    /**
     *  @private
     */
    public function set editorActivationMouseEvent(value:String):void
    {
        if (_editorActivationMouseEvent == value)
            return;
        
        _editorActivationMouseEvent = value;
        dispatchChangeEvent("editorActivationMouseEventChanged");
    }
    
    //----------------------------------
    //  editorColumnIndex
    //----------------------------------
    
    /**
     *  The zero-based column index of the cell that is being edited.  
     *  The value is -1 if no cell is being edited.
     * 
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get editorColumnIndex():int
    {
        if (editor)
            return editor.editorColumnIndex;
        
        return -1;
    }
    
    //----------------------------------
    //  editorRowIndex
    //----------------------------------
    
    /**
     *  The zero-based row index of the cell that is being edited.  
     *  The value is -1 if no cell is being edited.
     * 
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get editorRowIndex():int
    {
        if (editor)
            return editor.editorRowIndex;
        
        return -1;
    }
    
    //----------------------------------
    //  enableIME
    //----------------------------------
    
    /**
     *  A flag that indicates whether the IME should
     *  be enabled when the component receives focus.
     *
     *  If the item editor is open, it sets this property 
     *  accordingly.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get enableIME():Boolean
    {
        return false;
    }


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

    /**
    *  @copy spark.components.Grid#isFirstRow
    *  If a <code>grid</code> is not assigned, will always return false;
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function get isFirstRow():Boolean
    {
        if (grid)
        {
            return grid.isFirstRow;
        }
        else
        {
            return false;
        }
    }


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

    /**
    *  @copy spark.components.Grid#isLastRow
    *  If a <code>grid</code> is not assigned, will always return false;
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function get isLastRow():Boolean
    {
        if (grid)
        {
            return grid.isLastRow;
        }
        else
        {
            return false;
        }
    }


    //----------------------------------
    //  multiColumnSortingEnabled
    //----------------------------------
    
    private var _multiColumnSortingEnabled:Boolean = false;
    
    [Bindable("multiColumnSortingEnabledChanged")]
    [Inspectable(category="General", defaultValue="false")]
    
    /**
     *  If this property is true and sorting has been enabled, then users can interactively 
     *  specify multi-column sorts by control-clicking in column headers (Command+Click on OSX).  
     *  Sorting is enabled for a column if the DataGrid <code>sortable</code> property is true
     *  and the column's <code>sortable</code> property is true.   Sorting is enabled for
     *  all columns by default, multi-column sorting is not.
     * 
     *  @default false
     * 
     *  @see #sortableColumns
     *  @see spark.components.gridClasses.GridColumn#sortable

     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get multiColumnSortingEnabled():Boolean
    {
        return _multiColumnSortingEnabled;
    }
    
    /**
     *  @private
     */    
    public function set multiColumnSortingEnabled(value:Boolean):void
    {
        if (_multiColumnSortingEnabled == value)
            return;
        
        _multiColumnSortingEnabled = value;
        dispatchChangeEvent("multiColumnSortingEnabledChanged");
    }        
    
    //----------------------------------
    //  gridSelection (private)
    //----------------------------------    
    
    private var _gridSelection:GridSelection = null;
    
    /**
     *  @private
     *  This object becomes the grid's gridSelection property after the grid skin part has been
     *  added.  It should only be referenced by this class when the grid skin part is null. 
     */
    protected function get gridSelection():GridSelection
    {
        if (!_gridSelection)
            _gridSelection = createGridSelection();
        return _gridSelection;
    }
    
    //----------------------------------
    //  imeMode
    //----------------------------------
    
    /**
     *  @private
     */
    private var _imeMode:String = null;
    
    [Inspectable(environment="none")]
    
    /**
     *  The default value for the GridColumn <code>imeMode</code> property, 
     *  which specifies the IME (Input Method Editor) mode.
     *  The IME enables users to enter text in Chinese, Japanese, and Korean.
     *  Flex sets the specified IME mode when the control gets focus,
     *  and sets it back to the previous value when the control loses focus.
     *
     * <p>The flash.system.IMEConversionMode class defines constants for the
     *  valid values for this property.
     *  You can also specify <code>null</code> to specify no IME.</p>
     *
     *  @see flash.system.IMEConversionMode
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get imeMode():String
    {
        return _imeMode;
    }
    
    /**
     *  @private
     */
    public function set imeMode(value:String):void
    {
        _imeMode = value;
    }
    
    //----------------------------------
    //  internalFocusOwner
    //----------------------------------
    
    private static const GRID_FOCUS_OWNER:int = 0;
    private static const HEADER_FOCUS_OWNER:int = 1;
    private static const NO_FOCUS_OWNER:int = -1;
    
    private var _internalFocusOwner:int = -1;
    
    [Bindable("internalFocusOwnerChanged")]
    
    /**
     *  Tracks the internal focus owner when the DataGrid has the focus: one of GRID_FOCUS_OWNER, 
     *  HEADER_FOCUS_OWNER, or NO_FOCUS_OWNER.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    private function get internalFocusOwner():int
    {
        return _internalFocusOwner;
    }
    
    /**
     *  @private
     */
    private function set internalFocusOwner(value:int):void
    {
        if (_internalFocusOwner == value)
            return;
        
        _internalFocusOwner = value;
        
        if (columnHeaderGroup)
            columnHeaderGroup.highlightSelectedColumn = (value == HEADER_FOCUS_OWNER);
        
        if (grid)
            grid.showCaret = (value == GRID_FOCUS_OWNER); 
        
        dispatchChangeEvent("internalFocusOwnerChanged");
    }     
    
    //----------------------------------
    //  itemEditor
    //----------------------------------
    
    private var _itemEditor:IFactory = null;
    
    [Bindable("itemEditorChanged")]
    
    /**
     *  The default value for the GridColumn <code>itemEditor</code> property, 
     *  which specifies the IGridItemEditor class used to create item editor instances.
     * 
     *  @default null.
     *
     *  @see #dataField 
     *  @see spark.components.gridClasses.IGridItemEditor
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5 
     */
    public function get itemEditor():IFactory
    {
        return _itemEditor;
    }
    
    /**
     *  @private
     */
    public function set itemEditor(value:IFactory):void
    {
        if (_itemEditor == value)
            return;
        
        _itemEditor = value;
        
        dispatchChangeEvent("itemEditorChanged");
    }    
    
    /**
     *  A reference to the currently active instance of the item editor, 
     *  if it exists.
     *
     *  <p>To access the item editor instance and the new item value when an 
     *  item is being edited, you use the <code>itemEditorInstance</code> 
     *  property. The <code>itemEditorInstance</code> property
     *  is not valid until the <code>itemEditorSessionStart</code> event is 
     *  dispatched.</p>
     *
     *  <p>The <code>DataGridColumn.itemEditor</code> property defines the
     *  class of the item editor and, therefore, the data type of the item
     *  editor instance.</p>
     *
     *  <p>Do not set this property in MXML.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get itemEditorInstance():IGridItemEditor
    {
        if (editor)
            return editor.itemEditorInstance;
        
        return null; 
    }
    
    //----------------------------------
    //  itemRenderer (delegates to grid.itemRenderer)
    //----------------------------------    
    
    [Bindable("itemRendererChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.Grid#itemRenderer
     *
     *  @default DefaultGridItemRenderer
     *
     *  @see spark.components.gridClasses.GridItemRenderer
     *  @see spark.skins.spark.DefaultGridItemRenderer
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get itemRenderer():IFactory
    {
        return getGridProperty("itemRenderer");
    }
    
    /**
     *  @private
     */
    public function set itemRenderer(value:IFactory):void
    {
        if (setGridProperty("itemRenderer", value))
            dispatchChangeEvent("itemRendererChanged");
    }
    
    //----------------------------------
    //  lockedColumnCount (delegates to grid.lockedColumnCount)
    //---------------------------------- 
    
    [Bindable("lockedColumnCountChanged")]
    [Inspectable(category="General", defaultValue="0", minValue="0")]
    
    /**
     *  @copy spark.components.Grid#lockedColumnCount
     *
     *  @default 0
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public function get lockedColumnCount():int
    {
        return getGridProperty("lockedColumnCount");
    }
    
    /**
     *  @private
     */
    public function set lockedColumnCount(value:int):void
    {
        if (setGridProperty("lockedColumnCount", value))
            dispatchChangeEvent("lockedColumnCountChanged");
    }
    
    //----------------------------------
    //  lockedRowCount (delegates to grid.lockedRowCount)
    //----------------------------------    
    
    [Bindable("lockedRowCountChanged")]
    [Inspectable(category="General", defaultValue="0", minValue="0")]
    
    /**
     *  @copy spark.components.Grid#lockedRowCount
     *
     *  @default 0
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 5.0
     */
    public function get lockedRowCount():int
    {
        return getGridProperty("lockedRowCount");
    }
    
    /**
     *  @private
     */
    public function set lockedRowCount(value:int):void
    {
        if (setGridProperty("lockedRowCount", value))
            dispatchChangeEvent("lockedRowCountChanged");
    }    
    
    //----------------------------------
    //  preserveSelection (delegates to grid.preserveSelection)
    //----------------------------------
    
    [Inspectable(category="General", defaultValue="true")]
    
    /**
     *  @copy spark.components.Grid#preserveSelection
     *
     *  @default true
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get preserveSelection():Boolean
    {
        if (grid)
            return grid.preserveSelection;
        else
            return gridSelection.preserveSelection;
    }
    
    /**
     *  @private
     */    
    public function set preserveSelection(value:Boolean):void
    {
        if (grid)
            grid.preserveSelection = value;
        else
            gridSelection.preserveSelection = value;
    }
    
    //----------------------------------
    //  requireSelection (delegates to grid.requireSelection)
    //----------------------------------
    
    [Inspectable(category="General", defaultValue="false")]
    
    /**
     *  @copy spark.components.Grid#requireSelection
     *
     *  @default false
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requireSelection():Boolean
    {
        if (grid)
            return grid.requireSelection;
        else
            return gridSelection.requireSelection;
    }
    
    /**
     *  @private
     */    
    public function set requireSelection(value:Boolean):void
    {
        if (grid)
            grid.requireSelection = value;
        else
            gridSelection.requireSelection = value;
    }
    
    //----------------------------------
    //  requestedRowCount (delegates to grid.requestedRowCount)
    //----------------------------------
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  @copy spark.components.Grid#requestedRowCount
     *
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedRowCount():int
    {
        return getGridProperty("requestedRowCount");
    }
    
    /**
     *  @private
     */    
    public function set requestedRowCount(value:int):void
    {
        setGridProperty("requestedRowCount", value);
    }
    
    //----------------------------------
    //  requestedColumnCount (delegates to grid.requestedColumnCount)
    //----------------------------------
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  @copy spark.components.Grid#requestedColumnCount
     *
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedColumnCount():int
    {
        return getGridProperty("requestedColumnCount");
    }
    
    /**
     *  @private
     */    
    public function set requestedColumnCount(value:int):void
    {
        setGridProperty("requestedColumnCount", value);
    }
    
    //----------------------------------
    //  requestedMaxRowCount (delegates to grid.requestedMaxRowCount)
    //----------------------------------
    
    [Inspectable(category="General", defaultValue="10", minValue="-1")]
    
    /**
     *  @copy spark.components.Grid#requestedMaxRowCount
     *
     *  @default 10
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedMaxRowCount():int
    {
        return getGridProperty("requestedMaxRowCount");
    }
    
    /**
     *  @private
     */    
    public function set requestedMaxRowCount(value:int):void
    {
        setGridProperty("requestedMaxRowCount", value);
    }    
    
    //----------------------------------
    //  requestedMinRowCount (delegates to grid.requestedMinRowCount)
    //----------------------------------
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  @copy spark.components.Grid#requestedMinRowCount
     *
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedMinRowCount():int
    {
        return getGridProperty("requestedMinRowCount");
    }
    
    /**
     *  @private
     */    
    public function set requestedMinRowCount(value:int):void
    {
        setGridProperty("requestedMinRowCount", value);
    }
    
    //----------------------------------
    //  requestedMinColumnCount (delegates to grid.requestedMinColumnCount)
    //----------------------------------
    
    [Inspectable(category="General", minValue="-1")]
    
    /**
     *  @copy spark.components.Grid#requestedMinColumnCount
     *
     *  @default -1
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get requestedMinColumnCount():int
    {
        return getGridProperty("requestedMinColumnCount");
    }
    
    /**
     *  @private
     */    
    public function set requestedMinColumnCount(value:int):void
    {
        setGridProperty("requestedMinColumnCount", value);
    }
    
    //----------------------------------
    //  resizableColumns (delegates to grid.resizableColumns)
    //----------------------------------
    
    [Bindable("resizableColumnsChanged")]
    [Inspectable(category="General", defaultValue="true")]
    
    /**
     *  @copy spark.components.Grid#resizableColumns
     *
     *  @default true
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get resizableColumns():Boolean
    {
        return getGridProperty("resizableColumns");
    }
    
    /**
     *  @private
     */    
    public function set resizableColumns(value:Boolean):void
    {
        if (setGridProperty("resizableColumns", value))
            dispatchChangeEvent("resizableColumnsChanged");
    }        
    
    //----------------------------------
    //  rowHeight (delegates to grid.rowHeight)
    //----------------------------------
    
    [Bindable("rowHeightChanged")]
    [Inspectable(category="General", minValue="0.0")]
    
    /**
     *  @copy spark.components.Grid#rowHeight
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get rowHeight():Number
    {
        return getGridProperty("rowHeight");
    }
    
    /**
     *  @private
     */    
    public function set rowHeight(value:Number):void
    {
        if (setGridProperty("rowHeight", value))
            dispatchChangeEvent("rowHeightChanged");
    }    
    
    //----------------------------------
    //  selectionMode (delegates to grid.selectionMode)
    //----------------------------------    
    
    [Bindable("selectionModeChanged")]
    [Inspectable(category="General", enumeration="none,singleRow,multipleRows,singleCell,multipleCells", defaultValue="singleRow")]
    
    /**
     *  @copy spark.components.Grid#selectionMode
     *
     *  @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
    {
        if (grid)
            return grid.selectionMode;
        else
            return gridSelection.selectionMode;
    }
    
    /**
     *  @private
     */
    public function  set selectionMode(value:String):void
    {
        if (selectionMode == value)
            return;
        
        if (grid)
            grid.selectionMode = value;
        else
            gridSelection.selectionMode = value;
        
        // Show the caret if we have focus and not in grid selection mode of "none".
        if (grid)
            grid.showCaret = (value != GridSelectionMode.NONE) && (this == getFocus()) && (internalFocusOwner == GRID_FOCUS_OWNER);
        
        dispatchChangeEvent("selectionModeChanged");
    }
    
    /**
     *  @private
     */
    mx_internal function isRowSelectionMode():Boolean
    {
        const mode:String = selectionMode;
        return mode == GridSelectionMode.SINGLE_ROW || mode == GridSelectionMode.MULTIPLE_ROWS;
    }
    
    /**
     *  @private
     */
    mx_internal function isCellSelectionMode():Boolean
    {
        const mode:String = selectionMode;        
        return mode == GridSelectionMode.SINGLE_CELL || mode == GridSelectionMode.MULTIPLE_CELLS;
    }
    
    //----------------------------------
    //  showDataTips
    //----------------------------------
    
    [Bindable("showDataTipsChanged")]
    [Inspectable(category="Data", defaultValue="false")]
    
    /**
     *  @copy spark.components.Grid#showDataTips
     * 
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get showDataTips():Boolean
    {
        return getGridProperty("showDataTips");
    }
    
    /**
     *  @private
     */
    public function set showDataTips(value:Boolean):void
    {
        if (setGridProperty("showDataTips", value))
            dispatchChangeEvent("showDataTipsChanged");
    }    
    
    //----------------------------------
    //  sortableColumns
    //----------------------------------
    
    private var _sortableColumns:Boolean = true;
    
    [Bindable("sortableColumnsChanged")]
    [Inspectable(category="General", defaultValue="true")]
    
    /**
     *  Specifies whether the user can interactively sort columns.
     *  If <code>true</code>, the user can sort the data provider by the
     *  data field of a column by clicking on the column's header.
     *  If <code>true</code>, an individual column can set its
     *  <code>sortable</code> property to <code>false</code> to 
     *  prevent the user from sorting by that column.  
     * 
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get sortableColumns():Boolean
    {
        return _sortableColumns;
    }
    
    /**
     *  @private
     */    
    public function set sortableColumns(value:Boolean):void
    {
        if (_sortableColumns == value)
            return;
        
        _sortableColumns = value;
        dispatchChangeEvent("sortableColumnsChanged");
    }        
    
    //----------------------------------
    //  typicalItem (delegates to grid.typicalItem)
    //----------------------------------    
    
    [Bindable("typicalItemChanged")]
    [Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.Grid#typicalItem
     *
     *  @default null
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get typicalItem():Object
    {
        return getGridProperty("typicalItem");
    }
    
    /**
     *  @private
     */
    public function set typicalItem(value:Object):void
    {
        if (setGridProperty("typicalItem", value))
            dispatchChangeEvent("typicalItemChanged");
    }
    
    /**
     *  @copy spark.components.Grid#invalidateTypicalItem()
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4.5
     */
    public function invalidateTypicalItem():void
    {
        if (grid)
            grid.invalidateTypicalItemRenderer();
    }
    
    //----------------------------------
    //  variableRowHeight (delegates to grid.variableRowHeight)
    //----------------------------------
    
    [Bindable("variableRowHeightChanged")]
    [Inspectable(category="General", defaultValue="false")]
    
    /**
     *  @copy spark.components.Grid#variableRowHeight
     * 
     *  @default false
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get variableRowHeight():Boolean
    {
        return getGridProperty("variableRowHeight");
    }
    
    /**
     *  @private
     */    
    public function set variableRowHeight(value:Boolean):void
    {
        if (setGridProperty("variableRowHeight", value))
            dispatchChangeEvent("variableRowHeightChanged");
    }     
    
    //--------------------------------------------------------------------------
    //
    //  Drag and Drop Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  dragEnabled
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the dragEnabled property.
     */
    private var _dragEnabled:Boolean = false;
    
    [Inspectable(defaultValue="false")]
    
    /**
     *  A flag that indicates whether you can drag items out of
     *  this control and drop them on other controls.
     *  If <code>true</code>, dragging is enabled for the control.
     *  If the <code>dropEnabled</code> property is also <code>true</code>,
     *  you can drag items and drop them within this control
     *  to reorder the items.
     * 
     *  <p>Drag and drop is not supported on mobile devices where 
     *  <code>interactionMode</code> is set to <code>touch</code>.</p>
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function get dragEnabled():Boolean
    {
        return _dragEnabled;
    }
    
    /**
     *  @private
     */
    public function set dragEnabled(value:Boolean):void
    {
        if (value == _dragEnabled)
            return;
        _dragEnabled = value;
        
        if (_dragEnabled)
        {
            addEventListener(DragEvent.DRAG_START, dragStartHandler, false, EventPriority.DEFAULT_HANDLER);
            addEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler, false, EventPriority.DEFAULT_HANDLER);
        }
        else
        {
            removeEventListener(DragEvent.DRAG_START, dragStartHandler, false);
            removeEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler, false);
        }
    }
    
    //----------------------------------
    //  dragMoveEnabled
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the dragMoveEnabled property.
     */
    private var _dragMoveEnabled:Boolean = false;
    
    [Inspectable(defaultValue="false")]
    
    /**
     *  A flag that indicates whether items can be moved instead
     *  of just copied from the control as part of a drag-and-drop
     *  operation.
     *  If <code>true</code>, and the <code>dragEnabled</code> property
     *  is <code>true</code>, items can be moved.
     *  Often the data provider cannot or should not have items removed
     *  from it, so a MOVE operation should not be allowed during
     *  drag-and-drop.
     * 
     *  <p>Drag and drop is not supported on mobile devices where 
     *  <code>interactionMode</code> is set to <code>touch</code>.</p>
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function get dragMoveEnabled():Boolean
    {
        return _dragMoveEnabled;
    }
    
    /**
     *  @private
     */
    public function set dragMoveEnabled(value:Boolean):void
    {
        _dragMoveEnabled = value;
    }
    
    //----------------------------------
    //  dropEnabled
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the <code>dropEnabled</code> property.
     */
    private var _dropEnabled:Boolean = false;
    
    [Inspectable(defaultValue="false")]
    
    /**
     *  A flag that indicates whether dragged items can be dropped onto the 
     *  control.
     *
     *  <p>If you set this property to <code>true</code>,
     *  the control accepts all data formats, and assumes that
     *  the dragged data matches the format of the data in the data provider.
     *  If you want to explicitly check the data format of the data
     *  being dragged, you must handle one or more of the drag events,
     *  such as <code>dragEnter</code> and <code>dragOver</code>, 
     *  and call the DragEvent's <code>preventDefault()</code> method 
     *  to customize the way the list class accepts dropped data.</p>
     *
     *  <p>When you set <code>dropEnabled</code> to <code>true</code>, 
     *  Flex automatically calls the <code>showDropFeedback()</code> 
     *  and <code>hideDropFeedback()</code> methods to display the drop
     *  indicator.</p>
     * 
     *  <p>Drag and drop is not supported on mobile devices where 
     *  <code>interactionMode</code> is set to <code>touch</code>.</p>
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function get dropEnabled():Boolean
    {
        return _dropEnabled;
    }
    
    /**
     *  @private
     */
    public function set dropEnabled(value:Boolean):void
    {
        if (value == _dropEnabled)
            return;
        _dropEnabled = value;
        
        if (_dropEnabled)
        {
            addEventListener(DragEvent.DRAG_ENTER, dragEnterHandler, false, EventPriority.DEFAULT_HANDLER);
            addEventListener(DragEvent.DRAG_EXIT, dragExitHandler, false, EventPriority.DEFAULT_HANDLER);
            addEventListener(DragEvent.DRAG_OVER, dragOverHandler, false, EventPriority.DEFAULT_HANDLER);
            addEventListener(DragEvent.DRAG_DROP, dragDropHandler, false, EventPriority.DEFAULT_HANDLER);
        }
        else
        {
            removeEventListener(DragEvent.DRAG_ENTER, dragEnterHandler, false);
            removeEventListener(DragEvent.DRAG_EXIT, dragExitHandler, false);
            removeEventListener(DragEvent.DRAG_OVER, dragOverHandler, false);
            removeEventListener(DragEvent.DRAG_DROP, dragDropHandler, false);
        }
    }
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  This component holds the focus and accessibilityImplementation (DataGridAccImpl)
     *  for the DataGrid to enable accessibility when the focus shifts to DataGrid descendants, 
     *  notably item editors.
     * 
     *  DataGridAccImpl/createAccessibilityImplementation() initializes the focusOwner's
     *  accessibilityImplementation, rather than the DataGrid's, so that the MSAA 
     *  representation of descendant components will not be "obscured" by DataGridAccImpl.   
     * 
     *  @see #createChildren(), #setFocus(), #isOurFocus().
     */ 
    mx_internal var focusOwner:UIComponent;
    
    /**
     *  @private
     *  The accessibility implementation depends on the focusOwner's bounds, as in 
     *  DisplayObject.getBounds(), which is defined by the bounds of what has been drawn,
     *  not the focusOwner's width and height properties.
     */ 
    private var focusOwnerWidth:Number = 1;
    private var focusOwnerHeight:Number = 1;
    
    /**
     *  @private
     *  Create the focusOwner - a component that holds the keyboard focus for the DataGrid
     *  for the sake of the accessibility implementation.
     * 
     *  This component fails to add its DataGridAccImpl accessibilityImplementation to
     *  the MSAA if it doesn't render, so we draw one alpha=0.0 pixel here and make it
     *  $visible=true.
     */
    override protected function createChildren():void
    {
        super.createChildren();
        
        focusOwner = new UIComponent();
        const g:Graphics = focusOwner.graphics;
        g.clear();
        g.lineStyle(0, 0x000000, 0);
        g.drawRect(0, 0, focusOwnerWidth, focusOwnerHeight);
        $addChild(focusOwner);
        focusOwner.tabEnabled = true;
        focusOwner.tabIndex = tabIndex;
        focusOwner.$visible = true;
    }
    
    /**
     *  @private
     *  Ensure that IDataGridElements are laid out after the grid skin part.
     *  At the moment, DataGrid has only one IDataGridElement, columnHeaderGroup.
     * 
     *  The DataGrid columnHeaderGroup's layout role is unusual, since it depends on
     *  the layout of the grid skin part.
     *  The columnHeaderGroup's column widths, scroll position, and list of visible columns
     *  are defined by the grid.
     *  That means that the grid needs to compute its layout first.
     * 
     *  The Flex LayoutManager orders the per-element work in each of its phases according
     *  to the element's nestLevel. The measure() (validateSize) phase is "bottom up"
     *  with respect to the nestLevel, which means that the deepest nodes in the tree with the
     *  highest nestLevel are measured first.
     *  Similarly the updateDisplayList() (validateDisplayList) phase is "top down" where the nodes
     *  with the lowest nestLevel are validated first. 
     *  To guarantee that the columnHeaderGroup skin part is laid out after the grid skin part,
     *  we need to ensure that its nestLevel is greater than the grid's nestLevel.
     * 
     *  As the DataGrid's skin defines the grid and columnHeaderGroup skin parts, there is no
     *  way for the DataGrid component to constrain their relative locations in the visual element
     *  hierarchy.
     *  However, all ILayoutManagerClients have a nestLevel property, which specifies the element's
     *  depth relative to its SystemManager root.
     *  Thus, we can overcome the limitation by initializing the columnHeaderGroup's nestLevel
     *  to be grid.nestLevel+1, which ensures that the columnHeaderGroup will be validated after
     *  the grid.
     */
    override public function set nestLevel(value:int):void
    {
        super.nestLevel = value;
        
        if (grid)
            initializeDataGridElement(columnHeaderGroup);
    }
    
    /**
     *  @private
     *  Ensure that the DataGrid appears in the correct tab order, despite the fact that its
     *  focusOwner gets the focus.
     */
    override public function set tabIndex(index:int):void
    {
        super.tabIndex = index;
        if (focusOwner)
            focusOwner.tabIndex = index;
    }
    
    /**
     *  @private
     *  Sync the focusOwner's copy of this value because the we can't cover this case in
     *  DataGridAccImpl/get_accDescription(childID). Currently get_accDescription() is never
     *  called with childID=0.
     */
    override public function set accessibilityDescription(value:String):void
    {
        super.accessibilityDescription = value;
        if (focusOwner)
            focusOwner.accessibilityDescription = value;
    }
    
    /**
     *  @private
     *  Sync the focusOwner's copy of this value because the we can't cover this case in
     *  DataGridAccImpl/get_accShortcut(childID). Currently get_accShortcut() is never
     *  called with childID=0.
     */
    override public function set accessibilityShortcut(value:String):void
    {
        super.accessibilityShortcut = value;
        if (focusOwner)
            focusOwner.accessibilityShortcut = value;
    }
    
    /**
     *  @private
     */
    override protected function initializeAccessibility():void
    {
        if (DataGrid.createAccessibilityImplementation != null)
            DataGrid.createAccessibilityImplementation(this);
    }
    
    /**
     *  @private
     *  Override to set proper width and height on focusOwner object that 
     *  the DataGridAccImpl uses to compute the location of the DataGrid.
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        
        if (focusOwner && ((focusOwnerWidth != unscaledWidth) || (focusOwnerHeight != unscaledHeight)))
        {
            focusOwnerWidth = unscaledWidth;
            focusOwnerHeight = unscaledHeight;
            const g:Graphics = focusOwner.graphics;
            g.clear();
            g.lineStyle(0, 0x000000, 0);
            g.drawRect(0, 0, focusOwnerWidth, focusOwnerHeight);        
        }
    }
    
    /**
     *  @private
     */
    override public function setFocus():void
    {
        if (grid)
            focusOwner.setFocus();
    }
    
    /**
     *  @private
     */
    override protected function isOurFocus(target:DisplayObject):Boolean
    {
        return (target == focusOwner) || super.isOurFocus(target);
    }    
    
    /**
     *  @private
     */ 
    override public function styleChanged(styleName:String):void
    {
        super.styleChanged(styleName);
        
        const allStyles:Boolean = (styleName == null || styleName == "styleName");
        
        if (grid)
        {
            if (allStyles || styleManager.isSizeInvalidatingStyle(styleName))
            {
                if (grid)
                {
                    grid.invalidateSize();
                    grid.clearGridLayoutCache(true);
                }
                if (columnHeaderGroup)
                {
                    columnHeaderGroup.layout.clearVirtualLayoutCache();
                    columnHeaderGroup.invalidateSize();
                }
            }
            
            if (allStyles || (styleName == "alternatingRowColors"))
            {
                initializeGridRowBackground();
                if (grid && grid.layout)
                    grid.layout.clearVirtualLayoutCache();               
            }
            
            if (grid)
                grid.invalidateDisplayList();
            
            if (columnHeaderGroup)
                columnHeaderGroup.invalidateDisplayList();
        }
        
        if (scroller)
        {
            // The scrollPolicy styles are initialized in framework/defaults.css
            // so there's no way to determine if been explicitly set here.  To avoid 
            // preempting explicitly set scroller scrollPolicy styles with the default
            // "auto" value, we only forward the style if it's not "auto".
            
            const vsp:String = getStyle("verticalScrollPolicy");
            if (styleName == "verticalScrollPolicy")
                scroller.setStyle("verticalScrollPolicy", vsp);
            else if (allStyles && vsp && (vsp !== ScrollPolicy.AUTO))
                scroller.setStyle("verticalScrollPolicy", vsp);
            
            const hsp:String = getStyle("horizontalScrollPolicy");
            if (styleName == "horizontalScrollPolicy")
                scroller.setStyle("horizontalScrollPolicy", hsp);
            else if (allStyles && hsp && (hsp !== ScrollPolicy.AUTO))
                scroller.setStyle("horizontalScrollPolicy", hsp);
        }
    }
    
    /**
     *  @private
     *  Used to prevent keyboard events that have been redispatched to the Scroller from being
     *  redispatched a second time when they bubble back up.
     */
    private var scrollerEvent:KeyboardEvent = null;
    
    /**
     *  @private
     *  Build in basic keyboard navigation support in Grid. The focus is on
     *  the DataGrid which means the Scroller doesn't see the Keyboard events
     *  unless the event is dispatched to it.
     */
    override protected function keyDownHandler(event:KeyboardEvent):void
    {
        if (!grid || event.isDefaultPrevented())
            return;
        
        // We've seen this event already and dispatched it to the Scroller
        if (event == scrollerEvent)
        {
            scrollerEvent = null;
            event.preventDefault();
            return;
        }
        
        // If the key wasn't targeted to us, then ignore it.
        if (!isOurFocus(DisplayObject(event.target)))
            return;
        
        // Ctrl-A only comes thru on Mac.  On Windows it is a SELECT_ALL
        // event.
        if (event.keyCode == Keyboard.A && event.ctrlKey)
        { 
            selectAllFromKeyboard();
            event.preventDefault();
            return;
        }
        
        // Row selection requires valid row caret, cell selection
        // requires both a valid row and a valid column caret.
        
        if (selectionMode == GridSelectionMode.NONE || 
            grid.caretRowIndex < 0 || 
            grid.caretRowIndex >= dataProviderLength ||
            (isCellSelectionMode() && 
                (grid.caretColumnIndex < 0 || grid.caretColumnIndex >= columnsLength)))
        {
            // We're not going to handle this event, so give the scroller a chance.
            if (scroller && (scrollerEvent != event))
            {
                scrollerEvent = event.clone() as KeyboardEvent;
                scroller.dispatchEvent(scrollerEvent);
            }
            return;
        }

        switch (internalFocusOwner)
        {
            case GRID_FOCUS_OWNER: handleGridKeyEvent(event); break;
            case HEADER_FOCUS_OWNER: handleHeaderKeyEvent(event); break;
        }
    }
    
    /**
     *  @private
     *  Handle KeyboardEvents when the internalFocusOwner is the grid.
     */ 
    private function handleGridKeyEvent(event:KeyboardEvent):void
    {
        var op:String;
        		
        if (event.keyCode == Keyboard.SPACE)
        {
            if (event.ctrlKey)
            {
                // Updates the selection.  The caret remains the same and the
                // anchor is updated.
                if (toggleSelection(grid.caretRowIndex, grid.caretColumnIndex))
                {
                    grid.anchorRowIndex = grid.caretRowIndex;
                    grid.anchorColumnIndex = grid.caretColumnIndex;
                    event.preventDefault();                
                }
            }
            else if (event.shiftKey)
            {
                // Extend the selection.  The caret remains the same.
                if (extendSelection(grid.caretRowIndex, grid.caretColumnIndex))
                    event.preventDefault();                
            }
            else
            {
                if (grid.caretRowIndex != -1)
                {
                    if (isRowSelectionMode())
                    {
                        op = selectionMode == GridSelectionMode.SINGLE_ROW ?
                            GridSelectionEventKind.SET_ROW :
                            GridSelectionEventKind.ADD_ROW;
                        
                        // Add the row and leave the caret position unchanged.
                        if (!commitInteractiveSelection(
                            op, grid.caretRowIndex, grid.caretColumnIndex))
                        {
                            return;
                        }
                        event.preventDefault();                
                    }
                    else if (isCellSelectionMode() && grid.caretColumnIndex != -1)
                    {
                        op = selectionMode == GridSelectionMode.SINGLE_CELL ?
                            GridSelectionEventKind.SET_CELL :
                            GridSelectionEventKind.ADD_CELL;
                        
                        // Add the cell and leave the caret position unchanged.
                        if (!commitInteractiveSelection(
                            op, grid.caretRowIndex, grid.caretColumnIndex))
                        {
                            return;
                        }
                        event.preventDefault();                
                    }
                }
            }
            return;
        }
        
        // Was some other navigation key hit?
        adjustSelectionUponNavigation(event);        
    }
    
    /**
     *  @private
     *  Handle KeyboardEvents when the internalFocusOwner is the header.
     */ 
    private function handleHeaderKeyEvent(event:KeyboardEvent):void
    {
        if (!columnHeaderGroup)
            return;
        
        const selectedIndex:int = columnHeaderGroup.selectedColumnIndex;
        
        if (selectedIndex == -1)
            return;
        
        if ((event.keyCode == Keyboard.SPACE) || (event.keyCode == Keyboard.ENTER))
        {
            const column:GridColumn = getColumnAt(selectedIndex);
            const isMultiColumnSort:Boolean = event.ctrlKey;
            interactiveSortByColumns(column, isMultiColumnSort); 
            if (!isMultiColumnSort && grid)
                internalFocusOwner = GRID_FOCUS_OWNER;
            return;
        }
        
        if (!NavigationUnit.isNavigationUnit(event.keyCode))
            return;
        
        // swap Keyboard.LEFT and Keyboard.RIGHT for RTL layout
        const navigationUnit:uint = mapKeycodeForLayoutDirection(event);  
        
        const firstVisibleColumnIndex:int = grid.getNextVisibleColumnIndex(-1);
        const lastVisibleColumnIndex:int = grid.getPreviousVisibleColumnIndex(columns.length);
        var newSelectedIndex:int = selectedIndex;

        switch (navigationUnit)
        {
            case NavigationUnit.HOME:
            {
                newSelectedIndex = firstVisibleColumnIndex;
                break;
            }
                
            case NavigationUnit.END:
            {
                newSelectedIndex = lastVisibleColumnIndex;                
                break;
            }
                
            case NavigationUnit.LEFT:
            {
                if (event.ctrlKey && !event.shiftKey)
                {
                    moveColumnPosition(selectedIndex, -1);
                }
                else if (event.ctrlKey && event.shiftKey)
                {
                    changeColumnWidth(selectedIndex, -3);
                }
                else
                {
                    if (selectedIndex <= firstVisibleColumnIndex)
                        newSelectedIndex = firstVisibleColumnIndex;
                    else
                        newSelectedIndex = grid.getPreviousVisibleColumnIndex(selectedIndex);
                }
                break;
            }
                
            case NavigationUnit.RIGHT:
            {
                if (event.ctrlKey && !event.shiftKey)
                {
                    moveColumnPosition(selectedIndex, +1);
                }
                else if (event.ctrlKey && event.shiftKey)
                {
                    changeColumnWidth(selectedIndex, +3);
                }
                else
                {
                    if (selectedIndex >= lastVisibleColumnIndex)
                        newSelectedIndex = lastVisibleColumnIndex;
                    else
                        newSelectedIndex = grid.getNextVisibleColumnIndex(selectedIndex);
                }
                break;
            }
        }

        if (newSelectedIndex != selectedIndex)
        {
            columnHeaderGroup.selectedColumnIndex = newSelectedIndex;
            ensureCellIsVisible(-1, newSelectedIndex);
        }
    }
    
    /**
     *  @private
     *  Change the specified column's position by delta, where delta is either +1 or -1.
     */
    private function moveColumnPosition(columnIndex:int, delta:int):void
    {
        const column:GridColumn = getColumnAt(columnIndex);
        if (!column)
            return;
        
        var newColumnIndex:int = -1;
        if (delta == +1)
            newColumnIndex = grid.getNextVisibleColumnIndex(columnIndex);
        else if (delta == -1)
            newColumnIndex = grid.getPreviousVisibleColumnIndex(columnIndex);
        
        if (newColumnIndex != -1)
        {
            columns.removeItemAt(columnIndex);
            columns.addItemAt(column, newColumnIndex);
            columnHeaderGroup.selectedColumnIndex = newColumnIndex;
            grid.ensureCellIsVisible(-1, newColumnIndex);
        }
    }
    
    /**
     *  @private
     *  Change the specified column's width by delta.
     */
    private function changeColumnWidth(columnIndex:int, delta:Number):void
    {
        const column:GridColumn = getColumnAt(columnIndex);
        if (!column)
            return;
        
        var columnWidth:Number = column.width;
        if (isNaN(columnWidth))
            columnWidth = grid.getColumnWidth(columnIndex);

        columnWidth = Math.max(1, columnWidth + delta);
        if (!isNaN(column.maxWidth))
            columnWidth = Math.min(columnWidth, column.maxWidth);
        if (!isNaN(column.minWidth))
            columnWidth = Math.max(columnWidth, column.minWidth);
        column.width = columnWidth;
    }
    
    /**
     *  @private
     *  If the focusManager is trying to tab forwards from the DataGrid and the internalFocusOwner is
     *  currently the grid, then switch the internal focus to the header and cancel the focusManager's
     *  event.  Similarly, if the focusManager is trying to tab backwards (shift-tab) and the internal
     *  focus is currently on the header, then set the internal focus to the grid and cancel the event.
     */    
    protected function keyFocusChangeHandler(event:FocusEvent):void
    {
        if (event.isDefaultPrevented())
            return;
    
        // In an edit session.  Don't let the TAB switch the internal focus.
        if (editor && editor.editorRowIndex != -1 && editor.editorColumnIndex != -1)
            return;
        
        if ((internalFocusOwner == GRID_FOCUS_OWNER) && !event.shiftKey && columnHeaderGroup)
        {
            internalFocusOwner = HEADER_FOCUS_OWNER;
            event.preventDefault();
        }
        else if ((internalFocusOwner == HEADER_FOCUS_OWNER) && event.shiftKey && grid)
        {
            internalFocusOwner = GRID_FOCUS_OWNER;
            event.preventDefault();            
        }
        else 
        {
            internalFocusOwner = (internalFocusOwner == GRID_FOCUS_OWNER) ? HEADER_FOCUS_OWNER : GRID_FOCUS_OWNER;
            // If there's another focusable component, we will lose the focus here
        }
    }
    
    /**
     *  @private
     *  New event in FP10 dispatched when the user activates the platform 
     *  specific accelerator key combination for a select all operation.
     *  On Windows this is ctrl-A and on Mac this is cmd-A.
     */
    protected function selectAllHandler(event:Event):void
    {
        // If the select all was not targeted to the DataGrid, then ignore it.
        if (!grid || event.isDefaultPrevented() || 
            !isOurFocus(DisplayObject(event.target)))
        {
            return;
        }
        
        selectAllFromKeyboard();
    }
    
    /**
     *  @private
     */
    private function selectAllFromKeyboard():void
    {
        // If there is a caret, leave it in its current position.
        if (selectionMode == GridSelectionMode.MULTIPLE_CELLS || 
            selectionMode == GridSelectionMode.MULTIPLE_ROWS)
        {
            if (commitInteractiveSelection(
                GridSelectionEventKind.SELECT_ALL,
                0, 0, dataProvider.length, columns.length))
            {
                grid.anchorRowIndex = 0;
                grid.anchorColumnIndex = 0;
            }
        }
    }
    
    /**
     *  @private
     *  Call partAdded() for IFactory type skin parts.   By default, partAdded() is not 
     *  called for IFactory type skin part variables, because they're assumed to be 
     *  "dynamic" skin parts, to be created with createDynamicPartInstance().  That's 
     *  not the case with the IFactory valued parts listed in factorySkinPartNames.
     */ 
    override protected function findSkinParts():void
    {
        super.findSkinParts();
        
        for each (var partName:String in factorySkinPartNames)
        {
            if ((partName in skin) && skin[partName])
                partAdded(partName, skin[partName]);
        }
    }
    
    /**
     *  @private
     */
    private function initializeDataGridElement(elt:IDataGridElement):void
    {
        if (!elt)
            return;
        
        elt.dataGrid = this;
        if (elt.nestLevel <= grid.nestLevel)
        {
            elt.validateNow();
            elt.nestLevel = grid.nestLevel + 1;
        }
    }
    
    /**
     *  @private
     */
    override protected function partAdded(partName:String, instance:Object):void
    {
        super.partAdded(partName, instance);
        
        if (instance == grid)
        {
            // Basic Initialization
            
            gridSelection.grid = grid;
            grid.gridSelection = gridSelection;
            grid.dataGrid = this;
            
            // Grid cover Properties
            
            const modifiedGridProperties:Object = gridProperties;  // explicitly set properties
            gridProperties = {propertyBits:0};
            
            for (var propertyName:String in modifiedGridProperties)
            {
                if (propertyName == "propertyBits")
                    continue;
                setGridProperty(propertyName, modifiedGridProperties[propertyName]);
            }
            
            // IFactory valued skin parts => Grid visual element properties
            
            initializeGridRowBackground(); // sets grid.rowBackground if alternatingRowColors set
            grid.columnSeparator = columnSeparator;
            grid.rowSeparator = rowSeparator;
            grid.hoverIndicator = hoverIndicator;
            grid.caretIndicator = caretIndicator;
            grid.selectionIndicator = selectionIndicator;
            grid.lockedColumnsSeparator = lockedColumnsSeparator;
            grid.lockedRowsSeparator = lockedRowsSeparator;
            
            // Event Handlers
            
            grid.addEventListener(GridEvent.GRID_MOUSE_DOWN, grid_mouseDownHandler, false, EventPriority.DEFAULT_HANDLER);
            grid.addEventListener(GridEvent.GRID_MOUSE_UP, grid_mouseUpHandler, false, EventPriority.DEFAULT_HANDLER);
            grid.addEventListener(GridEvent.GRID_ROLL_OVER, grid_rollOverHandler, false, EventPriority.DEFAULT_HANDLER);
            grid.addEventListener(GridEvent.GRID_ROLL_OUT, grid_rollOutHandler, false, EventPriority.DEFAULT_HANDLER);
            grid.addEventListener(GridCaretEvent.CARET_CHANGE, grid_caretChangeHandler);            
            grid.addEventListener(FlexEvent.VALUE_COMMIT, grid_valueCommitHandler);
            grid.addEventListener("invalidateSize", grid_invalidateSizeHandler);            
            grid.addEventListener("invalidateDisplayList", grid_invalidateDisplayListHandler);
            grid.addEventListener("gridViewsChanged", grid_gridViewsChangedHandler);
            
            // Deferred operations (grid selection updates)
            
            for each (var deferredGridOperation:Function in deferredGridOperations)
            deferredGridOperation(grid);
            deferredGridOperations.length = 0;
            
            // IDataGridElements: columnHeaderGroup...
            
            initializeDataGridElement(columnHeaderGroup);
            
            // Create the data grid editor
            
            editor = createEditor();
            editor.initialize();                               
        }
        
        if (instance == alternatingRowColorsBackground)
            initializeGridRowBackground();
        
        if (grid)
        {
            if (instance == columnSeparator) 
                grid.columnSeparator = columnSeparator;
            
            if (instance == rowSeparator) 
                grid.rowSeparator = rowSeparator;
            
            if (instance == lockedColumnsSeparator) 
                grid.lockedColumnsSeparator = lockedColumnsSeparator;
            
            if (instance == lockedRowsSeparator) 
                grid.lockedRowsSeparator = lockedRowsSeparator;            
            
            if (instance == hoverIndicator) 
                grid.hoverIndicator = hoverIndicator;
            
            if (instance == caretIndicator)
            {                
                grid.caretIndicator = caretIndicator;
                
                // Add a focus listener so we can turn the caret on and off
                // when we get and lose focus.
                addEventListener(FocusEvent.FOCUS_IN, dataGrid_focusHandler);
                addEventListener(FocusEvent.FOCUS_OUT, dataGrid_focusHandler);
                if (grid)
                    grid.showCaret = false;
            }
            
            if (instance == rowBackground)
                grid.rowBackground = rowBackground;
            
            if (instance == selectionIndicator) 
                grid.selectionIndicator = selectionIndicator;
            
        }
        
        if (instance == columnHeaderGroup)
        {
            if (grid)
                initializeDataGridElement(columnHeaderGroup);
            
            columnHeaderGroup.addEventListener(GridEvent.GRID_CLICK, columnHeaderGroup_clickHandler);
            columnHeaderGroup.addEventListener(GridEvent.GRID_ROLL_OVER, columnHeaderGroup_rollOverHandler);
            columnHeaderGroup.addEventListener(GridEvent.GRID_ROLL_OUT, columnHeaderGroup_rollOutHandler);                
            columnHeaderGroup.addEventListener(GridEvent.SEPARATOR_ROLL_OVER, separator_rollOverHandler);
            columnHeaderGroup.addEventListener(GridEvent.SEPARATOR_ROLL_OUT, separator_rollOutHandler);
            columnHeaderGroup.addEventListener(GridEvent.SEPARATOR_MOUSE_DOWN, separator_mouseDownHandler);
            columnHeaderGroup.addEventListener(GridEvent.SEPARATOR_MOUSE_DRAG, separator_mouseDragHandler);
            columnHeaderGroup.addEventListener(GridEvent.SEPARATOR_MOUSE_UP, separator_mouseUpHandler);  
        }
        
        if (instance == scroller)
        {
            // The scrollPolicy styles are initialized in framework/defaults.css
            // so there's no way to determine if been explicitly set here.  To avoid 
            // preempting explicitly set scroller scrollPolicy styles with the default
            // "auto" value, we only forward the style if it's not "auto".
            
            const vsp:String = getStyle("verticalScrollPolicy");
            if (vsp && (vsp !== ScrollPolicy.AUTO))
                scroller.setStyle("verticalScrollPolicy", vsp);
            
            const hsp:String = getStyle("horizontalScrollPolicy");
            if (hsp && (hsp !== ScrollPolicy.AUTO))
                scroller.setStyle("horizontalScrollPolicy", hsp);            
        }
    }
    
    /**
     * @private
     */
    override protected function partRemoved(partName:String, instance:Object):void
    {
        super.partRemoved(partName, instance);
        
        if (instance == grid)
        {
            // Basic Initialization
            
            gridSelection.grid = null;
            grid.gridSelection = null;
            grid.dataGrid = null;            
            
            // Event Handlers
            grid.removeEventListener("gridViewsChanged", grid_gridViewsChangedHandler);            
            grid.removeEventListener("invalidateSize", grid_invalidateSizeHandler);            
            grid.removeEventListener("invalidateDisplayList", grid_invalidateDisplayListHandler);
            grid.removeEventListener(GridEvent.GRID_MOUSE_DOWN, grid_mouseDownHandler);
            grid.removeEventListener(GridEvent.GRID_MOUSE_UP, grid_mouseUpHandler);
            grid.removeEventListener(GridEvent.GRID_ROLL_OVER, grid_rollOverHandler);
            grid.removeEventListener(GridEvent.GRID_ROLL_OUT, grid_rollOutHandler);            
            grid.removeEventListener(GridCaretEvent.CARET_CHANGE, grid_caretChangeHandler);            
            grid.removeEventListener(FlexEvent.VALUE_COMMIT, grid_valueCommitHandler);
            
            // Cover Properties
            
            const gridPropertyBits:uint = gridProperties.propertyBits;
            gridProperties = {};
            
            for (var propertyName:String in gridPropertyDefaults)
            {
                var propertyBit:uint = partPropertyBits[propertyName];
                if ((propertyBit & gridPropertyBits) == propertyBit)
                    gridProperties[propertyName] = getGridProperty(propertyName);                
            }
            
            // Visual Elements
            
            grid.rowBackground = null;
            grid.columnSeparator = null;
            grid.rowSeparator = null;
            grid.hoverIndicator = null;
            grid.caretIndicator = null;
            grid.selectionIndicator = null;
            
            // IDataGridElements: grid, columnHeaderGroup
            
            if (columnHeaderGroup)
                columnHeaderGroup.dataGrid = null; 
            
            // Data grid editor
            if (editor)
            {
                editor.uninitialize();
                editor = null;
            }
            
            if (internalFocusOwner == GRID_FOCUS_OWNER)
                internalFocusOwner = NO_FOCUS_OWNER;
        }
        
        if (grid)
        {
            if (instance == columnSeparator) 
                grid.columnSeparator = null;
            
            if (instance == rowSeparator) 
                grid.rowSeparator = null;
            
            if (instance == lockedColumnsSeparator) 
                grid.lockedColumnsSeparator = null;
            
            if (instance == lockedRowsSeparator) 
                grid.lockedRowsSeparator = null;                
            
            if (instance == hoverIndicator) 
                grid.hoverIndicator = null;
            
            if (instance == caretIndicator)
            {
                grid.caretIndicator = null;
                
                removeEventListener(FocusEvent.FOCUS_IN, dataGrid_focusHandler);
                removeEventListener(FocusEvent.FOCUS_OUT, dataGrid_focusHandler);
            }
            
            if (instance == selectionIndicator) 
                grid.selectionIndicator = null;
            
            if (instance == rowBackground)
                grid.rowBackground = null;
        }
        
        if (instance == columnHeaderGroup)
        {
            columnHeaderGroup.dataGrid = null;
            columnHeaderGroup.removeEventListener(GridEvent.GRID_CLICK, columnHeaderGroup_clickHandler);
            columnHeaderGroup.removeEventListener(GridEvent.GRID_ROLL_OVER, columnHeaderGroup_rollOverHandler);
            columnHeaderGroup.removeEventListener(GridEvent.GRID_ROLL_OUT, columnHeaderGroup_rollOutHandler);               
            columnHeaderGroup.removeEventListener(GridEvent.SEPARATOR_ROLL_OVER, separator_rollOverHandler);
            columnHeaderGroup.removeEventListener(GridEvent.SEPARATOR_ROLL_OUT, separator_rollOutHandler);
            columnHeaderGroup.removeEventListener(GridEvent.SEPARATOR_MOUSE_DOWN, separator_mouseDownHandler);
            columnHeaderGroup.removeEventListener(GridEvent.SEPARATOR_MOUSE_DRAG, separator_mouseDragHandler);
            columnHeaderGroup.removeEventListener(GridEvent.SEPARATOR_MOUSE_UP, separator_mouseUpHandler);
            
            if (internalFocusOwner == HEADER_FOCUS_OWNER)
                internalFocusOwner = NO_FOCUS_OWNER;            
        }
    }
    
    //----------------------------------
    //  selectedCell
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    
    /**
     *  @copy spark.components.Grid#selectedCell
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedCell():CellPosition
    {
        if (grid)
            return grid.selectedCell;
        
        return selectedCells.length ? selectedCells[0] : null;
    }
    
    /**
     *  @private
     */
    public function set selectedCell(value:CellPosition):void
    {
        if (grid)
            grid.selectedCell = value;
        else
        {
            const valueCopy:CellPosition = (value) ? new CellPosition(value.rowIndex, value.columnIndex) : null;
            
            var f:Function = function(g:Grid):void
            {
                g.selectedCell = valueCopy;
            }
            deferredGridOperations.push(f);
        }
    }    
    
    //----------------------------------
    //  selectedCells
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    
    /**
     *  @copy spark.components.Grid#selectedCells
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedCells():Vector.<CellPosition>
    {
        return grid ? grid.selectedCells : gridSelection.allCells();
    }
    
    /**
     *  @private
     */
    public function set selectedCells(value:Vector.<CellPosition>):void
    {
        if (grid)
            grid.selectedCells = value;
        else
        {
            const valueCopy:Vector.<CellPosition> = (value) ? value.concat() : null;
            var f:Function = function(g:Grid):void
            {
                g.selectedCells = valueCopy;
            }
            deferredGridOperations.push(f);
        }
    }       
    
    //----------------------------------
    //  selectedIndex
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General", defaultValue="-1")]
    
    /**
     *  @copy spark.components.Grid#selectedIndex
     *
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedIndex():int
    {
        if (grid)
            return grid.selectedIndex;
        
        return (selectedIndices.length > 0) ? selectedIndices[0] : -1;
    }
    
    /**
     *  @private
     */
    public function set selectedIndex(value:int):void
    {
        if (grid)
            grid.selectedIndex = value;
        else
        {
            var f:Function = function(g:Grid):void
            {
                g.selectedIndex = value;
            };
            deferredGridOperations.push(f);
        }
    }
    
    //----------------------------------
    //  selectedIndices
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General")]
    
    /**
     *  @copy spark.components.Grid#selectedIndices
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedIndices():Vector.<int>
    {
        return grid ? grid.selectedIndices : gridSelection.allRows();
    }
    
    /**
     *  @private
     */
    public function set selectedIndices(value:Vector.<int>):void
    {
        if (grid)
            grid.selectedIndices = value;
        else
        {
            const valueCopy:Vector.<int> = (value) ? value.concat() : null;
            var f:Function = function(g:Grid):void
            {
                g.selectedIndices = valueCopy;
            }
            deferredGridOperations.push(f);
        }
    }    
    
    //----------------------------------
    //  selectedItem
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General", defaultValue="null")]
    
    /**
     *  @copy spark.components.Grid#selectedItem
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedItem():Object
    {
        if (grid)
            return grid.selectedItem;
        
        return (dataProvider && (selectedIndex > 0)) ? 
            dataProvider.getItemAt(selectedIndex) : undefined;
    }
    
    /**
     *  @private
     */
    public function set selectedItem(value:Object):void
    {
        if (grid)
            grid.selectedItem = value;
        else
        {
            var f:Function = function(g:Grid):void
            {
                g.selectedItem = value;
            }
            deferredGridOperations.push(f);
        }
    }    
    
    //----------------------------------
    //  selectedItems
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    [Inspectable(category="General")]
    
    /**
     *  @copy spark.components.Grid#selectedItems
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectedItems():Vector.<Object>
    {
        if (grid)
            return grid.selectedItems;
        
        var items:Vector.<Object> = new Vector.<Object>();
        
        for (var i:int = 0; i < selectedIndices.length; i++)
            items.push(selectedIndices[i]);
        
        return items;
    }
    
    /**
     *  @private
     */
    public function set selectedItems(value:Vector.<Object>):void
    {
        if (grid)
            grid.selectedItems = value;
        else
        {
            const valueCopy:Vector.<Object> = value.concat();
            var f:Function = function(g:Grid):void
            {
                g.selectedItems = valueCopy;
            }
            deferredGridOperations.push(f);
        }
    }      
    
    //----------------------------------
    //  selectionLength
    //----------------------------------
    
    [Bindable("selectionChange")]
    [Bindable("valueCommit")]
    
    /**
     *  @copy spark.components.Grid#selectionLength
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get selectionLength():int
    {
        return grid ? grid.selectionLength : gridSelection.selectionLength;
    }    
    
    //--------------------------------------------------------------------------
    //
    //  Public Methods
    //
    //--------------------------------------------------------------------------

    /**
    *  @copy spark.components.Grid#findRowIndex()
    *
    *  @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
    {
        if (grid)
        {
            return grid.findRowIndex(field, value, startingIndex, patternType);
        }
        else
        {
            return -1;
        }
    }


    /**
    *  @copy spark.components.Grid#findRowIndices()
    *
    *  @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
    {
        if (grid)
        {
            return grid.findRowIndices(field, values, patternType);
        }
        else
        {
            return [];
        }
    }


    /**
     *  @copy spark.components.Grid#invalidateCell()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function invalidateCell(rowIndex:int, columnIndex:int):void
    {
        if (grid)
            grid.invalidateCell(rowIndex, columnIndex);
    }


    /**
    *  @copy spark.components.Grid#moveIndexFindRow()
    *
    *  @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
    {
        if (grid)
        {
            return grid.moveIndexFindRow(field, value, startingIndex, patternType);
        }
        else
        {
            return false;
        }
    }


    /**
    *  @copy spark.components.Grid#moveIndexFirstRow()
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexFirstRow():void
    {
        if (grid)
        {
            grid.moveIndexFirstRow();
        }
    }


    /**
    *  @copy spark.components.Grid#moveIndexLastRow()
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexLastRow():void
    {
        if (grid)
        {
            grid.moveIndexLastRow();
        }
    }


    /**
    *  @copy spark.components.Grid#moveIndexNextRow()
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexNextRow():void
    {
        if (grid)
        {
            grid.moveIndexNextRow();
        }
    }


    /**
    *  @copy spark.components.Grid#moveIndexPreviousRow()
    *
    *  @langversion 3.0
    *  @playerversion Flash 11.1
    *  @playerversion AIR 3.4
    *  @productversion Flex 4.10
    */
    public function moveIndexPreviousRow():void
    {
        if (grid)
        {
            grid.moveIndexPreviousRow();
        }
    }


    /**
     *  @copy spark.components.Grid#selectAll()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectAll():Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.selectAll();
        }
        else
        {
            selectionChanged = gridSelection.selectAll();
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  @copy spark.components.Grid#clearSelection()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function clearSelection():Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.clearSelection();
        }
        else
        {
            selectionChanged = gridSelection.removeAll();
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    //----------------------------------
    //  selection for rows
    //----------------------------------    
    
    /**
     *  @copy spark.components.Grid#selectionContainsIndex()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectionContainsIndex(rowIndex:int):Boolean 
    {
        if (grid)
            return grid.selectionContainsIndex(rowIndex);
        else
            return gridSelection.containsRow(rowIndex);         
    }
    
    /**
     *  @copy spark.components.Grid#selectionContainsIndices()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectionContainsIndices(rowIndices:Vector.<int>):Boolean 
    {
        if (grid)
            return grid.selectionContainsIndices(rowIndices);
        else
            return gridSelection.containsRows(rowIndices);
    }
    
    /**
     *  @copy spark.components.Grid#setSelectedIndex()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function setSelectedIndex(rowIndex:int):Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.setSelectedIndex(rowIndex);
        }
        else
        {
            selectionChanged = gridSelection.setRow(rowIndex);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  @copy spark.components.Grid#addSelectedIndex()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function addSelectedIndex(rowIndex:int):Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.addSelectedIndex(rowIndex);
        }
        else
        {
            selectionChanged = gridSelection.addRow(rowIndex);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  @copy spark.components.Grid#removeSelectedIndex()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function removeSelectedIndex(rowIndex:int):Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.removeSelectedIndex(rowIndex);
        }
        else
        {
            selectionChanged = gridSelection.removeRow(rowIndex);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  @copy spark.components.Grid#selectIndices()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectIndices(rowIndex:int, rowCount:int):Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.selectIndices(rowIndex, rowCount);
        }
        else
        {
            selectionChanged = gridSelection.setRows(rowIndex, rowCount);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    //----------------------------------
    //  selection for cells
    //----------------------------------    
    
    /**
     *  @copy spark.components.Grid#selectionContainsCell()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function selectionContainsCell(rowIndex:int, columnIndex:int):Boolean
    {
        if (grid)
            return grid.selectionContainsCell(rowIndex, columnIndex);
        else
            return gridSelection.containsCell(rowIndex, columnIndex);
    }
    
    /**
     *  @copy spark.components.Grid#selectionContainsCellRegion()
     * 
     *  @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
    {
        if (grid)
        {
            return grid.selectionContainsCellRegion(
                rowIndex, columnIndex, rowCount, columnCount);
        }
        else
        {
            return gridSelection.containsCellRegion(
                rowIndex, columnIndex, rowCount, columnCount);
        }
    }
    
    /**
     *  @copy spark.components.Grid#setSelectedCell()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function setSelectedCell(rowIndex:int, columnIndex:int):Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.setSelectedCell(rowIndex, columnIndex);
        }
        else
        {
            selectionChanged = gridSelection.setCell(rowIndex, columnIndex);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  @copy spark.components.Grid#addSelectedCell()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function addSelectedCell(rowIndex:int, columnIndex:int):Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.addSelectedCell(rowIndex, columnIndex);
        }
        else
        {
            selectionChanged = gridSelection.addCell(rowIndex, columnIndex);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  @copy spark.components.Grid#removeSelectedCell()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function removeSelectedCell(rowIndex:int, columnIndex:int):Boolean
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.removeSelectedCell(rowIndex, columnIndex);
        }
        else
        {
            selectionChanged = gridSelection.removeCell(rowIndex, columnIndex);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }
    
    /**
     *  @copy spark.components.Grid#selectCellRegion()
     *  
     *  @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
    {
        var selectionChanged:Boolean;
        
        if (grid)
        {
            selectionChanged = grid.selectCellRegion(
                rowIndex, columnIndex, rowCount, columnCount);
        }
        else
        {
            selectionChanged = gridSelection.setCellRegion(
                rowIndex, columnIndex, rowCount, columnCount);
            if (selectionChanged)
                dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        }
        
        return selectionChanged;
    }    
    
    /**
     *  In response to user input (mouse or keyboard) which changes the 
     *  selection, this method dispatches the <code>selectionChanging</code> event. 
     *  If the event is not canceled, it then commits the selection change, and then 
     *  dispatches the <code>selectionChange</code> event.  
     *  The caret location is not updated.  
     *  To detect if the caret has changed, use the <code>caretChanged</code> event.
     * 
     *  @param selectionEventKind A constant defined by the GridSelectionEventKind class 
     *  that specifies the selection that is being committed.  If not null, this is used to 
     *  generate the <code>selectionChanging</code> event.
     * 
     *  @param rowIndex If <code>selectionEventKind</code> is for a row or a
     *  cell, the 0-based <code>rowIndex</code> of the selection in the 
     *  data provider. 
     *  If <code>selectionEventKind</code> is 
     *  for multiple cells, the 0-based <code>rowIndex</code> of the origin of the
     *  cell region. The default is -1 to indicate this
     *  parameter is not being used.
     * 
     *  @param columnIndex If <code>selectionEventKind</code> is for a single row or 
     *  a single cell, the 0-based <code>columnIndex</code> of the selection. 
     *  If <code>selectionEventKind</code> is for multiple 
     *  cells, the 0-based <code>columnIndex</code> of the origin of the
     *  cell region. The default is -1 to indicate this
     *  parameter is not being used.
     * 
     *  @param rowCount If <code>selectionEventKind</code> is for a cell region, 
     *  the number of rows in the cell region.  The default is -1 to indicate
     *  this parameter is not being used.
     * 
     *  @param columnCount If <code>selectionEventKind</code> is for a cell region, 
     *  the number  of columns in the cell region.  The default is -1 to 
     *  indicate this parameter is not being used.
     *
     *  @return <code>true</code> if the selection was committed or did not change, or 
     *  <code>false</code> if the selection was canceled or could not be committed due to 
     *  an error, such as index out of range or the <code>selectionEventKind</code> is not 
     *  compatible with the <code>selectionMode</code>.
     * 
     *  @see spark.events.GridSelectionEvent#SELECTION_CHANGE
     *  @see spark.events.GridSelectionEvent#SELECTION_CHANGING
     *  @see spark.events.GridSelectionEventKind
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    protected function commitInteractiveSelection(
        selectionEventKind:String,                                         
        rowIndex:int,
        columnIndex:int, 
        rowCount:int = 1, 
        columnCount:int = 1):Boolean
        
    {
        if (!grid)
            return false;
        
        // Assumes selectionEventKind is valid for given selectionMode.  Assumes
        // indices are within range.
        
        var selectionChange:CellRegion = 
            new CellRegion(rowIndex, columnIndex, rowCount, columnCount);
        
        // Step 1: determine if the selection will change if the operation.
        // is committed.  
        if (!doesChangeCurrentSelection(selectionEventKind, selectionChange))
            return true;
        
        // Step 2: dispatch the "changing" event. If preventDefault() is called
        // on this event, the selection change will be cancelled.        
        if (hasEventListener(GridSelectionEvent.SELECTION_CHANGING))
        {
            const changingEvent:GridSelectionEvent = 
                new GridSelectionEvent(GridSelectionEvent.SELECTION_CHANGING, 
                    false, true, 
                    selectionEventKind, selectionChange); 
            
            // The event was cancelled so don't change the selection.
            if (!dispatchEvent(changingEvent))
                return false;
        }
        
        // Step 3: commit the selection change.  Call the gridSelection
        // methods directly so that the caret position is not altered and 
        // a VALUE_COMMIT event is not dispatched.
        
        var changed:Boolean;
        switch (selectionEventKind)
        {
            case GridSelectionEventKind.SET_ROW:
            {
                changed = grid.gridSelection.setRow(rowIndex);
                break;
            }
            case GridSelectionEventKind.ADD_ROW:
            {
                changed = grid.gridSelection.addRow(rowIndex);
                break;
            }
                
            case GridSelectionEventKind.REMOVE_ROW:
            {
                changed = grid.gridSelection.removeRow(rowIndex);
                break;
            }
                
            case GridSelectionEventKind.SET_ROWS:
            {
                changed = grid.gridSelection.setRows(rowIndex, rowCount);
                break;
            }
                
            case GridSelectionEventKind.SET_CELL:
            {
                changed = grid.gridSelection.setCell(rowIndex, columnIndex);
                break;
            }
                
            case GridSelectionEventKind.ADD_CELL:
            {
                changed = grid.gridSelection.addCell(rowIndex, columnIndex);
                break;
            }
                
            case GridSelectionEventKind.REMOVE_CELL:
            {
                changed = grid.gridSelection.removeCell(rowIndex, columnIndex);
                break;
            }
                
            case GridSelectionEventKind.SET_CELL_REGION:
            {
                changed = grid.gridSelection.setCellRegion(
                    rowIndex, columnIndex, 
                    rowCount, columnCount);
                break;
            }
                
            case GridSelectionEventKind.SELECT_ALL:
            {
                changed = grid.gridSelection.selectAll();
                break;
            }
        }
        
        // Selection change failed for some unforseen reason.
        if (!changed)
            return false;
        
        grid.invalidateDisplayListFor("selectionIndicator");
        
        // Step 4: dispatch the "change" event.
        if (hasEventListener(GridSelectionEvent.SELECTION_CHANGE))
        {
            const changeEvent:GridSelectionEvent = 
                new GridSelectionEvent(GridSelectionEvent.SELECTION_CHANGE, 
                    false, true, 
                    selectionEventKind, selectionChange); 
            dispatchEvent(changeEvent);
            // TBD: to trigger bindings on grid selectedCell/Index/Item properties
            if (grid.hasEventListener(GridSelectionEvent.SELECTION_CHANGE))
                grid.dispatchEvent(changeEvent);
        }
        
        // Step 5: dispatch the "valueCommit" event.
        dispatchFlexEvent(FlexEvent.VALUE_COMMIT);
        
        return true;
    }
    
    /**
     *  Updates the grid's caret position.  
     *  If the caret position changes, the <code>grid</code> skin part dispatches a 
     *  <code>caretChange</code> event.
     *
     *  @param newCaretRowIndex The 0-based rowIndex of the new caret position.
     * 
     *  @param newCaretColumnIndex The 0-based columnIndex of the new caret 
     *  position.  If the selectionMode is row-based, this is -1.
     * 
     *  @see spark.events.GridCaretEvent#CARET_CHANGE
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    protected function commitCaretPosition(newCaretRowIndex:int, 
                                           newCaretColumnIndex:int):void
    {
        grid.caretRowIndex = newCaretRowIndex;
        grid.caretColumnIndex = newCaretColumnIndex;
    }
    
    /**
     *  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.
     *
     *  @see spark.components.Grid.createGridSelection
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    mx_internal function createGridSelection():GridSelection
    {
        return new GridSelection();    
    }
    
    //--------------------------------------------------------------------------
    //
    //  Selection Utility Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    protected function selectionContainsOnlyIndex(index:int):Boolean 
    {
        if (grid)
            return grid.selectionContainsIndex(index) && grid.selectionLength == 1;
        else
            return gridSelection.containsRow(index) && gridSelection.selectionLength == 1;
    }
    
    /**
     *  @private
     *  Return true, if the current selection, only contains the rows in
     *  the selection change.
     */
    protected function selectionContainsOnlyIndices(selectionChange:CellRegion):Boolean 
    {
        var selectionLength:int = 
            grid ? grid.selectionLength : gridSelection.selectionLength;
        
        if (selectionChange.rowCount != selectionLength)
            return false;
        
        const bottom:int = 
            selectionChange.rowIndex + selectionChange.rowCount;
        
        for (var rowIndex:int = selectionChange.rowIndex; 
            rowIndex < bottom; 
            rowIndex++)
        {
            if (grid)
            {
                if (!grid.selectionContainsIndex(rowIndex)) 
                    return false;
            }
            else
            {
                if (!gridSelection.containsRow(rowIndex))
                    return false;
            }
        }
        
        return true;        
    }
    
    /**
     *  @private
     */
    private function selectionContainsOnlyCell(rowIndex:int, columnIndex:int):Boolean
    {
        if (grid)
            return grid.selectionContainsCell(rowIndex, columnIndex) && grid.selectionLength == 1;
        else
            return gridSelection.containsCell(rowIndex, columnIndex) && gridSelection.selectionLength == 1;
    }
    
    /**
     *  @private
     */
    private function selectionContainsOnlyCellRegion(rowIndex:int, 
                                                     columnIndex:int, 
                                                     rowCount:int, 
                                                     columnCount:int):Boolean
    {
        if (grid)
        {
            return grid.selectionContainsCellRegion(
                rowIndex, columnIndex, rowCount, columnCount) &&
                grid.selectionLength == rowCount * columnCount;
        }
        else
        {
            return gridSelection.containsCellRegion(
                rowIndex, columnIndex, rowCount, columnCount) &&
                gridSelection.selectionLength == rowCount * columnCount;
        }
    }
    
    //--------------------------------------------------------------------------
    //
    //  Item Editor Methods
    //
    //--------------------------------------------------------------------------
 
	/**
	 *  Returns true if a datagrid cell is editable.
	 * 
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 2.5
	 *  @productversion Flex 4.5
	 *  
	 */ 
	protected function isCellEditable(rowIndex:int, columnIndex:int):Boolean
	{
        try
        {
            var dataItem:Object = dataProvider.getItemAt(rowIndex);
            var column:GridColumn = GridColumn(columns.getItemAt(columnIndex));
            var dataField:String = column.dataField;
        }
        catch (e:RangeError)
        {
            return false;
        }


		return isDataEditable(dataItem, dataField);
	}
	
	/**
	 *  Override to make a datagrid cell editable based on the data item.
	 * 
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 2.5
	 *  @productversion Flex 4.5
	 *  
	 */ 
	protected function isDataEditable(dataItem:Object, dataField:String):Boolean
	{
		return (dataItem != null);
	}
	
    /**
     *  Starts an editor session on a selected cell in the grid. This method  
     *  by-passes checks of the editable property on the DataGrid and GridColumn
     *  that prevent the user interface from starting an editor session.
     * 
     *  A <code>startItemEditorSession</code> event is dispatched before
     *  an item editor is created. This allows a listener dynamically change 
     *  the item editor for a specified cell. 
     * 
     *  The event can also be cancelled by calling the 
     *  <code>preventDefault()</code> method, to prevent the 
     *  editor session from being created.
     * 
     *  @param rowIndex The zero-based row index of the cell to edit.
     *
     *  @param columnIndex The zero-based column index of the cell to edit.  
     * 
     *  @return <code>true</code> if the editor session was started. 
     *  Returns <code>false</code> if the editor session was cancelled or was
     *  otherwise unable to be started. Note that an editor session cannot be
     *  started in a column that is not visible.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     *  
     */ 
    public function startItemEditorSession(rowIndex:int, columnIndex:int):Boolean
    {
        if (editor && isCellEditable(rowIndex,columnIndex))
            return editor.startItemEditorSession(rowIndex, columnIndex);
        
        return false;
    }
    
    /**
     *  Closes the currently active editor and optionally saves the editor's value
     *  by calling the item editor's <code>save()</code> method.  
     *  If the <code>cancel</code> parameter is <code>true</code>,
     *  then the editor's <code>cancel()</code> method is called instead.
     * 
     *  @param cancel If <code>false</code>, the data in the editor is saved. 
     *  Otherwise the data in the editor is discarded.
     *
     *  @return <code>true</code> if the editor session was saved, 
     *  and <code>false</code> if the save was cancelled.  
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */ 
    public function endItemEditorSession(cancel:Boolean = false):Boolean
    {
        if (editor)
            return editor.endItemEditorSession(cancel);
        
        return false;
    }
    
    /**
     *  Create the data grid editor. Overriding this function will
     *  allow the complete replacement of the data grid editor.
     */ 
    mx_internal function createEditor():DataGridEditor
    {
        return new DataGridEditor(this);    
    }

    //--------------------------------------------------------------------------
    //
    //  Sorting Methods
    //
    //--------------------------------------------------------------------------

    private function ensureComplexFieldsMonitoring(sortFields:Array):void
    {
        if(!(dataProvider is ListCollectionView))
            return;

        for (var i:int = 0; i < sortFields.length; i++)
        {
            var sortField:ISortField = sortFields[i];
            if(sortField is IComplexSortField)
                break;
        }

        if(i < sortFields.length)
        {
            if(!ListCollectionView(dataProvider).complexFieldWatcher)
                ListCollectionView(dataProvider).complexFieldWatcher = new ComplexFieldChangeWatcher();
        }
        else
            ListCollectionView(dataProvider).complexFieldWatcher = null;
    }

    /**
     *  Sort the DataGrid by one or more columns, and refresh the display.
     *
     *  <p>If the <code>dataProvider</code> is an ICollectionView, then it's <code>sort</code> property is
     *  set to a value based on each column's <code>dataField</code>, <code>sortCompareFunction</code>,
     *  and <code>sortDescending</code> flag.
     *  Then, the data provider's <code>refresh()</code> method is called. </p>
     *
     *  <p>If the <code>dataProvider</code> is not an ICollectionView, then this method has no effect.</p>
     *
     *  <p>If isInteractive is true then a <code>GridSortEvent.SORT_CHANGING</code> is dispatched before the
     *  sort is applied.  Listeners can change modify the event to change the sort or cancel
     *  the event to cancel the sort.   If isInteractive is true and the sort is not cancelled, then a
     *  <code>GridSortEvent.SORT_CHANGE</code> event is dispatched after the dataProvider's sort has been
     *  updated.</p>
     *
     *  <p>If the sort has not be cancelled, the columnHeaderGroup's <code>visibleSortIndicatorIndices</code> is updated.</p>
     *
     *  @param columnIndices The indices of the columns by which to sort the <code>dataProvider</code>.
     *
     *  @param isInteractive If true, <code>GridSortEvent.SORT_CHANGING</code> and
     *  <code>GridSortEvent.SORT_CHANGE</code> events are dispatched.
     *
     *  @return <code>true</code> if the <code>dataProvider</code> was sorted with the provided
     *  column indicies.
     *
     *  @see spark.components.DataGrid#dataProvider
     *  @see spark.components.gridClasses.GridColumn#sortCompareFunction
     *  @see spark.components.gridClasses.GridColumn#sortDescending
     *  @see spark.components.gridClasses.GridColumn#sortField
     *  @see spark.components.GridColumnHeaderGroup#visibleSortIndicatorIndices
     *  @see spark.events.GridSortEvent
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function sortByColumns(columnIndices:Vector.<int>, isInteractive:Boolean=false):Boolean
    {
       const dataProvider:ICollectionView = this.dataProvider as ICollectionView;
        if (!dataProvider)
            return false;

        var sort:ISort = dataProvider.sort;
        if (sort)
            sort.compareFunction = null;
        else
            sort = new Sort();

        var sortFields:Array = createSortFields(columnIndices, sort.fields);
        if (!sortFields || (sortFields.length == 0))
            return false;

        var oldSortFields:Array = (dataProvider.sort) ? dataProvider.sort.fields : null;

        // Dispatch the "changing" event. If preventDefault() is called
        // on this event, the sort operation will be cancelled.  If columnIndices or
        // sortFields are changed, the new values will be used.
        if (isInteractive)
        {
            // This is a shallow copy which means only the pointers to the ISortField objects
            // are copied to the new Array, not the ISortField objects themselves.
            if (oldSortFields)
                oldSortFields = oldSortFields.concat();

            if (hasEventListener(GridSortEvent.SORT_CHANGING))
            {
                const changingEvent:GridSortEvent =
                    new GridSortEvent(GridSortEvent.SORT_CHANGING,
                        false, true,
                        columnIndices,
                        oldSortFields,  /* intended to be read-only but no way to enforce this */
                        sortFields);

                // The event was cancelled so don't sort.
                if (!dispatchEvent(changingEvent))
                    return false;

                // Update the sort columns since they might have changed.
                columnIndices = changingEvent.columnIndices;
                if (!columnIndices)
                    return false;

                // Update the new sort fields since they might have changed.
                sortFields = changingEvent.newSortFields;
                if (!sortFields)
                    return false;
            }
        }

        // Remove each old SortField that's not a member of the new sortFields Array
        // as a "styleClient" of this DataGrid.

        if (oldSortFields)
        {
            for each (var oldSortField:ISortField in oldSortFields)
            {
                var oldASC:IAdvancedStyleClient = oldSortField as IAdvancedStyleClient;
                if (!oldASC || (oldASC.styleParent != this) || (sortFields.indexOf(oldASC) != -1))
                    continue;
                removeStyleClient(oldASC);
            }
        }

        // Add new SortFields as "styleClients" of this DataGrid so that they
        // inherit this DataGrid's locale style.

        for each (var newSortField:ISortField in sortFields)
        {
            var newASC:IAdvancedStyleClient = newSortField as IAdvancedStyleClient;
            if (!newASC || (newASC.styleParent == this))
                continue;
            addStyleClient(newASC);
        }

        ensureComplexFieldsMonitoring(sortFields);

        sort.fields = sortFields;

        dataProvider.sort = sort;
        dataProvider.refresh();

        if (isInteractive)
        {
            // Dispatch the "change" event.
            if (hasEventListener(GridSortEvent.SORT_CHANGE))
            {
                const changeEvent:GridSortEvent =
                    new GridSortEvent(GridSortEvent.SORT_CHANGE,
                        false, true,
                        columnIndices,
                        oldSortFields, sortFields);
                dispatchEvent(changeEvent);
            }

            // Update the visible sort indicators.
            if (columnHeaderGroup)
                columnHeaderGroup.visibleSortIndicatorIndices = columnIndices;
        }

        return true;
    }

    /**
     *  @private
     *  Return an array of ISortFields, one per column.   If a matching sort field is found in 
     *  previousFields then it's used, otherwise a new sort field is created.  Each sort field's 
     *  sortDescending property is set to match its column's sortDescending property.
     */
    private function createSortFields(columnIndices:Vector.<int>, previousFields:Array):Array 
    {
        const fields:Array = []; // return value
        
        for each (var columnIndex:int in columnIndices)
        {
            var col:GridColumn = this.getColumnAt(columnIndex);

            if (!col || (!col.dataField && (col.labelFunction == null) && (col.sortCompareFunction == null)))
                return null;

            var sortField:ISortField = findSortField(col.dataField, previousFields);
            
            if (!sortField)
            {
                //Constructs a new sortField from the columns own sortField property.
                sortField = col.sortField;
            }
            else
            {
                sortField.descending = col.sortDescending;
            }

            fields.push(sortField);
        }
        
        return fields;
    }
    
    /**
     *  @private
     *  Finds a SortField using the provided dataField and returns it.
     *
     *  @param dataField The dataField of the column.
     *  @param fields The array of SortFields to search through.
     */
    private static function findSortField(dataField:String, fields:Array):ISortField
    {
        if (dataField == null)
            return null;
        
        for each (var field:ISortField in fields)
        {
            if (field.name == dataField)
                return field;
        }
        
        return null;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Private Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  @return True if there is an anchor position set.
     */    
    private function isAnchorSet():Boolean
    {
        if (!grid)
            return false;
        
        if (isRowSelectionMode())
            return grid.anchorRowIndex != -1;
        else
            return grid.anchorRowIndex != -1 && grid.anchorRowIndex != -1;
    }
    
    /**
     *  @private
     *  Toggle the selection and set the caret to rowIndex/columnIndex.
     * 
     *  @return True if the selection has changed.
     */
    private function toggleSelection(rowIndex:int, columnIndex:int):Boolean
    {
        var kind:String;
        
        if (isRowSelectionMode())
        { 
            if (grid.selectionContainsIndex(rowIndex))
                kind = GridSelectionEventKind.REMOVE_ROW;
            else if (selectionMode == GridSelectionMode.MULTIPLE_ROWS)
                kind = GridSelectionEventKind.ADD_ROW;
            else
                kind = GridSelectionEventKind.SET_ROW;
            
        }
        else if (isCellSelectionMode())
        {
            if (grid.selectionContainsCell(rowIndex, columnIndex))
                kind = GridSelectionEventKind.REMOVE_CELL;
            else if (selectionMode == GridSelectionMode.MULTIPLE_CELLS)
                kind = GridSelectionEventKind.ADD_CELL;
            else
                kind = GridSelectionEventKind.SET_CELL;
        }
        
        var success:Boolean = 
            commitInteractiveSelection(kind, rowIndex, columnIndex);
        
        // Update the caret if the selection was not cancelled.
        if (success)
            commitCaretPosition(rowIndex, columnIndex);
        
        return success;
    }
    
    /**
     *  @private
     *  Extends the selection from the anchor position to the given 'caret'
     *  position and updates the caret position.
     */
    private function extendSelection(caretRowIndex:int, 
                                     caretColumnIndex:int):Boolean
    {
        if (!isAnchorSet())
            return false;
        
        const startRowIndex:int = Math.min(grid.anchorRowIndex, caretRowIndex);
        const endRowIndex:int = Math.max(grid.anchorRowIndex, caretRowIndex);
        var success:Boolean;
        
        if (selectionMode == GridSelectionMode.MULTIPLE_ROWS)
        {
            success = commitInteractiveSelection(
                GridSelectionEventKind.SET_ROWS,
                startRowIndex, -1,
                endRowIndex - startRowIndex + 1, 0);
        }
        else if (selectionMode == GridSelectionMode.SINGLE_ROW)
        {
            // Can't extend the selection so move it to the caret position.
            success = commitInteractiveSelection(
                GridSelectionEventKind.SET_ROW, caretRowIndex, -1, 1, 0);                
        }
        else if (selectionMode == GridSelectionMode.MULTIPLE_CELLS)
        {
            const rowCount:int = endRowIndex - startRowIndex + 1;
            const startColumnIndex:int = 
                Math.min(grid.anchorColumnIndex, caretColumnIndex);
            const endColumnIndex:int = 
                Math.max(grid.anchorColumnIndex, caretColumnIndex); 
            const columnCount:int = endColumnIndex - startColumnIndex + 1;
            
            success = commitInteractiveSelection(
                GridSelectionEventKind.SET_CELL_REGION, 
                startRowIndex, startColumnIndex,
                rowCount, columnCount);
        }            
        else if (selectionMode == GridSelectionMode.SINGLE_CELL)
        {
            // Can't extend the selection so move it to the caret position.
            success = commitInteractiveSelection(
                GridSelectionEventKind.SET_CELL, 
                caretRowIndex, caretColumnIndex, 1, 1);                
        }
        
        // Update the caret.
        if (success)
            commitCaretPosition(caretRowIndex, caretColumnIndex);
        
        return success;
    }
    
    /**
     *  @private
     *  Sets the selection and updates the caret and anchor positions.
     */
    private function setSelectionAnchorCaret(rowIndex:int, columnIndex:int):Boolean
    {
        // click sets the selection and updates the caret and anchor 
        // positions.
        var success:Boolean;
        if (isRowSelectionMode())
        {
            // Select the row.
            success = commitInteractiveSelection(
                GridSelectionEventKind.SET_ROW, 
                rowIndex, columnIndex);
        }
        else if (isCellSelectionMode())
        {
            // Select the cell.
            success = commitInteractiveSelection(
                GridSelectionEventKind.SET_CELL, 
                rowIndex, columnIndex);
        }
        
        // Update the caret and anchor positions unless cancelled.
        if (success)
        {
            commitCaretPosition(rowIndex, columnIndex);
            grid.anchorRowIndex = rowIndex;
            grid.anchorColumnIndex = columnIndex; 
        }    
        
        return success;
    }
    
    /**
     *  @private
     *  Returns the new caret position based on the current caret position and 
     *  the navigationUnit as a Point, where x is the columnIndex and y is the 
     *  rowIndex.  Assures there is a valid caretPosition.
     */
    private function setCaretToNavigationDestination(navigationUnit:uint):CellPosition
    {
        var caretRowIndex:int = grid.caretRowIndex;
        var caretColumnIndex:int = grid.caretColumnIndex;
        
        const rowCount:int = dataProviderLength;
        const columnCount:int = columnsLength;
        
        const gridLayout:GridLayout = grid.layout as GridLayout;
        const centerGridView:GridView = gridLayout.centerGridView;
        const topGridView:GridView = gridLayout.topGridView;
        var caretGridView:GridView;
        
        switch (navigationUnit)
        {
            case NavigationUnit.LEFT: 
            {
                if (isCellSelectionMode())
                {
                    if (grid.caretColumnIndex > 0)
                        caretColumnIndex = grid.getPreviousVisibleColumnIndex(caretColumnIndex);
                }
                break;
            }
                
            case NavigationUnit.RIGHT:
            {
                if (isCellSelectionMode())
                {
                    if (grid.caretColumnIndex + 1 < columnCount)
                        caretColumnIndex = grid.getNextVisibleColumnIndex(caretColumnIndex);
                }
                break;
            } 
                
            case NavigationUnit.UP:
            {
                if (grid.caretRowIndex > 0)
                    caretRowIndex--;
                break; 
            }
                
            case NavigationUnit.DOWN:
            {
                if (grid.caretRowIndex + 1 < rowCount)
                    caretRowIndex++;
                break; 
            }
                
            case NavigationUnit.PAGE_UP:
            {
                // If the caret is below the first visible row, then just move the caret up to
                // the first visible row.   Otherwise scroll up far enough to put the caret row
                // at the top of the view.
                
                caretGridView = ((lockedRowCount > 0) && (caretRowIndex <= lockedRowCount)) ? topGridView : centerGridView;
                const firstVisibleRowIndex:int = caretGridView.gridViewLayout.getFirstFullyVisibleRowIndex();
                
                if (caretRowIndex > firstVisibleRowIndex)
                {
                    caretRowIndex = firstVisibleRowIndex;
                }
                else if (caretRowIndex >= lockedRowCount)
                {
                    // Attempt to synchronously scroll caretRowIndex to bottom of the view 
                    // and then reset the caretRowIndex to whatever row actually ends up at the top.
                    
                    const caretRowBounds:Rectangle = grid.getRowBounds(caretRowIndex);
                    const visibleBounds:Rectangle = centerGridView.gridViewLayout.getVisibleBounds();
                    const pageUpDelta:Number = visibleBounds.bottom - caretRowBounds.bottom;
                    grid.verticalScrollPosition -= pageUpDelta;
                    validateNow();
                    
                    caretRowIndex = centerGridView.gridViewLayout.getFirstFullyVisibleRowIndex();                    
                }
                
                break;
            }
                
            case NavigationUnit.PAGE_DOWN:
            {
                // If the caret is on the last locked row, move to the first unlocked row.  Otherwise:
                // If the caret is above the last visible row, then just move the caret to the last visible row.  
                // Otherwise scroll down far enough to position the caret row at the top of the grid view and 
                // then reset the caret to the new last fully visible row.
                
                caretGridView = ((lockedRowCount > 0) && (caretRowIndex < (lockedRowCount - 1))) ? topGridView : centerGridView;
                const lastVisibleRowIndex:int = caretGridView.gridViewLayout.getLastFullyVisibleRowIndex();
                
                if ((lockedRowCount > 0) && (rowCount > lockedRowCount) && (caretRowIndex == (lockedRowCount - 1)))
                {
                    caretRowIndex = lockedRowCount;
                }
                else if (caretRowIndex < lastVisibleRowIndex)
                {
                    caretRowIndex = lastVisibleRowIndex;
                }
                else if (caretRowIndex >= lockedRowCount)
                {
                    // Attempt to synchronously scroll caretRowIndex to the top of the view 
                    // and then reset the caretRowIndex to whatever row actually ends up at the bottom.
                    
                    grid.verticalScrollPosition = grid.getRowBounds(caretRowIndex).y;
                    validateNow();
                    
                    caretRowIndex = centerGridView.gridViewLayout.getLastFullyVisibleRowIndex();                    
                }
                
                break; 
            }
                
            case NavigationUnit.HOME:
            {
                caretRowIndex = 0;
                caretColumnIndex = isCellSelectionMode() ? grid.getNextVisibleColumnIndex(-1) : -1; 
                break;
            }
                
            case NavigationUnit.END:
            {
                caretRowIndex = rowCount - 1;
                caretColumnIndex = isCellSelectionMode() ? grid.getPreviousVisibleColumnIndex(columnCount) : -1;
                
                // The heights of any rows that have not been rendered yet are
                // estimated.  Force them to draw so the heights are accurate.
                // TBD: is there a better way to do this?
                grid.verticalScrollPosition = grid.contentHeight;
                validateNow();
                if (grid.contentHeight != grid.verticalScrollPosition)
                {
                    grid.verticalScrollPosition = grid.contentHeight;
                    validateNow();
                }
                break;
            }
                
            default: 
            {
                return null;
            }
        }
        
        return new CellPosition(caretRowIndex, caretColumnIndex);
    }
    
    /**
     *  @copy spark.components.Grid#ensureCellIsVisible()
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function ensureCellIsVisible(rowIndex:int, columnIndex:int = -1):void
    {
        if (grid)
            grid.ensureCellIsVisible(rowIndex, columnIndex);
    }
    
    /**
     *  @private
     * 
     *  Adjusts the caret and the selection based on what keystroke is used
     *  in combination with a ctrl/cmd key or a shift key.  Returns false
     *  if the selection was not changed.
     */
    protected function adjustSelectionUponNavigation(event:KeyboardEvent):Boolean
    {
        // Some unrecognized key stroke was entered, return. 
        if (!NavigationUnit.isNavigationUnit(event.keyCode))
            return false; 
        
        // If rtl layout, need to swap Keyboard.LEFT and Keyboard.RIGHT.
        var navigationUnit:uint = mapKeycodeForLayoutDirection(event);
        
        const newPosition:CellPosition = setCaretToNavigationDestination(navigationUnit);
        if (!newPosition)
            return false;
        
        // Cancel so another component doesn't handle this event.
        event.preventDefault(); 
        
        var selectionChanged:Boolean = false;
        
        if (event.shiftKey)
        {
            // The shift key-nav key combination extends the selection and 
            // updates the caret.
            selectionChanged = 
                extendSelection(newPosition.rowIndex, newPosition.columnIndex);
        }
        else if (event.ctrlKey)
        {
            // If its a ctrl/cmd key-nav key combination, there is nothing
            // more to do then set the caret.
            commitCaretPosition(newPosition.rowIndex, newPosition.columnIndex);
        }
        else
        {
            // Select the current row/cell.
            setSelectionAnchorCaret(newPosition.rowIndex, newPosition.columnIndex);
        }
        
        // Ensure this position is visible.
        ensureCellIsVisible(newPosition.rowIndex, newPosition.columnIndex);
        
        return true;
    }
    
    /**
     *  @private
     * 
     *  Returns true if committing the given selection operation would change
     *  the current selection.
     */
    private function doesChangeCurrentSelection(
        selectionEventKind:String, 
        selectionChange:CellRegion):Boolean
    {
        var changesSelection:Boolean;
        
        const rowIndex:int = selectionChange.rowIndex;
        const columnIndex:int = selectionChange.columnIndex;
        const rowCount:int = selectionChange.rowCount;
        const columnCount:int = selectionChange.columnCount;
        
        switch (selectionEventKind)
        {
            case GridSelectionEventKind.SET_ROW:
            {
                changesSelection = 
                    !selectionContainsOnlyIndex(rowIndex);
                break;
            }
            case GridSelectionEventKind.ADD_ROW:
                
            {
                changesSelection = 
                    !grid.selectionContainsIndex(rowIndex);
                break;
            }
                
            case GridSelectionEventKind.REMOVE_ROW:
            {
                changesSelection = requireSelection ?
                    !selectionContainsOnlyIndex(rowIndex) :
                    grid.selectionContainsIndex(rowIndex);
                break;
            }
                
            case GridSelectionEventKind.SET_ROWS:
            {
                changesSelection = 
                    !selectionContainsOnlyIndices(selectionChange);
                break;
            }
                
            case GridSelectionEventKind.SET_CELL:
            {
                changesSelection = 
                    !selectionContainsOnlyCell(rowIndex, columnIndex);
                break;
            }
                
            case GridSelectionEventKind.ADD_CELL:
            {
                changesSelection = 
                    !grid.selectionContainsCell(rowIndex, columnIndex);
                break;
            }
                
            case GridSelectionEventKind.REMOVE_CELL:
            {
                changesSelection = requireSelection ?
                    !selectionContainsOnlyCell(rowIndex, columnIndex) :                  
                    grid.selectionContainsCell(rowIndex, columnIndex);
                break;
            }
                
            case GridSelectionEventKind.SET_CELL_REGION:
            {
                changesSelection = 
                    !selectionContainsOnlyCellRegion(
                        rowIndex, columnIndex, rowCount, columnCount);
                break;
            }
                
            case GridSelectionEventKind.SELECT_ALL:
            {
                changesSelection = true;
                break;
            }
        }
        
        return changesSelection;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Grid event handlers
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  Updating the hover is disabled if the mouse button was depressed
     *  while not over the grid.  The common case for this is while 
     *  scrolling.  While the scroll thumb is depressed don't want the 
     *  hover updated if the mouse drifts into the grid.
     */
    protected function grid_rollOverHandler(event:GridEvent):void
    {
        if (event.isDefaultPrevented())
            return;
        
        // The related object is the object that was previously under
        // the pointer.
        if (event.buttonDown && event.relatedObject != grid)
            updateHoverOnRollOver = false;
        
        grid.hoverRowIndex = updateHoverOnRollOver ? event.rowIndex : -1;
        grid.hoverColumnIndex = updateHoverOnRollOver ? event.columnIndex : -1;
        
        event.updateAfterEvent();        
    }
    
    /**
     *  @private
     *  If the mouse button is depressed while outside of the grid, the hover 
     *  indicator is not enabled again until GRID_MOUSE_UP or GRID_ROLL_OUT. 
     */
    protected function grid_rollOutHandler(event:GridEvent):void
    {
        if (event.isDefaultPrevented())
            return;
        
        grid.hoverRowIndex = -1;
        grid.hoverColumnIndex = -1;
        
        updateHoverOnRollOver = true;
        event.updateAfterEvent();
    }
    
    /**
     *  @private
     *  If the mouse button is depressed while outside of the grid, the hover 
     *  indicator is not enabled again until GRID_MOUSE_UP or GRID_ROLL_OUT. 
     */
    protected function grid_mouseUpHandler(event:GridEvent):void
    {
        if (event.isDefaultPrevented())
            return;
        
        if (!updateHoverOnRollOver)
        {
            grid.hoverRowIndex = event.rowIndex;
            grid.hoverColumnIndex = event.columnIndex;
            updateHoverOnRollOver = true;
        }
    }
    
    /**
     *  @private
     */
    protected function grid_mouseDownHandler(event:GridEvent):void
    {
        if (event.isDefaultPrevented())
            return;
        
        const isCellSelection:Boolean = isCellSelectionMode();
        
        const rowIndex:int = event.rowIndex;
        const columnIndex:int = isCellSelection ? event.columnIndex : -1;
        
        // Clicked on empty place in grid.  Don't change selection or caret
        // position.
        if (rowIndex == -1 || isCellSelection && columnIndex == -1)
            return;


        if (event.ctrlKey)
        {
            // ctrl-click toggles the selection and updates caret and anchor.
            if (!toggleSelection(rowIndex, columnIndex))
                return;
            
            grid.anchorRowIndex = rowIndex;
            grid.anchorColumnIndex = columnIndex;
        }
        else
        {
            if (event.shiftKey)
            {
                // shift-click extends the selection and updates the caret.
                if  (grid.selectionMode == GridSelectionMode.MULTIPLE_ROWS || grid.selectionMode == GridSelectionMode.MULTIPLE_CELLS)
                {    
                    if (!extendSelection(rowIndex, columnIndex))
                        return;
                }
            }
            else
            {
                // click sets the selection and updates the caret and anchor positions.
                setSelectionAnchorCaret(rowIndex, columnIndex);
            }
        }


        if (dragEnabled && isRowSelectionMode() && selectionContainsIndex(rowIndex))
        {
            pendingSelectionOnMouseUp = true;
        }
        
        // If selection is pending on mouse up then we have just moused down on
        // an item, part of an already commited selection.
        // However if we moused down on an item that's not currently selected,
        // we must commit the selection before trying to start dragging since
        // listeners may prevent the item from being selected.
        if (!pendingSelectionOnMouseUp)
            validateProperties();
        
        mouseDownPoint = event.target.localToGlobal(new Point(event.localX, event.localY));
        mouseDownObject = event.target as DisplayObject;
        mouseDownRowIndex = rowIndex;
        mouseDownColumnIndex = columnIndex;
        
        var listenForDrag:Boolean = (dragEnabled && 
            getStyle("interactionMode") == InteractionMode.MOUSE && selectedIndices && 
            this.selectedIndices.indexOf(rowIndex) != -1);
        // Handle any drag gestures that may have been started
        if (listenForDrag)
        {
            // Listen for GRID_MOUSE_DRAG.
            // The user may have cliked on the item renderer close
            // to the edge of the list, and we still want to start a drag
            // operation if they move out of the list.
            grid.addEventListener(GridEvent.GRID_MOUSE_DRAG, grid_mouseDragHandler);
        }
        
        if (pendingSelectionOnMouseUp || listenForDrag)
        {
            // FIXME (dloverin): When dragging a proxy in an untrusted 
            // child application the cursor does not follow drag proxy.
            
            // FIXME (dloverin): The listener on the sandbox root can be removed when:
            // 1. MouseEventUtil.addDownDragUpListeners() dispatches
            //    a MOUSE_UP_SOMEWHERE.
            // 2. Grid.grid_mouseDownDragUpHandler() changes its parameter from
            //    a MouseEvent to an event so a MOUSE_UP_SOMEWHERE event does 
            //    not cause an RTE. Grid can then handle the MOUSE_UP_SOMEWHERE
            //    event by dispatching a MOUSE_UP or aGRID_MOUSE_UP_SOMEWHERE 
            //    event.
            systemManager.getSandboxRoot().addEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, sandbox_mouseUpHandler, false, 0, true);
        }
        
    }
    
    /**
     *  @private
     *  Redispatch the grid's "caretChange" event.
     */
    protected function grid_caretChangeHandler(event:GridCaretEvent):void
    {
        if (hasEventListener(GridCaretEvent.CARET_CHANGE))
            dispatchEvent(event);
    }
    
    /**
     *  @private
     *  Redispatch the grid's "valueCommit" event.
     */
    protected function grid_valueCommitHandler(event:FlexEvent):void
    {
        if (hasEventListener(FlexEvent.VALUE_COMMIT))
            dispatchEvent(event);
    }
    
    /**
     *  @private
     */
    private function grid_invalidateDisplayListHandler(event:Event):void
    {
        // invalidate all IDataGridElements
        if (columnHeaderGroup && grid.isInvalidateDisplayListReason("horizontalScrollPosition"))
            columnHeaderGroup.invalidateDisplayList();
    }
    
    /**
     *  @private
     */
    private function grid_invalidateSizeHandler(event:Event):void
    {
        // invalidate all IDataGridElements
        if (columnHeaderGroup)
            columnHeaderGroup.invalidateSize();
    }
    
    /**
     *  @private
     */
    private function grid_gridViewsChangedHandler(event:Event):void
    {
        if (columnHeaderGroup)
            columnHeaderGroup.configureGridColumnHeaderViews();
    }   
    
    //--------------------------------------------------------------------------
    //
    //  Header event handlers
    //
    //--------------------------------------------------------------------------  
    
    private var stretchCursorID:int = CursorManager.NO_CURSOR;
    private var resizeColumn:GridColumn = null;
    private var resizeAnchorX:Number = NaN;
    private var resizeColumnWidth:Number = NaN;
    private var nextColumn:GridColumn = null;  // RTL layout only
    private var nextColumnWidth:Number = NaN;  // RTL layout only
    
    /**
     *  @private
     *  Flip the specified column's sortDescending flag and and sort the dataProvider.   If 
     *  isMultiColumnSort is true, add the column to the set of columns being sorted (that's
     *  columnHeaderGroup.visibleSortIndicatorIndices) otherwise just sort per the specified column.
     * 
     *  If the sort was possible and was not cancelled (see sortByColumns()) then set the 
     *  columnHeaderGroup's selectedColumnIndex and return true, otherwise return false.
     */
    private function interactiveSortByColumns(column:GridColumn, isMultiColumnSort:Boolean):Boolean
    {
        if (!enabled || !sortableColumns || !column || !column.sortable || !columnHeaderGroup)
            return false;
                
        const columnIndex:int = column.columnIndex;
        const currentSortColumnIndices:Vector.<int> = columnHeaderGroup.visibleSortIndicatorIndices;
        const reverseSort:Boolean = currentSortColumnIndices.indexOf(columnIndex) != -1;        
        var sortColumnIndices:Vector.<int>;
        
        if (isMultiColumnSort && multiColumnSortingEnabled)
        {
            sortColumnIndices = currentSortColumnIndices;
            if (!reverseSort)
                sortColumnIndices.push(columnIndex);
        }
        else
        {
            sortColumnIndices = new <int>[columnIndex];
        }
        
        if (reverseSort)
            column.sortDescending = !column.sortDescending;
        
        if (!sortByColumns(sortColumnIndices, true) && reverseSort)
        {
            column.sortDescending = !column.sortDescending;    // sort was cancelled 
            return false;
        }
        
        columnHeaderGroup.selectedColumnIndex = column.columnIndex;
        
        return true;
    }
    
    /**
     *  @private
     */
    protected function columnHeaderGroup_clickHandler(event:GridEvent):void
    {
       interactiveSortByColumns(event.column, event.ctrlKey);
    }
    
    /**
     *  @private
     */
    protected function columnHeaderGroup_rollOverHandler(event:GridEvent):void
    {
        if (resizeColumn || !enabled)
            return;
        
        columnHeaderGroup.hoverColumnIndex = event.columnIndex;
    }    
    
    /**
     *  @private
     */
    protected function columnHeaderGroup_rollOutHandler(event:GridEvent):void
    {
        if (!enabled)
            return;
        
        columnHeaderGroup.hoverColumnIndex = -1;       
    }
    
    /**
     *  @private
     */
    protected function separator_mouseDownHandler(event:GridEvent):void
    {
        const column:GridColumn = event.column;
        if (!enabled || !grid.resizableColumns || !column || !column.resizable)
            return;
        
        resizeColumn = event.column;
        resizeAnchorX = event.localX;
        resizeColumnWidth = grid.getColumnWidth(resizeColumn.columnIndex);
        
        // If we're laying out RTL then dragging to the left - which increases
        // a column's width - and the Grid's width is unconstrained, then only
        // allow the column's width to grow to the extent that the adjacent 
        // (next) column can shrink. 
        
        if (isNaN(explicitWidth) && (layoutDirection == LayoutDirection.RTL))
        {
            const nextColumnIndex:int = grid.getNextVisibleColumnIndex(resizeColumn.columnIndex);
            nextColumn = getColumnAt(nextColumnIndex);
            nextColumnWidth = Math.ceil(grid.getColumnWidth(nextColumnIndex));           
        }
        else
        {
            nextColumn = null;
            nextColumnWidth = NaN;
        }
        
        // Give all of the columns to the left of this one an explicit so that resizing
        // this column doesn't change their width and, consequently, this column's location.
        
        const resizeColumnIndex:int = resizeColumn.columnIndex;
        for (var columnIndex:int = 0; columnIndex < resizeColumnIndex; columnIndex++)
        {
            var gc:GridColumn = getColumnAt(columnIndex);
            if (gc.visible && isNaN(gc.width))
                gc.width = grid.getColumnWidth(columnIndex);
        }
    }    
    
    /**
     *  @private
     */
    protected function separator_mouseDragHandler(event:GridEvent):void
    {
        if (!resizeColumn)
            return;
        
        const widthDelta:Number = event.localX - resizeAnchorX;
        const minWidth:Number = isNaN(resizeColumn.minWidth) ? 0 : resizeColumn.minWidth;
        const maxWidth:Number = resizeColumn.maxWidth;
        var newWidth:Number = Math.ceil(resizeColumnWidth + widthDelta);
        
        // Layout is RTL (see sparator_mouseDownHandler). Make sure that the
        // next column's width can shrink as much as the resizeColumn is growing,
        // or vice versa.
        
        if (nextColumn)
        {
            const nextMinWidth:Number = isNaN(nextColumn.minWidth) ? 0 : nextColumn.minWidth;
            
            if (Math.ceil(nextColumnWidth - widthDelta) <= nextMinWidth)
                return;
            if (Math.ceil(resizeColumnWidth + widthDelta) <= minWidth)
                return;
            
            nextColumn.width = nextColumnWidth - widthDelta;
        }
        
        newWidth = Math.max(newWidth, minWidth);
        if (!isNaN(maxWidth))
            newWidth = Math.min(newWidth, maxWidth);
        
        resizeColumn.width = newWidth;
        validateNow();  // smooth out the drag
        event.updateAfterEvent();
    } 
    
    /**
     *  @private
     */
    protected function separator_mouseUpHandler(event:GridEvent):void
    {
        if (!resizeColumn)
            return;
        
        resizeColumn = null;
        cursorManager.removeCursor(stretchCursorID);        
    }     
    
    /**
     *  @private
     */
    protected function separator_rollOverHandler(event:GridEvent):void
    {
        const column:GridColumn = event.column;
        if (resizeColumn || !enabled || !grid.resizableColumns || !column || !column.resizable)
            return;
        
        var stretchCursorClass:Class = getStyle("stretchCursor") as Class;
        if (stretchCursorClass)
            stretchCursorID = cursorManager.setCursor(stretchCursorClass, CursorManagerPriority.HIGH, 0, 0);
    }
    
    /**
     *  @private
     */
    protected function separator_rollOutHandler(event:GridEvent):void
    {
        if (!enabled || resizeColumn)
            return;
        
        cursorManager.removeCursor(stretchCursorID);
    }     
    
    //--------------------------------------------------------------------------
    //
    //  DataGrid event handlers
    //
    //--------------------------------------------------------------------------  
    
    /**
     *  @private
     *  The UIComponent's focusInHandler and focusOutHandler draw the
     *  focus.  This handler exists only when there is a caretIndicator part.
     */
    protected function dataGrid_focusHandler(event:FocusEvent):void
    {
        if (!grid)
            return;
        
        const isFocusIn:Boolean = event.type == FocusEvent.FOCUS_IN;
        const isFocusOut:Boolean = event.type == FocusEvent.FOCUS_OUT; 
        
        if (isOurFocus(DisplayObject(event.target)))
            grid.showCaret = isFocusIn && (selectionMode != GridSelectionMode.NONE);
        
        if (isFocusIn)
            internalFocusOwner = GRID_FOCUS_OWNER;
        else if (isFocusOut)
            internalFocusOwner = NO_FOCUS_OWNER;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Drag methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  The default handler for the <code>dragStart</code> event.
     *
     *  @param event The DragEvent object.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function dragStartHandler(event:DragEvent):void
    {
        if (event.isDefaultPrevented())
            return;
        
        var dragSource:DragSource = new DragSource();
        addDragData(dragSource);
        DragManager.doDrag(this, 
            dragSource, 
            event, 
            createDragIndicator(), 
            0 /*xOffset*/, 
            0 /*yOffset*/, 
            0.5 /*imageAlpha*/, 
            dragMoveEnabled);
    }
    
    /**
     *  @private
     *  Used to sort the selected indices during drag and drop operations.
     */
    private function compareValues(a:int, b:int):int
    {
        return a - b;
    } 
    
    /**
     *  @private
     *  Handles <code>DragEvent.DRAG_COMPLETE</code> events.  This method
     *  removes the items from the data provider.
     *
     *  @param event The DragEvent object.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function dragCompleteHandler(event:DragEvent):void
    {
        if (event.isDefaultPrevented())
            return;
        
        // Remove the dragged items only if they were drag moved to
        // a different list. If the items were drag moved to this
        // list, the reordering was already handles in the 
        // DragEvent.DRAG_DROP listener.
        if (!dragMoveEnabled ||
            event.action != DragManager.MOVE || 
            event.relatedObject == this)
            return;
        
        // Clear the selection, but remember which items were moved
        var movedIndices:Vector.<int> = selectedIndices;
        selectedIndices = new Vector.<int>();
        validateProperties(); // To commit the selection
        
        // Remove the moved items
        movedIndices.sort(compareValues);
        var count:int = movedIndices.length;
        for (var i:int = count - 1; i >= 0; i--)
        {
            dataProvider.removeItemAt(movedIndices[i]);
        }
    }
    
    /**
     *  Creates an instance of a class that is used to display the visuals
     *  of the dragged items during a drag and drop operation.
     *  The default <code>DragEvent.DRAG_START</code> handler passes the
     *  instance to the <code>DragManager.doDrag()</code> method.
     *
     *  @return The IFlexDisplayObject representing the drag indicator.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function createDragIndicator():IFlexDisplayObject
    {
        var dragIndicator:IFlexDisplayObject;
        var dragIndicatorClass:Class = Class(getStyle("dragIndicatorClass"));
        if (dragIndicatorClass)
        {
            dragIndicator = new dragIndicatorClass();
            if (dragIndicator is IVisualElement)
                IVisualElement(dragIndicator).owner = this;
        }
        
        return dragIndicator;
    }
    
    /**
     *  Adds the selected items to the DragSource object as part of
     *  a drag-and-drop operation.
     *  Override this method to add other data to the drag source.
     * 
     *  @param ds The DragSource object to which to add the data.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function addDragData(dragSource:DragSource):void
    {
        dragSource.addHandler(copySelectedItemsForDragDrop, "itemsByIndex");
        
        // Calculate the index of the focus item within the vector
        // of ordered items returned for the "itemsByIndex" format.
        var caretIndex:int = 0;
        var draggedIndices:Vector.<int> = selectedIndices;
        var count:int = draggedIndices.length;
        for (var i:int = 0; i < count; i++)
        {
            if (mouseDownRowIndex > draggedIndices[i])
                caretIndex++;
        }
        dragSource.addData(caretIndex, "caretIndex");
    }
    
    /**
     *  @private
     */
    private function copySelectedItemsForDragDrop():Vector.<Object>
    {
        // Copy the vector so that we don't modify the original
        // since selectedIndices returns a reference.
        var draggedIndices:Vector.<int> = selectedIndices.slice(0, selectedIndices.length);
        var result:Vector.<Object> = new Vector.<Object>(draggedIndices.length);
        
        // Sort in the order of the data source
        draggedIndices.sort(compareValues);
        
        // Copy the items
        var count:int = draggedIndices.length;
        for (var i:int = 0; i < count; i++)
            result[i] = dataProvider.getItemAt(draggedIndices[i]);  
        return result;
    }
    
    /**
     *  @private
     *  Handles <code>MouseEvent.MOUSE_MOVE</code> events from any mouse
     *  targets contained in the list including the renderers.  This method
     *  watches for a gesture that constitutes the beginning of a
     *  drag drop and send a <code>DragEvent.DRAG_START</code> event.
     *  It also checks to see if the mouse is over a non-target area of a
     *  renderer so that Flex can try to make it look like that renderer was 
     *  the target.
     *
     *  @param event The MouseEvent object.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function grid_mouseDragHandler(event:MouseEvent):void
    {
        if (!mouseDownPoint || !dragEnabled)
            return;
        
        var pt:Point = new Point(event.localX, event.localY);
        pt = DisplayObject(event.target).localToGlobal(pt);
        
        const DRAG_THRESHOLD:int = 5;
        
        if (Math.abs(mouseDownPoint.x - pt.x) > DRAG_THRESHOLD ||
            Math.abs(mouseDownPoint.y - pt.y) > DRAG_THRESHOLD)
        {
            var dragEvent:DragEvent = new DragEvent(DragEvent.DRAG_START);
            dragEvent.dragInitiator = this;
            
            var localMouseDownPoint:Point = this.globalToLocal(mouseDownPoint);
            
            dragEvent.localX = localMouseDownPoint.x;
            dragEvent.localY = localMouseDownPoint.y;
            dragEvent.buttonDown = true;
            
            // We're starting a drag operation, remove the handlers
            // that are monitoring the mouse move, we don't need them anymore:
            dispatchEvent(dragEvent);
            
            var gridEvent:GridEvent = new GridEvent(GridEvent.GRID_MOUSE_UP, false, false, event.localX, event.localY,
                event.relatedObject, event.ctrlKey, event.altKey, event.shiftKey, event.buttonDown, event.delta);
            
            // Finally, remove the mouse handlers
            removeMouseHandlersForDragStart(gridEvent);
        }
    }
    
    private function removeMouseHandlersForDragStart(event:GridEvent):void
    {
        // If dragging failed, but we had a pending selection, commit it here
        if (pendingSelectionOnMouseUp && !DragManager.isDragging)
        {
            const rowIndex:int = mouseDownRowIndex;
            const columnIndex:int = mouseDownColumnIndex;
            
            if (event.ctrlKey)
            {
                // ctrl-click toggles the selection and updates caret and anchor.
                if (!toggleSelection(rowIndex, columnIndex))
                    return;
                
                grid.anchorRowIndex = rowIndex;
                grid.anchorColumnIndex = columnIndex;
            }
            else if (event.shiftKey)
            {
                // shift-click extends the selection and updates the caret.
                if  (grid.selectionMode == GridSelectionMode.MULTIPLE_ROWS || 
                    grid.selectionMode == GridSelectionMode.MULTIPLE_CELLS)
                {    
                    if (!extendSelection(rowIndex, columnIndex))
                        return;
                }
            }
            else
            {
                // click sets the selection and updates the caret and anchor 
                // positions.
                setSelectionAnchorCaret(rowIndex, columnIndex);
            }           
        }
        
        // Always clean up the flag, even if currently dragging.
        pendingSelectionOnMouseUp = false;
        
        mouseDownPoint = null;
        mouseDownObject = null;
        mouseDownRowIndex = -1;
        mouseDownColumnIndex = -1;
        
        grid.removeEventListener(GridEvent.GRID_MOUSE_DRAG, grid_mouseDragHandler);
        systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, sandbox_mouseUpHandler, false);
    }
    
    /**
     *  @private
     *  Handles <code>SandboxMouseEvent.MOUSE_UP_SOMEWHERE</code> events.
     *
     *  @param event The SandboxMouseEvent object.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function sandbox_mouseUpHandler(event:SandboxMouseEvent):void
    {
        var sandboxMouseEvent:SandboxMouseEvent = SandboxMouseEvent(event);
        var gridEvent:GridEvent = new GridEvent(GridEvent.GRID_MOUSE_UP, false, false, NaN, NaN, null,
            sandboxMouseEvent.ctrlKey, sandboxMouseEvent.altKey, sandboxMouseEvent.shiftKey, 
            sandboxMouseEvent.buttonDown, 0);
        
        removeMouseHandlersForDragStart(gridEvent);
    }
    
    
    //--------------------------------------------------------------------------
    //
    //  Drop methods
    //
    //--------------------------------------------------------------------------
    
    /**
    *  @private
    *  Used in drag n drop methods for drop location / drop indicators.
    */
    private var _gridViewLayout:GridViewLayout = null;


    /**
     *  Creates and instance of the dropIndicator class that is used to
     *  display the visuals of the drop location during a drag and drop
     *  operation. The instance is set in the layout's 
     *  <code>dropIndicator</code> property.
     *
     *  <p>If you override the <code>dragEnter</code> event handler, 
     *  and call <code>preventDefault()</code> so that the default handler does not execute, 
     *  call <code>createDropIndicator()</code> to create the drop indicator.</p>
     * 
     *  @return Returns the dropIndicator that was set in the layout.
     *
     *  @see #destroyDropIndicator
     *
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function createDropIndicator():DisplayObject
    {
        // Do we have a drop indicator already?
        if (_gridViewLayout.dropIndicator)
            return _gridViewLayout.dropIndicator;


        var dropIndicatorInstance:DisplayObject;

        if (dropIndicator)
        {
            dropIndicatorInstance = DisplayObject(createDynamicPartInstance("dropIndicator"));
        }
        else
        {
            var dropIndicatorClass:Class = Class(getStyle("dropIndicatorSkin"));
            if (dropIndicatorClass)
                dropIndicatorInstance = new dropIndicatorClass();
        }

        if (dropIndicatorInstance is IVisualElement)
            IVisualElement(dropIndicatorInstance).owner = this;
        
        // Set it in the layout
        _gridViewLayout.dropIndicator = dropIndicatorInstance;

        return dropIndicatorInstance;
    }
    
    /**
     *  Releases the <code>dropIndicator</code> instance that is currently set in the layout.
     *
     *  <p>If you override the <code>dragExit</code> event handler, 
     *  and call <code>preventDefault()</code> so that the default handler does not execute, 
     *  call <code>destroyDropIndicator()</code> to delete the drop indicator.</p>
     *
     *  @return Returns the dropIndicator that was removed. 
     * 
     *  @see #createDropIndicator
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    public function destroyDropIndicator():DisplayObject
    {
        var dropIndicatorInstance:DisplayObject = _gridViewLayout.dropIndicator;

        if (!dropIndicatorInstance)
            return null;
        
        // Release the reference from the layout
        _gridViewLayout.dropIndicator = null;
        
        // Release it if it's a dynamic skin part
        var count:int = numDynamicParts("dropIndicator");

        for (var i:int = 0; i < count; i++)
        {
            if (dropIndicatorInstance == getDynamicPartAt("dropIndicator", i))
            {
                // This was a dynamic part, remove it now:
                removeDynamicPartInstance("dropIndicator", dropIndicatorInstance);
                break;
            }
        }

        return dropIndicatorInstance;
    }
    
    /**
     *  @private
     *  Handles <code>DragEvent.DRAG_ENTER</code> events.  This method
     *  determines if the DragSource object contains valid elements and uses
     *  the <code>DragManager.showDropFeedback()</code> method to set up the 
     *  UI feedback as well as the layout's <code>showDropIndicator()</code>
     *  method to display the drop indicator and initiate drag scrolling.
     *
     *  @param event The DragEvent object.
     * 
     *  @see spark.layouts.LayoutBase#showDropIndicator
     *  @see spark.layouts.LayoutBase#hideDropIndicator
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function dragEnterHandler(event:DragEvent):void
    {
        if (event.isDefaultPrevented())
            return;


        if (!_gridViewLayout)
        {
            //Store a current gridview layout.
            _gridViewLayout = (grid.layout as GridLayout).centerGridView.layout as GridViewLayout;
        }


        var dropLocation:DropLocation = _gridViewLayout.calculateDropLocation(event);

        if (dropLocation)
        {
            DragManager.acceptDragDrop(this);
            
            // Create the dropIndicator instance. The layout will take care of
            // parenting, sizing, positioning and validating the dropIndicator.
            createDropIndicator();
            
            // Show focus
            drawFocusAnyway = true;
            drawFocus(true);
            
            // Notify manager we can drop
            DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE);
            
            // Show drop indicator
            _gridViewLayout.showDropIndicator(dropLocation);
        }
        else
        {
            DragManager.showFeedback(DragManager.NONE);
        }
    }
    
    /**
     *  @private
     *  Handles <code>DragEvent.DRAG_OVER</code> events. This method
     *  determines if the DragSource object contains valid elements and uses
     *  the <code>showDropFeedback()</code> method to set up the UI feedback 
     *  as well as the layout's <code>showDropIndicator()</code> method
     *  to display the drop indicator and initiate drag scrolling.
     *
     *  @param event The DragEvent object.
     *  
     *  @see spark.layouts.LayoutBase#showDropIndicator
     *  @see spark.layouts.LayoutBase#hideDropIndicator
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function dragOverHandler(event:DragEvent):void
    {
        if (event.isDefaultPrevented())
            return;


        var dropLocation:DropLocation = _gridViewLayout.calculateDropLocation(event);

        if (dropLocation)
        {
            // Show focus
            drawFocusAnyway = true;
            drawFocus(true);
            
            // Notify manager we can drop
            DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE);
            
            // Show drop indicator
            _gridViewLayout.showDropIndicator(dropLocation);
        }
        else
        {
            // Hide if previously showing
            _gridViewLayout.hideDropIndicator();
            
            // Hide focus
            drawFocus(false);
            drawFocusAnyway = false;
            
            // Notify manager we can't drop
            DragManager.showFeedback(DragManager.NONE);
        }
    }
    
    /**
     *  @private
     *  Handles <code>DragEvent.DRAG_EXIT</code> events. This method hides
     *  the UI feedback by calling the <code>hideDropFeedback()</code> method
     *  and also hides the drop indicator by calling the layout's 
     *  <code>hideDropIndicator()</code> method.
     *
     *  @param event The DragEvent object.
     *  
     *  @see spark.layouts.LayoutBase#showDropIndicator
     *  @see spark.layouts.LayoutBase#hideDropIndicator
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function dragExitHandler(event:DragEvent):void
    {
        if (event.isDefaultPrevented())
            return;

        // Hide if previously showing
        _gridViewLayout.hideDropIndicator();
        
        // Hide focus
        drawFocus(false);
        drawFocusAnyway = false;
        
        // Destroy the dropIndicator instance
        destroyDropIndicator();
    }
    
    /**
     *  @private
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    private function touchInteractionStartHandler(event:TouchInteractionEvent):void
    {
        // cancel actual selection
        mouseDownRowIndex = -1;
        mouseDownColumnIndex = -1;
        mouseDownObject = null;
        mouseDownPoint = null;
        pendingSelectionOnMouseUp = false;
    }
    
    /**
     *  @private
     *  Handles <code>DragEvent.DRAG_DROP events</code>. This method  hides
     *  the drop feedback by calling the <code>hideDropFeedback()</code> method.
     *
     *  <p>If the action is a <code>COPY</code>, 
     *  then this method makes a deep copy of the object 
     *  by calling the <code>ObjectUtil.copy()</code> method, 
     *  and replaces the copy's <code>uid</code> property (if present) 
     *  with a new value by calling the <code>UIDUtil.createUID()</code> method.</p>
     * 
     *  @param event The DragEvent object.
     *
     *  @see mx.utils.ObjectUtil
     *  @see mx.utils.UIDUtil
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function dragDropHandler(event:DragEvent):void
    {
        if (event.isDefaultPrevented())
            return;


        // Hide the drop indicator
		_gridViewLayout.hideDropIndicator();
        destroyDropIndicator();
        
        // Hide focus
        drawFocus(false);
        drawFocusAnyway = false;
        
        // Get the dropLocation
		var dropLocation:DropLocation = _gridViewLayout.calculateDropLocation(event);

        if (!dropLocation)
            return;
        
        // Find the dropIndex
        var dropIndex:int = dropLocation.dropIndex;
        
        // Make sure the manager has the appropriate action
        DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE);
        
        var dragSource:DragSource = event.dragSource;
        var items:Vector.<Object> = dragSource.dataForFormat("itemsByIndex") as Vector.<Object>;
        
        var caretIndex:int = -1;
        if (dragSource.hasFormat("caretIndex"))
            caretIndex = event.dragSource.dataForFormat("caretIndex") as int;
        
        // Clear the selection first to avoid extra work while adding and removing items.
        // We will set a new selection further below in the method.
        var indices:Vector.<int> = selectedIndices; 
        clearSelection();
        validateProperties(); // To commit the selection
        
        // If we are reordering the list, remove the items now,
        // adjusting the dropIndex in the mean time.
        // If the items are drag moved to this list from a different list,
        // the drag initiator will remove the items when it receives the
        // DragEvent.DRAG_COMPLETE event.
        if (dragMoveEnabled &&
            event.action == DragManager.MOVE &&
            event.dragInitiator == this)
        {
            // Remove the previously selected items
            indices.sort(compareValues);
            for (var i:int = indices.length - 1; i >= 0; i--)
            {
                if (indices[i] < dropIndex)
                    dropIndex--;
                dataProvider.removeItemAt(indices[i]);
            }
        }
        
        // Drop the items at the dropIndex
        var newSelection:Vector.<int> = new Vector.<int>();
        
        // Update the selection with the index of the caret item
        if (caretIndex != -1)
            newSelection.push(dropIndex + caretIndex);
        
        // Create dataProvider if needed
        if (!dataProvider)
            dataProvider = new ArrayCollection();
        
        var copyItems:Boolean = (event.action == DragManager.COPY);
        for (i = 0; i < items.length; i++)
        {
            // Get the item, clone if needed
            var item:Object = items[i];
            if (copyItems)
                item = copyItemWithUID(item);
            
            // Copy the data
            dataProvider.addItemAt(item, dropIndex + i);
            
            // Update the selection
            if (i != caretIndex)
                newSelection.push(dropIndex + i);
        }
        
        // Set the selection
        selectedIndices = newSelection;
        
        // Scroll the caret index in view
        if (caretIndex != -1)
            ensureCellIsVisible(dropIndex + items.length);
    }
    
    /**
     *  Makes a deep copy of the object by calling the 
     *  <code>ObjectUtil.copy()</code> method, and replaces 
     *  the copy's <code>uid</code> property (if present) with a 
     *  new value by calling the <code>UIDUtil.createUID()</code> method.
     * 
     *  <p>This method is used for a drag and drop copy.</p>
     * 
     *  @param item The item to copy.
     *  
     *  @return The copy of the object.
     *
     *  @see mx.utils.ObjectUtil
     *  @see mx.utils.UIDUtil
     *  
     *  @langversion 3.0
     *  @playerversion Flash 11
     *  @playerversion AIR 3.0
     *  @productversion Flex 5.0
     */
    protected function copyItemWithUID(item:Object):Object
    {
        var copyObj:Object = ObjectUtil.copy(item);
        
        if (copyObj is IUID)
        {
            IUID(copyObj).uid = UIDUtil.createUID();
        }
        else if (copyObj is Object && "mx_internal_uid" in copyObj)
        {
            copyObj.mx_internal_uid = UIDUtil.createUID();
        }
        
        return copyObj;
    }
}
}