////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.controls
{

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Keyboard;
import flash.utils.Dictionary;
import flash.utils.describeType;
import flash.utils.getTimer;

import mx.collections.CursorBookmark;
import mx.collections.ICollectionView;
import mx.collections.ISort;
import mx.collections.ISortField;
import mx.collections.IViewCursor;
import mx.collections.ItemResponder;
import mx.collections.Sort;
import mx.collections.SortField;
import mx.collections.errors.ItemPendingError;
import mx.controls.advancedDataGridClasses.AdvancedDataGridBase;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
import mx.controls.advancedDataGridClasses.AdvancedDataGridDragProxy;
import mx.controls.advancedDataGridClasses.AdvancedDataGridHeaderInfo;
import mx.controls.advancedDataGridClasses.AdvancedDataGridHeaderRenderer;
import mx.controls.advancedDataGridClasses.AdvancedDataGridItemRenderer;
import mx.controls.advancedDataGridClasses.AdvancedDataGridListData;
import mx.controls.advancedDataGridClasses.AdvancedDataGridSortItemRenderer;
import mx.controls.advancedDataGridClasses.SortInfo;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.controls.listClasses.ListBaseSeekPending;
import mx.controls.listClasses.ListBaseSelectionData;
import mx.controls.listClasses.ListRowInfo;
import mx.controls.scrollClasses.ScrollBar;
import mx.core.ClassFactory;
import mx.core.ContextualClassFactory;
import mx.core.EdgeMetrics;
import mx.core.EventPriority;
import mx.core.FlexShape;
import mx.core.FlexSprite;
import mx.core.IBorder;
import mx.core.IFactory;
import mx.core.IFlexDisplayObject;
import mx.core.IFlexModuleFactory;
import mx.core.IIMESupport;
import mx.core.IInvalidating;
import mx.core.IPropertyChangeNotifier;
import mx.core.IUIComponent;
import mx.core.LayoutDirection;
import mx.core.ScrollPolicy;
import mx.core.UIComponent;
import mx.core.UIComponentGlobals;
import mx.core.mx_internal;
import mx.events.AdvancedDataGridEvent;
import mx.events.AdvancedDataGridEventReason;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.events.DragEvent;
import mx.events.IndexChangedEvent;
import mx.events.ListEvent;
import mx.events.SandboxMouseEvent;
import mx.events.ScrollEvent;
import mx.events.ScrollEventDetail;
import mx.events.ScrollEventDirection;
import mx.managers.CursorManager;
import mx.managers.CursorManagerPriority;
import mx.managers.IFocusManager;
import mx.managers.IFocusManagerComponent;
import mx.skins.halo.DataGridColumnDropIndicator;
import mx.styles.ISimpleStyleClient;
import mx.utils.ObjectUtil;
import mx.utils.StringUtil;

use namespace mx_internal;

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

/**
 *  Dispatched when the user releases the mouse button while over an item 
 *  renderer, tabs to the AdvancedDataGrid control or within the AdvancedDataGrid control, 
 *  or in any other way attempts to edit an item.
 *
 *  @eventType mx.events.AdvancedDataGridEvent.ITEM_EDIT_BEGINNING
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="itemEditBeginning", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched when the <code>editedItemPosition</code> property has been set
 *  and the item can be edited.
 *
 *  @eventType mx.events.AdvancedDataGridEvent.ITEM_EDIT_BEGIN
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="itemEditBegin", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched when an item editing session ends for any reason.
 *
 *  @eventType mx.events.AdvancedDataGridEvent.ITEM_EDIT_END
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="itemEditEnd", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched when an item renderer gets focus, which can occur if the user
 *  clicks on an item in the AdvancedDataGrid control or navigates to the item using
 *  a keyboard.  Only dispatched if the item is editable.
 *
 *  @eventType mx.events.AdvancedDataGridEvent.ITEM_FOCUS_IN
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="itemFocusIn", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched when an item renderer loses focus, which can occur if the user
 *  clicks another item in the AdvancedDataGrid control or clicks outside the control,
 *  or uses the keyboard to navigate to another item in the AdvancedDataGrid control
 *  or outside the control.
 *  Only dispatched if the item is editable.
 *
 *  @eventType mx.events.AdvancedDataGridEvent.ITEM_FOCUS_OUT
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="itemFocusOut", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched when a user changes the width of a column, indicating that the 
 *  amount of data displayed in that column may have changed.
 *  If <code>horizontalScrollPolicy</code> is <code>"none"</code>, other
 *  columns shrink or expand to compensate for the columns' resizing,
 *  and they also dispatch this event.
 *
 *  @eventType mx.events.AdvancedDataGridEvent.COLUMN_STRETCH
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="columnStretch", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched 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. The AdvancedDataGrid control has a default handler for this event that implements
 *  a single-column sort.  Multiple-column sort can be implemented by calling the 
 *  <code>preventDefault()</code> method to prevent the single column sort and setting 
 *  the <code>sort</code> property of the data provider.
 * <p>
 * <b>Note</b>: The sort arrows are defined by the default event handler for
 * the <code>headerRelease</code> event. If you call the <code>preventDefault()</code> method
 * in your event handler, the arrows are not drawn.
 * </p>
 *
 *  @eventType mx.events.AdvancedDataGridEvent.HEADER_RELEASE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="headerRelease", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched when sorting is to be performed on the AdvancedDataGrid control.
 *
 *  @eventType mx.events.AdvancedDataGridEvent.SORT
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="sort", type="mx.events.AdvancedDataGridEvent")]

/**
 *  Dispatched when the user releases the mouse button on a column header after 
 *  having dragged the column to a new location resulting in shifting the column
 *  to a new index
 *
 *  @eventType mx.events.IndexChangedEvent.HEADER_SHIFT
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="headerShift", type="mx.events.IndexChangedEvent")]

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

include "../styles/metadata/IconColorStyles.as"

/**
 *  Name of the class of the itemEditor to be used if one is not
 *  specified for a column.  This is a way to set
 *  an item editor for a group of AdvancedDataGrids instead of having to
 *  set each one individually.  If you set the AdvancedDataGridColumn's itemEditor
 *  property, it supercedes this value.
 *  @default null
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="defaultDataGridItemEditor", type="Class", inherit="no")]

/**
 *  Name of the class of the itemRenderer to be used if one is not
 *  specified for a column.  This is a way to set
 *  an itemRenderer for a group of AdvancedDataGrids instead of having to
 *  set each one individually.  If you set the AdvancedDataGrid's itemRenderer
 *  property, it supercedes this value.
 *  @default null
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="defaultDataGridItemRenderer", type="Class", inherit="no")]

/**
 *  A flag that indicates whether to show vertical grid lines between
 *  the columns.
 *  If <code>true</code>, shows vertical grid lines.
 *  If <code>false</code>, hides vertical grid lines.
 *  @default true
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="verticalGridLines", type="Boolean", inherit="no")]

/**
 *  A flag that indicates whether to show horizontal grid lines between
 *  the rows.
 *  If <code>true</code>, shows horizontal grid lines.
 *  If <code>false</code>, hides horizontal grid lines.
 *  @default false
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="horizontalGridLines", type="Boolean", inherit="no")]

/**
 *  The color of the vertical grid lines.
 *  @default 0x666666
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="verticalGridLineColor", type="uint", format="Color", inherit="yes")]

/**
 *  The color of the horizontal grid lines.
  *  
  *  @langversion 3.0
  *  @playerversion Flash 9
  *  @playerversion AIR 1.1
  *  @productversion Flex 3
  */
[Style(name="horizontalGridLineColor", type="uint", format="Color", inherit="yes")]

/**
 *  An array of two colors used to draw the header background gradient.
 *  The first color is the top color.
 *  The second color is the bottom color.
 *  @default [0xFFFFFF, 0xE6E6E6]
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerColors", type="Array", arrayType="uint", format="Color", inherit="yes")]

/**
 *  The color of the row background when the user rolls over the row.
 *  @default 0xE3FFD6
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="rollOverColor", type="uint", format="Color", inherit="yes")]

/**
 *  The color of the background for the row when the user selects 
 *  an item renderer in the row.
 *  @default 0xCDFFC1
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="selectionColor", type="uint", format="Color", inherit="yes")]

/**
 *  The name of a CSS style declaration for controlling other aspects of
 *  the appearance of the column headers.
 *  @default "dataGridStyles"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerStyleName", type="String", inherit="no")]

/**
 *  The class to use as the skin for a column that is being resized.
 * 
 *  @default mx.skins.halo.DataGridColumnResizeSkin (for both Halo and Spark themes)
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="columnResizeSkin", type="Class", inherit="no")]


/**
 *  The class to use as the skin that defines the appearance of the  
 *  background of the column headers in a AdvancedDataGrid control.
 * 
 *  <p>The default skin class is based on the theme. For example, with the Halo theme,
 *  the default skin class is <code>mx.skins.halo.DataGridHeaderBackgroundSkin</code>. For the Spark theme, the default skin
 *  class is <code>mx.skins.spark.DataGridHeaderBackgroundSkin</code>.</p>
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerBackgroundSkin", type="Class", inherit="no")]

/**
 *  The class to use as the skin that defines the appearance of the 
 *  separator between column headers in a AdvancedDataGrid control.
 *  
  *  <p>The default skin class is based on the theme. For example, with the Halo theme,
 *  the default skin class is <code>mx.skins.halo.DataGridHeaderSeparator</code>. For the Spark theme, the default skin
 *  class is <code>mx.skins.spark.DataGridHeaderSeparatorSkin</code>.</p>
*  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerSeparatorSkin", type="Class", inherit="no")]

/**
 *  The class to use as the skin that defines the appearance of the 
 *  separator between a column group and its children columns/column group headers
 *  in an AdvancedDataGrid control.
 *  @default mx.skins.halo.AdvancedDataGridHeaderHorizontalSeparator
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerHorizontalSeparatorSkin", type="Class", inherit="no")]

/**
 *  The class to use as the skin that defines the appearance of the 
 *  separator between rows in a AdvancedDataGrid control. 
 *  By default, the AdvancedDataGrid control uses the 
 *  <code>drawHorizontalLine()</code> and <code>drawVerticalLine()</code> methods
 *  to draw the separators.
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="horizontalSeparatorSkin", type="Class", inherit="no")]

/**
 *  The class to use as the skin that defines the appearance of the 
 *  separator between the locked and unlocked rows in a AdvancedDataGrid control.
 *  By default, the AdvancedDataGrid control uses the 
 *  <code>drawHorizontalLine()</code> and <code>drawVerticalLine()</code> methods
 *  to draw the separators.
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="horizontalLockedSeparatorSkin", type="Class", inherit="no")]

/**
 *  The class to use as the skin that defines the appearance of the 
 *  separators between columns in a AdvancedDataGrid control.
 *  By default, the AdvancedDataGrid control uses the 
 *  <code>drawHorizontalLine()</code> and <code>drawVerticalLine()</code> methods
 *  to draw the separators.
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="verticalSeparatorSkin", type="Class", inherit="no")]

/**
 *  The class to use as the skin that defines the appearance of the 
 *  separator between the locked and unlocked columns in a AdvancedDataGrid control.
 *  By default, the AdvancedDataGrid control uses the 
 *  <code>drawHorizontalLine()</code> and <code>drawVerticalLine()</code> methods
 *  to draw the separators.
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="verticalLockedSeparatorSkin", type="Class", inherit="no")]

/**
 *  The class to use as the skin for the cursor that indicates that a column
 *  can be resized.
 *  @default mx.skins.halo.DataGridStretchCursor
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="stretchCursor", type="Class", inherit="no")]

/**
 *  The class to use as the skin that indicates that 
 *  a column can be dropped in the current location.
 *
 *  @default mx.skins.halo.DataGridColumnDropIndicator (for both Halo and Spark themes)
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="columnDropIndicatorSkin", type="Class", inherit="no")]

/**
 *  The name of a CSS style declaration for controlling aspects of the
 *  appearance of column when the user is dragging it to another location.
 *
 *  @default "headerDragProxyStyle"
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerDragProxyStyleName", type="String", inherit="no")]

//--------------------------------------
//  Excluded APIs
//--------------------------------------

[Exclude(name="columnCount", kind="property")]
[Exclude(name="labelField", kind="property")]
[Exclude(name="offscreenExtraRowsOrColumns", kind="property")]
[Exclude(name="offscreenExtraRows", kind="property")]
[Exclude(name="offscreenExtraRowsTop", kind="property")]
[Exclude(name="offscreenExtraRowsBottom", kind="property")]
[Exclude(name="offscreenExtraColumns", kind="property")]
[Exclude(name="offscreenExtraColumnsLeft", kind="property")]
[Exclude(name="offscreenExtraColumnsRight", kind="property")]
[Exclude(name="offscreenExtraRowsOrColumnsChanged", kind="property")]
[Exclude(name="maxHorizontalScrollPosition", kind="property")]
[Exclude(name="maxVerticalScrollPosition", kind="property")]
[Exclude(name="showDataTips", kind="property")]
[Exclude(name="cornerRadius", kind="style")]

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

[DataBindingInfo("acceptedTypes", "{ dataProvider: &quot;String&quot; }")]

[DefaultBindingProperty(source="selectedItem", destination="dataProvider")]

[DefaultProperty("dataProvider")]

[DefaultTriggerEvent("change")]

[IconFile("AdvancedDataGrid.png")]

[RequiresDataBinding(true)]

/**
 * The AdvancedDataGridBaseEx class is a base class of the AdvancedDataGrid control. 
 * This class contains code that provides functionality similar to the DataGrid control.
 * 
 *  @mxml
 *  <p>
 *  The <code>&lt;mx:AdvancedDataGridBaseEx&gt;</code> tag inherits all of the tag attributes
 *  of its superclass, except for <code>labelField</code>, <code>iconField</code>,
 *  and <code>iconFunction</code>, and adds the following tag attributes:
 *  </p>
 *  <pre>
 *  &lt;mx:AdvancedDataGridBaseEx
 *    <b>Properties</b>
 *    columns="<i>From dataProvider</i>"
 *    draggableColumns="true|false"
 *    editable="item group summary"
 *    editedItemPosition="<code>null</code>"
 *    horizontalScrollPosition="null"
 *    imeMode="null"
 *    itemEditorInstance="null"
 *    lookAheadDuratio="400"
 *    minColumnWidth="<code>NaN</code>"
 *    resizableColumns="true|false"
 *    sortableColumns="true|false"
 *    sortExpertMode="false|true"
 *     
 *    <b>Styles</b>
 *    columnDropIndicatorSkin="DataGridColumnDropIndicator"
 *    columnResizeSkin="DataGridColumnResizeSkin"
 *    disabledIconColor="0x999999"
 *    headerBackgroundSkin="DataGridHeaderSeparator"
 *    headerColors="[#FFFFFF, #E6E6E6]"
 *    headerDragProxyStyleName="headerDragProxyStyle"
 *    headerHorizontalSeparatorSkin="AdvancedDataGridHeaderHorizontalSeparator"
 *    headerSeparatorSkin="DataGridHeaderSeparator"
 *    headerStyleName="<i>No default</i>"
 *    horizontalGridLineColor="<i>No default</i>"
 *    horizontalGridLines="false|true"
 *    horizontalLockedSeparatorSkin="undefined"
 *    horizontalSeparatorSkin="undefined"
 *    iconColor="0x111111"
 *    rollOverColor="#E3FFD6"
 *    selectionColor="#CDFFC1"
 *    stretchCursor="DataGridStretchCursor"
 *    verticalGridLineColor="#666666"
 *    verticalGridLines="false|true"
 *    verticalLockedSeparatorSkin="undefined"
 *    verticalSeparatorSkin="undefined"
 *     
 *    <b>Events</b>
 *    columnStretch="<i>No default</i>"
 *    headerRelease="<i>No default</i>"
 *    headerShift="<i>No default</i>"
 *    itemEditBegin="<i>No default</i>"
 *    itemEditBeginning="<i>No default</i>" 
 *    itemEditEnd="<i>No default</i>"
 *    itemFocusIn="<i>No default</i>"
 *    itemFocusOut="<i>No default</i>"
 *  /&gt;
 *   
 *  <i>The following AdvancedDataGrid code sample specifies the column order:</i>
 *  &lt;mx:AdvancedDataGrid&gt;
 *    &lt;mx:dataProvider&gt;
 *        &lt;mx:Object Artist="Pavement" Price="11.99"
 *          Album="Slanted and Enchanted"/&gt;
 *        &lt;mx:Object Artist="Pavement"
 *          Album="Brighten the Corners" Price="11.99"/&gt;
 *    &lt;/mx:dataProvider&gt;
 *    &lt;mx:columns&gt;
 *        &lt;mx:AdvancedDataGridColumn dataField="Album"/&gt;
 *        &lt;mx:AdvancedDataGridColumn dataField="Price"/&gt;
 *    &lt;/mx:columns&gt;
 *  &lt;/mx:AdvancedDataGrid&gt;
 *  </pre>
 *  </p>
 * 
 * @see mx.controls.AdvancedDataGrid
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class AdvancedDataGridBaseEx extends AdvancedDataGridBase implements IIMESupport
{
    include "../core/Version.as";
    
    //--------------------------------------------------------------------------
    //
    //  Class constants
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  TODO!!! Replace with global versioning infrastructure
     */
    public static var useOldDGHeaderBGLogic:Boolean = false;
    
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function AdvancedDataGridBaseEx()
    {
        super();

        _columns = [];
        
        headerRenderer = new ClassFactory(AdvancedDataGridHeaderRenderer);
        sortItemRenderer = new ClassFactory(AdvancedDataGridSortItemRenderer);

        // pick a default row height
        setRowHeight(20);

        // Register default handlers for item editing and sorting events.

        addEventListener(AdvancedDataGridEvent.ITEM_EDIT_BEGINNING,
                         itemEditorItemEditBeginningHandler,
                         false, EventPriority.DEFAULT_HANDLER);

        addEventListener(AdvancedDataGridEvent.ITEM_EDIT_BEGIN,
                         itemEditorItemEditBeginHandler,
                         false, EventPriority.DEFAULT_HANDLER);

        addEventListener(AdvancedDataGridEvent.ITEM_EDIT_END,
                         itemEditorItemEditEndHandler,
                         false, EventPriority.DEFAULT_HANDLER);

        addEventListener(AdvancedDataGridEvent.HEADER_RELEASE,
                         headerReleaseHandler,
                         false, EventPriority.DEFAULT_HANDLER);

        addEventListener(AdvancedDataGridEvent.SORT,
                         sortHandler,
                         false, EventPriority.DEFAULT_HANDLER);

        addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);                         
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  true if we want to block editing on mouseUp
     */
    private var dontEdit:Boolean = false;

    /**
     *  @private
     *  true if we want to block editing on mouseUp
     */
    private var losingFocus:Boolean = false;
    
    /**
     *  @private
     */
    private var _focusPane:Sprite;

    /**
     *  @private
     *  true if we're in the endEdit call.  Used to handle
     *  some timing issues with collection updates
     */
    private var inEndEdit:Boolean = false;

    /**
     *  @private
     *  true if we've disabled updates in the collection
     */
    private var collectionUpdatesDisabled:Boolean = false;

    /**
     *  Specifies a graphic that shows the proposed column width as the user stretches it.
     *  
     *  @private
     */
    private var resizeGraphic:IFlexDisplayObject;

    /**
     *  @private
     *  A tmp var to store the stretching col's X coord.
     */
    private var startX:Number;

    /**
     *  @private
     *  A tmp var to store the stretching col's min X coord for column's minWidth.
     */
    private var minX:Number;
    
    /**
     *  @private
     *  A tmp var to store the last point (in dataGrid coords) received while dragging.
     */
    private var lastPt:Point;

    /**
     *  @private
     *  List of header separators for column resizing.
     */
    private var separators:Array;

    /**
     *  @private
     *  List of header separators for column resizing in the locked column area.
     */
    protected var lockedSeparators:Array;

    /**
     *  @private
     *  The column that is being resized.
     */
    private var resizingColumn:AdvancedDataGridColumn;

    /**
     *  @private
     *  The index of the column being sorted.
     */
    private var sortIndex:int = -1;

    /**
     *  @private
     *  The column being sorted.
     */
    private var sortColumn:AdvancedDataGridColumn;

    /**
     *  @private
     *  The direction of the sort
     */
    private var sortDirection:String;

    /**
     *  @private
     *  The index of the last column being sorted on.
     */
    private var lastSortIndex:int = -1;

    /**
     *  @private
     */
    private var lastItemDown:IListItemRenderer;

    /**
     *  @private
     *  The column that is being moved.
     */
    protected var movingColumn:AdvancedDataGridColumn;

    /**
     *  @private
     *  Index of column before which to drop
     */
    protected var dropColumnIndex:int = -1;

    /**
     *  @private
     */
    mx_internal var columnDropIndicator:IFlexDisplayObject;

    /**
     *  @private
     */
    private var displayWidth:Number;

    /**
     *  @private
     *  Additional affordance given to header separators.
     */
    private var separatorAffordance:Number = 3;


    /**
     *  @private
     *  Columns with visible="true"
     */
    protected var displayableColumns:Array;
    /**
     *  @private
     *  Whether we have auto-generated the set of columns
     *  Defaults to true so we'll run the auto-generation at init time if needed
     */
    protected var generatedColumns:Boolean = true;

    /**
     *  @private
     *  A hash table of objects used to calculate sizes
     */
    protected var measuringObjects:Dictionary;

    /**
     *  @private
     */
    private var resizeCursorID:int = CursorManager.NO_CURSOR;

    // last known position of item editor instance
    private var actualRowIndex:int;
    private var actualColIndex:int;

    /**
     *  @private
     *  Flag to indicate whether sorting is manual or programmatic.  If it's
     *  not manual, we try to draw the sort arrow on the right column header.
     */
    private var manualSort:Boolean;

    /**
     *  An ordered list of AdvancedDataGridHeaderInfo instances that 
     *  correspond to the visible column headers.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var orderedHeadersList:Array = [];

    /**
     * Contains <code>true</code> if the <code>headerInfos</code> property 
     * has been initialized with AdvancedDataGridHeaderInfo instances.
     *
     * @see mx.controls.advancedDataGridClasses.AdvancedDataGridHeaderInfo 
     *
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var headerInfoInitialized:Boolean = false;

    /**
     *  Contains <code>true</code> if a key press is in progress.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var isKeyPressed:Boolean = false;
    
    /**
     *  @private
     *  Stores the last typed character(s)
     *  for multiple characters type ahead lookup.
     */
    private var lookAheadCache:String = "";
    
    /**
     *  @private
     *  Stores the time of the last typed character
     *  for multiple characters type ahead lookup.
     */
    private var previousTime:uint;

    private var headerBGSkinChanged:Boolean = false;

    private var headerSepSkinChanged:Boolean = false;
    
    private var columnsChanged:Boolean = false;
    
    /**
     *  @private
     *  Set to true when the view is scrolled and
     *  optimumColumns != visibleColumns
     */
    private var subContentScrolled:Boolean = false;
    
    /**
     *  @private
     */
    private var minColumnWidthInvalid:Boolean = false;
    
    /**
     *  @private
     */
    private var bEditedItemPositionChanged:Boolean = false;

    /**
     *  @private
     *  undefined means we've processed it
     *  null means don't put up an editor
     *  {} is the coordinates for the editor
     */
    private var _proposedEditedItemPosition:*;

    /**
     *  @private
     *  the last editedItemPosition.  We restore editing
     *  to this point if we get focus from the TAB key
     */
    private var lastEditedItemPosition:*;
    
    private var _headerWordWrapPresent:Boolean = false;
    private var _originalExplicitHeaderHeight:Boolean = false;
    private var _originalHeaderHeight:Number = 0;
    
    /**
     *  @private
     *  true if based on mouse position, a dropIndex has been found
     */
    private var dropIndexFound:Boolean = false;
    
    /**
     *  @private
     *  true if header getting dragged is outside the permissible area
     */
    private var isHeaderDragOutside:Boolean = false;
    
    /**
     *  The AdvancedDataGridHeaderInfo instances that 
     *  correspond to the currently selected column header.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var selectedHeaderInfo:AdvancedDataGridHeaderInfo;

    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  itemRenderer
    //----------------------------------
    
    /**
    * @private
    * 
    * Defer creation of the class factory to give a chance for the moduleFactory to be set.
    */
    override public function get itemRenderer():IFactory
    {
        if (super.itemRenderer == null)
        {
            var fontName:String = StringUtil.trimArrayElements(getStyle("fontFamily"),",");
            var fontWeight:String = getStyle("fontWeight");
            var fontStyle:String = getStyle("fontStyle");
            var bold:Boolean = (fontWeight == "bold");
            var italic:Boolean = (fontStyle == "italic");
            var flexModuleFactory:IFlexModuleFactory = getFontContext(fontName, bold, italic);
            
            var c:Class = getStyle("defaultDataGridItemRenderer");
            if (!c)
                c = AdvancedDataGridItemRenderer;
            
            super.itemRenderer = new ContextualClassFactory(c, flexModuleFactory);
            
        }
        
        return super.itemRenderer;
    }
    
    //----------------------------------
    //  baselinePosition
    //----------------------------------

    /**
     *  @private
     */
    override public function get baselinePosition():Number
    {
        var top:Number = 0;

        if (border && border is IBorder)
            top = IBorder(border).borderMetrics.top;

        return top + measureText(" ").ascent;
    }

    /**
     *  @private
     *  Number of columns that can be displayed.
     *  Some may be offscreen depending on horizontalScrollPolicy
     *  and the width of the AdvancedDataGrid.
     */
    override public function get columnCount():int
    {
        if (_columns)
            return _columns.length;
        else
            return 0;
    }

    //----------------------------------
    //  enabled
    //----------------------------------

    [Inspectable(category="General", enumeration="true,false", defaultValue="true")]

    /**
     *  @private
     */
    override public function set enabled(value:Boolean):void
    {
        super.enabled = value;

        if (itemEditorInstance)
            endEdit(AdvancedDataGridEventReason.OTHER);

        invalidateDisplayList();
    }

    //----------------------------------
    //  horizontalScrollPosition
    //----------------------------------

    /**
     *  The offset into the content from the left edge. 
     *  This can be a pixel offset in some subclasses or some other metric 
     *  like the number of columns in an AdvancedDataGrid control. 
     *
     *  The AdvancedDataGrid scrolls by columns so the value of the 
     *  <code>horizontalScrollPosition</code> property is always
     *  in the range of 0 to the index of the columns
     *  that will make the last column visible.  
     *  This is different from the List control, which scrolls by pixels.  
     *  The AdvancedDataGrid control always aligns the left edge
     *  of a column with the left edge of the AdvancedDataGrid control.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override public function set horizontalScrollPosition(value:Number):void
    {
        // if not init or no data;
        if (!initialized || listItems.length == 0)
        {
            super.horizontalScrollPosition = value;
            return;
        }

        var oldValue:int = super.horizontalScrollPosition;
        super.horizontalScrollPosition = value;

        columnsInvalid = true;
        calculateColumnSizes();

        // we are going to get a full repaint so don't repaint now
        if (itemsSizeChanged)
            return;

        if (oldValue != value)
        {
            removeClipMask();

            if (getOptimumColumns() == visibleColumns)
            {
                //clearIndicators();
                visibleData = {};

                // columns have variable width so we need to recalc scroll parms
                scrollAreaChanged = true;

                var bookmark:CursorBookmark;
                
                if (iterator)
                    bookmark = iterator.bookmark;
                
                //if we scrolled more than the number of scrollable columns
                makeRowsAndColumns(0, 0, listContent.width, listContent.height, 0, 0);
                
                if (iterator && bookmark)
                    iterator.seek(bookmark, 0);
                
            }
            else
            {
                // In case of column grouping and
                // column span we just move the scroll rect
                subContentScrolled = true;
            }

            updateSubContent();
            updateHeaderSearchList();

            addClipMask(false);

            //an invalidation is needed, to redraw the vertical lines and separators
            invalidateDisplayList();
        }
    }
    
    //----------------------------------
    //  verticalScrollPosition
    //----------------------------------
    
    /**
     *  @private
     *  Sets verticalScrollPosition and draw horizontal lines again
     *  variableRowHeight is true.
     */
    override public function set verticalScrollPosition(value:Number):void
    {
        super.verticalScrollPosition = value;
         
        // draw the horizontal lines afresh if variableRowHeight is true
        // i.e., row height may differ for each row
        if (variableRowHeight)
            drawHorizontalSeparators();
    }
    
    //----------------------------------
    //  focusPane
    //----------------------------------
    
    /**
     *  @private
     */
    override public function set focusPane(value:Sprite):void
    {
        super.focusPane = value;
        
        if (value)
            value.scrollRect = listSubContent ? listSubContent.scrollRect : null;
        
        if (!value && _focusPane)
            _focusPane.mask = null;
        _focusPane = value;
    }

    //----------------------------------
    //  horizontalScrollPolicy
    //----------------------------------

    /**
     *  @private
     *  Accomodates ScrollPolicy.AUTO.
     *  Makes sure column widths stay in synch.
     *
     *  @param policy on, off, or auto
     */
    override public function set horizontalScrollPolicy(value:String):void
    {
        super.horizontalScrollPolicy = value;
        columnsInvalid = true;
        itemsSizeChanged = true;
        invalidateDisplayList();
    }
    
    //----------------------------------
    //  lockedColumnCount
    //----------------------------------

    /**
     *  @private
     */
    override public function set lockedColumnCount(value:int):void
    {
        var i:int = 0;
        var j:int = 0;
        var m:int = 0;
        // remove the items from columnMap, so that they can be created again
        if (value > super.lockedColumnCount)
        {
            for (i = super.lockedColumnCount; i < value ;i++)
            {
                m = listItems.length;
                for(j = 0; j < m; j++)
                {
                    if (listItems[j] && listItems[j][i])
                        delete columnMap[listItems[j][i].name];
                }
            }
        }
        else if (value < super.lockedColumnCount)
        {
            for (i = value; i < super.lockedColumnCount ;i++)
            {
                m = listItems.length;
                for(j = 0; j < m; j++)
                {
                    if (listItems[j] && listItems[j][i])
                        delete columnMap[listItems[j][i].name];
                }
            }
        } 
        super.lockedColumnCount = value;
        
        //listSubContent scrollRectneed to be changed in case lockedColumnCount has changed
        // otherwise items in the scrollrect overlap with the items which have come
        // because of change in lockedColumnCount
        updateSubContent();
        
        itemsSizeChanged = true;

        columnsInvalid = true;

        // set the horizontalScrollPosition so that all the changes are reflected correctly
        horizontalScrollPosition = super.horizontalScrollPosition;
    }
    
    //----------------------------------
    //  dragImage
    //----------------------------------
    
    /**
     *  @private
     */
    override protected function get dragImage():IUIComponent
    {
        var image:AdvancedDataGridDragProxy = new AdvancedDataGridDragProxy();
        image.owner = this;
        image.moduleFactory = moduleFactory;
        return image;
    }

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  columns
    //----------------------------------

    /**
     *  @private
     */
    // Added to AdvancedDataGridBase
    //private var _columns:Array; // the array of our AdvancedDataGridColumns

    [Bindable("columnsChanged")]
    [Inspectable(category="General", arrayType="mx.controls.advancedDataGridClasses.AdvancedDataGridColumn")]

    /**
     *  An array of AdvancedDataGridColumn objects, one for each column that
     *  can be displayed. If not explicitly set, the AdvancedDataGrid control 
     *  attempts to examine the first data provider item to determine the
     *  set of properties and display those properties in alphabetic
     *  order.
     *
     *  <p>If you want to change the set of columns, you must get this Array,
     *  make modifications to the columns and order of columns in the Array,
     *  and then assign the new Array to the <code>columns</code> property.  This is because
     *  the AdvancedDataGrid control returns a copy of the Array of columns, 
     *  not a reference, and therefore cannot detect changes to the copy.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get columns():Array
    {
        return _columns.slice(0);
    }

    /**
     *  @private
     */
    public function set columns(value:Array):void
    {
        var n:int;
        var i:int;
        
        // remove the header items
        purgeHeaderRenderers();
        
        n = _columns.length;
        for (i = 0; i < n; i++)
        {
            columnRendererChanged(_columns[i]);
        }
        
        freeItemRenderersTable = new Dictionary(false);
        itemRendererToFactoryMap = new Dictionary(true);
        columnMap = {};

        _columns = value.slice(0);
        columnsInvalid = true;
        generatedColumns = false;

        n = value.length;
        for (i = 0; i < n; i++)
        {
            var column:AdvancedDataGridColumn = _columns[i];
            column.owner = this;
            column.colNum = i;
        }

        updateSortIndexAndDirection();
        itemsSizeChanged = true;
        columnsChanged = true;
        invalidateDisplayList();
        dispatchEvent(new Event("columnsChanged"));
    }
	
	/**
	 *  An array of AdvancedDataGridColumn objects, one for each column that
	 *  can be displayed. 
	 * 
	 *  <p>Used internally instead of using <code>columns<code> when higher
	 *  performance is required.</p>
	 *
	 *  <p>Use externally with caution and don't modify the array that comes
	 *  back or you may get unexpected issues.</p>
	 *   
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 4.11
	 * 
	 *  @private
	 */
	mx_internal function get rawColumns():Array {
		return _columns;
	}
	
    
    //----------------------------------
    //  draggableColumns
    //----------------------------------

    /**
     *  @private
     *  Storage for the draggableColumns property.
     */
    private var _draggableColumns:Boolean = true;

    [Inspectable(defaultValue="true")]

    /**
     *  Indicates whether you are allowed to reorder columns.
     *  If <code>true</code>, you can reorder the columns
     *  of the AdvancedDataGrid control by dragging the header cells.
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get draggableColumns():Boolean
    {
        return _draggableColumns;
    }

    /**
     *  @private
     */
    public function set draggableColumns(value:Boolean):void
    {
        _draggableColumns = value;
    }
    
    //----------------------------------
    //  enableIME
    //----------------------------------
    
    /**
     *  A flag that indicates whether the IME should
     *  be enabled when the component receives focus.
     *
     *  If the editor is up, it will set enableIME
     *  accordingly.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get enableIME():Boolean
    {
        return false;
    }
    
    //----------------------------------
    //  imeMode
    //----------------------------------

    /**
     *  @private
     */
    private var _imeMode:String = null;

    [Inspectable(environment="none")]

    /**
     *  Specifies the IME (input method editor) mode.
     *  The IME mode enables users to enter text in Chinese, Japanese, and Korean.
     *  Flex sets the specified IME mode when the control gets the focus,
     *  and sets it back to the previous value when the control loses the 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 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get imeMode():String
    {
        return _imeMode;
    }

    /**
     *  @private
     */
    public function set imeMode(value:String):void
    {
        _imeMode = value;
    }

    //----------------------------------
    //  minColumnWidth
    //----------------------------------

    /**
     *  @private
     */
    private var _minColumnWidth:Number;

    [Inspectable(defaultValue="NaN")]

    /**
     *  The minimum width of the columns, in pixels.  If not NaN,
     *  the AdvancedDataGrid control applies this value as the minimum width for
     *  all columns.  Otherwise, individual columns can have
     *  their own minimum widths.
     *  
     *  @default NaN
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get minColumnWidth():Number
    {
        return _minColumnWidth;
    }

    /**
     *  @private
     */
    public function set minColumnWidth(value:Number):void
    {
        _minColumnWidth = value;
        minColumnWidthInvalid = true;
        itemsSizeChanged = true;
        columnsInvalid = true;
        invalidateDisplayList();
    }
    
    //----------------------------------
    //  itemEditorInstance
    //----------------------------------
    
    [Inspectable(environment="none")]

    /**
     *  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 after the event listener for
     *  the <code>itemEditBegin</code> event executes. Therefore, you typically
     *  only access the <code>itemEditorInstance</code> property from within 
     *  the event listener for the <code>itemEditEnd</code> event.</p>
     *
     *  <p>The <code>AdvancedDataGridColumn.itemEditor</code> property defines the
     *  class of the item editor,
     *  and therefore the data type of the item editor instance.</p>
     *
     *  <p>You do not set this property in MXML.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var itemEditorInstance:IListItemRenderer;
    
    //----------------------------------
    //  editedItemRenderer
    //----------------------------------
    
    /**
     *  A reference to the item renderer
     *  in the AdvancedDataGrid control whose item is currently being edited.
     *
     *  <p>From within an event listener for the <code>itemEditBegin</code>
     *  and <code>itemEditEnd</code> events,
     *  you can access the current value of the item being edited
     *  using the <code>editedItemRenderer.data</code> property.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get editedItemRenderer():IListItemRenderer
    {
        if (!itemEditorInstance) return null;

        return listItems[actualRowIndex][actualColIndex];
    }
    
    //----------------------------------
    //  headerIndex
    //----------------------------------
    
    /**
     *  @private
     *  Storage for headerIndex
     */
    private var _headerIndex:int = -1;
    
    /**
     *  If a header is selected via keyboard.
     *
     *  headerIndex is the absolute column number i.e. index of 'columns'.
     *
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal function set headerIndex(value:int):void
    {
        _headerIndex = value;
        
        dispatchEvent(new ListEvent(ListEvent.CHANGE));
    }
    
    mx_internal function get headerIndex():int
    {
        return _headerIndex;
        
    }

    //----------------------------------
    //  editable
    //----------------------------------

    private var _editable:String = "";

    [Inspectable(category="General")]
    /**
     *  Indicates whether or not the user can edit items in the data provider.
     *
     *  <p>If <code>"item"</code>, the item renderers in the control are editable.
     *  The user can click on an item renderer to open an editor.</p>
     *
     *  <p>If <code>"item group"</code>, the item renderers and grouping headers can be edited.</p>
     *
     *  <p>If <code>"item summary"</code>, the item renderers and summary cells can be edited.</p>
     *
     *  <p>You can combine these values. For example, <code>editable = "item group summary"</code>.
     *  Note that item editing has to be enabled if enabling group or summary editing.</p>
     *
     *  <p>If you specify an empty String, no editing is allowed.</p>
     *
     *  <p>The values <code>"true"</code> and <code>"false"</code> correspond 
     *  to item editing and no editing.</p>
     *
     *  <p>A value of <code>"all"</code> means everything is editable.</p>
     *
     *  <p>You can turn off editing for individual columns of the
     *  AdvancedDataGrid control using the <code>AdvancedDataGridColumn.editable</code> property,
     *  or by handling the <code>itemEditBeginning</code> and
     *  <code>itemEditBegin</code> events.</p>
     *
     *  @default ""
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get editable():String
    {
        return _editable;
    }

    public function set editable(value:String):void
    {
        _editable = "";

        if (!value)
            return;

        var editableFlags:Array = value.split(" "); // space delimited
        var n:int = editableFlags.length;
        var keepProcessingFlags:Boolean = true;

        for (var i:int = 0; i < n && keepProcessingFlags; i++)
        {
            switch (editableFlags[i])
            {
                case "item":
                case "group":
                case "summary":
                    {
                        _editable += editableFlags[i] + " ";
                        break;
                    }

                case "true":
                    {
                        _editable = "item" + " ";
                        keepProcessingFlags = false;
                        break;
                    }

                case "false":
                    {
                        _editable = "" + " ";
                        keepProcessingFlags = false;
                        break;
                    }

                case "all":
                    {
                        _editable = "item group summary" + " ";
                        keepProcessingFlags = false;
                        break;
                    }
            }
        }
        _editable = _editable.slice(0, -1); // remove trailing space
    }

    //----------------------------------
    //  editedItemPosition
    //----------------------------------

    /**
     *  @private
     */
    private var _editedItemPosition:Object;

    [Bindable("itemFocusIn")]

    /**
     *  The column and row index of the item renderer for the
     *  data provider item being edited, if any.
     *
     *  <p>This Object has two fields, <code>columnIndex</code> and 
     *  <code>rowIndex</code>,
     *  the zero-based column and row indexes of the item.
     *  For example: {columnIndex:2, rowIndex:3}</p>
     *
     *  <p>Setting this property scrolls the item into view and
     *  dispatches the <code>itemEditBegin</code> event to
     *  open an item editor on the specified item renderer.</p>
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get editedItemPosition():Object
    {
        if (_editedItemPosition)
            return {rowIndex: _editedItemPosition.rowIndex,
                                  columnIndex: _editedItemPosition.columnIndex};
        else
            return _editedItemPosition;
    }

    /**
     *  @private
     */
    public function set editedItemPosition(value:Object):void
    {
        if (!value)
        {
            setEditedItemPosition(null);
            return;
        }

        var newValue:Object = {rowIndex: value.rowIndex,
                               columnIndex: value.columnIndex};

        setEditedItemPosition(newValue);
    }
    
    //----------------------------------
    //  lookAheadDuration
    //----------------------------------

    [Inspectable(defaultValue="400")]
    /**
     *  The type look-ahead duration, in milliseconds, for multi-character look ahead.
     *  Setting it to 0 will turn off multiple character type ahead lookup.
     *  
     *  @default 400
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var lookAheadDuration:Number = 400;

    //----------------------------------
    //  resizableColumns
    //----------------------------------

    [Inspectable(category="General")]

    /**
     *  A flag that indicates whether the user can change the size of the
     *  columns.
     *  If <code>true</code>, the user can stretch or shrink the columns of 
     *  the AdvancedDataGrid control by dragging the grid lines between the header cells.
     *  If <code>true</code>, individual columns must also have their 
     *  <code>resizeable</code> properties set to <code>false</code> to 
     *  prevent the user from resizing a particular column.  
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var resizableColumns:Boolean = true;

    //----------------------------------
    //  sortableColumns
    //----------------------------------

    [Inspectable(category="General")]

    /**
     *  A flag that indicates whether the user can sort the data provider items
     *  by clicking on a column header cell.
     *  If <code>true</code>, the user can sort the data provider items by
     *  clicking on a column header cell. 
     *  The <code>AdvancedDataGridColumn.dataField</code> property of the column
     *  or the <code>AdvancedDataGridColumn.sortCompareFunction</code> property 
     *  of the column is used as the sort field.  
     *  If a column is clicked more than once, 
     *  the sort alternates between ascending and descending order.
     *  If <code>true</code>, individual columns can be made to not respond
     *  to a click on a header by setting the column's <code>sortable</code>
     *  property to <code>false</code>.
     *
     *  <p>When a user releases the mouse button over a header cell, the AdvancedDataGrid
     *  control dispatches a <code>headerRelease</code> event if both
     *  this property and the column's sortable property are <code>true</code>.  
     *  If no handler calls the <code>preventDefault()</code> method on the event, the 
     *  AdvancedDataGrid sorts using that column's <code>AdvancedDataGridColumn.dataField</code> or  
     *  <code>AdvancedDataGridColumn.sortCompareFunction</code> properties.</p>
     * 
     *  @default true
     *
     *  @see mx.controls.advancedDataGridClasses.AdvancedDataGridColumn#dataField
     *  @see mx.controls.advancedDataGridClasses.AdvancedDataGridColumn#sortCompareFunction
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var sortableColumns:Boolean = true;

    //----------------------------------
    //  sortExpertMode
    //----------------------------------

    // Type of sorting UI displayed
    private var _sortExpertMode:Boolean = false;

    /**
     *  By default, the <code>sortExpertMode</code> property is set to <code>false</code>, 
     *  which means you click in the header area of a column to sort the rows of 
     *  the AdvancedDataGrid control by that column. 
     *  You then click in the multiple-column sort area of the header to sort by additional columns. 
     *  If you set the <code>sortExpertMode</code> property to <code>true</code>, 
     *  you use the Control key to select every column after the first column to perform sort.
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    [Inspectable(enumeration="true,false", defaultValue="false")]
    public function get sortExpertMode():Boolean
    {
        return _sortExpertMode;
    }

    /**
     *  @private
     */
    public function set sortExpertMode(value:Boolean):void
    {
        _sortExpertMode = value;

        invalidateHeaders();
        invalidateProperties();
        invalidateDisplayList();
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------

    [Inspectable(category="Data", defaultValue="undefined")]

    /**
     *  @private
     */
    override public function set dataProvider(value:Object):void
    {
        if (itemEditorInstance)
            endEdit(AdvancedDataGridEventReason.OTHER);

        lastEditedItemPosition = null;

        super.dataProvider = value;

        invalidateProperties();
    }
    
    /**
     *  @private
     *  Adds support for multiple characters type ahead lookup.
     */
    override protected function findKey(eventCode:int):Boolean
    {
        var tmpCode:int = eventCode;
        
        // get the timer value now
        var now:uint = getTimer();
        var str:String = String.fromCharCode(tmpCode);
        
        if (!(tmpCode >= 33 && tmpCode <= 126))
            return false;
        // store the value of the _selectedIndex
        var selIndex:Number = _selectedIndex;
        
        // compare the timer value with the previously stored
        // timer value and set up multiple character type ahead
        // lookup.
        if ((now - previousTime) < lookAheadDuration)
        {
            str = lookAheadCache + str;
            lookAheadCache = str;
            previousTime = now;
            // decrement the _selecteIndex
            // we want the lookup to start from the previous item
            if (_selectedIndex > 0)
            {
                selIndex = _selectedIndex;
                _selectedIndex--;
            }
        }
        else
        {
            previousTime = now;
            lookAheadCache = str;
        }
        
        var selectionChanged:Boolean = findString(str);
        
        // set the _selectedIndex back if we cant find the item
        if (!selectionChanged && _selectedIndex != selIndex)
            _selectedIndex = selIndex;
        
        return selectionChanged;
    }

    /**
     *  @private
     *  Measures the AdvancedDataGrid based on its contents,
     *  summing the total of the visible column widths.
     */
    override protected function measure():void
    {
        super.measure();

        var o:EdgeMetrics = viewMetrics;

        var n:int = _columns.length;
        if (n == 0)
        {
            measuredWidth = DEFAULT_MEASURED_WIDTH;
            measuredMinWidth = DEFAULT_MEASURED_MIN_WIDTH;
            return;
        }

        var columnWidths:Number = 0;
        var columnMinWidths:Number = 0;
        for (var i:int = 0; i < n; i++)
        {
            if (_columns[i].visible)
            {
                columnWidths += _columns[i].preferredWidth;
                if (isNaN(_minColumnWidth))
                    columnMinWidths += _columns[i].minWidth;
            }
        }

        if (!isNaN(_minColumnWidth))
            columnMinWidths = n * _minColumnWidth;

        measuredWidth = columnWidths + o.left + o.right;
        measuredMinWidth = columnMinWidths + o.left + o.right;

        // factor out scrollbars if policy == AUTO.  See Container.viewMetrics
        if (verticalScrollPolicy == ScrollPolicy.AUTO &&
            verticalScrollBar && verticalScrollBar.visible)
        {
            measuredWidth -= verticalScrollBar.minWidth;
            measuredMinWidth -= verticalScrollBar.minWidth;
        }
        if (horizontalScrollPolicy == ScrollPolicy.AUTO &&
            horizontalScrollBar && horizontalScrollBar.visible)
        {
            measuredHeight -= horizontalScrollBar.minHeight;
            measuredMinHeight -= horizontalScrollBar.minHeight;
        }

    }
    /**
     *  @private
     *  Sizes and positions the column headers, columns, and items based on the
     *  size of the AdvancedDataGrid.
     */
    override protected function updateDisplayList(unscaledWidth:Number,
                                                  unscaledHeight:Number):void
    {
        // Note: We can't immediately call super.updateDisplayList()
        // because the visibleColumns array must be populated first.
        var updateContent:Boolean = false;
        if (displayWidth != unscaledWidth - viewMetrics.right - viewMetrics.left)
        {
            displayWidth = unscaledWidth - viewMetrics.right - viewMetrics.left;
            columnsInvalid = true;
            updateContent = true;
        }


        calculateColumnSizes();

        if (updateContent)
            updateSubContent();

        if (rendererChanged)
            purgeItemRenderers(); 

        super.updateDisplayList(unscaledWidth, unscaledHeight);
        
        // We need to explicitly call configureScrollBars
        // when horizontal scrolling is optimized. In this case
        // because scrollAreaChanged is false, super doesn't 
        // configure scrollbars.
        if (horizontalScrollPolicy != ScrollPolicy.OFF
            && getOptimumColumns() != visibleColumns
            && !itemsSizeChanged && !bSelectionChanged 
            && !scrollAreaChanged
            && subContentScrolled)
        {
            configureScrollBars();
            subContentScrolled = false;
        }

        if (collection && collection.length)
        {
            setRowCount(listItems.length);

            if (headerInfos && headerInfos.length)
                setColumnCount(headerInfos.length);
            else
                setColumnCount(0);
        }
        
        if (_horizontalScrollPolicy == ScrollPolicy.OFF)
        {
            // If we have a vScroll only and if we have room to fit the scrollbar below the header,
            // we want the scrollbar to be below

            var bm:EdgeMetrics = borderMetrics;
            var hh:Number = headerRowInfo.length ? headerRowInfo[0].height : headerHeight;

            if (verticalScrollBar != null && verticalScrollBar.visible && headerVisible 
                && roomForScrollBar(verticalScrollBar, 
                                    unscaledWidth-bm.left-bm.right, 
                                    unscaledHeight-hh-bm.top-bm.bottom))
            {
                verticalScrollBar.move(verticalScrollBar.x, viewMetrics.top + hh);
                verticalScrollBar.setActualSize(
                    verticalScrollBar.width,
                    unscaledHeight - viewMetrics.top - viewMetrics.bottom - hh);
                verticalScrollBar.visible =  (verticalScrollBar.height >= verticalScrollBar.minHeight);
            }
        }
        if (bEditedItemPositionChanged)
        {
            bEditedItemPositionChanged = false;
			// don't do this if mouse is down on an item
			// on mouse up, we'll let the edit session logic
			// request a new position
			if (!lastItemDown)
            	commitEditedItemPosition(_proposedEditedItemPosition);
            _proposedEditedItemPosition = undefined;
            itemsSizeChanged = false;
        }

        var headerBG:UIComponent =
            UIComponent(listContent.getChildByName("headerBG"));

        if (headerBGSkinChanged)
        {
            headerBGSkinChanged = false;
            if (headerBG)
                listContent.removeChild(headerBG);
            headerBG = null;
        }

        if (!headerBG)
        {
            headerBG = new UIComponent();
            headerBG.name = "headerBG";
            listContent.addChildAt(DisplayObject(headerBG), listContent.getChildIndex(selectionLayer));

            var headerBGSkinClass:Class = getStyle("headerBackgroundSkin");
            
            if (headerBGSkinClass != null)
            {
                var headerBGSkin:IFlexDisplayObject = new headerBGSkinClass();
    
                if (headerBGSkin is ISimpleStyleClient)
                    ISimpleStyleClient(headerBGSkin).styleName = this;
                headerBG.addChild(DisplayObject(headerBGSkin));
            }
        }

        if (headerVisible)
        {
            headerBG.visible = true;
            if (useOldDGHeaderBGLogic)
            {
                drawHeaderBackground(headerBG);
            }
            else
            {
                if (headerBG.numChildren > 0)
                    drawHeaderBackgroundSkin(IFlexDisplayObject(headerBG.getChildAt(0)));
            }
        }
        else
        {
            headerBG.visible = false;
        }

        drawRowBackgrounds();

        if (headerVisible)
            drawSeparators();
        else
            clearSeparators();

        drawLinesAndColumnBackgrounds();

        // trace("<<updateDisplayList");
    }

    /**
     *  @private
     */
    override protected function adjustListContent(unscaledWidth:Number = -1,
                                       unscaledHeight:Number = -1):void
    {
        super.adjustListContent(unscaledWidth, unscaledHeight);

		if(getOptimumColumns() != visibleColumns)
		{
			var n:int = displayableColumns.length;
			var listSubContentWidth:int = 0;
			for(var i:int = lockedColumnCount; i < n; i++)
			{
				listSubContentWidth += displayableColumns[i].width;
			}
			
			listSubContentWidth += getLastColumnResidualWidth() + 50; //Adding default sort renderer's width
			listSubContent.setActualSize(listSubContentWidth,unscaledHeight);
		}
		
        // listSubContent scrollRect needs to be updated whenever
        // listContent size is adjusted
        updateSubContent();
    }
	
	/**
	 *  @private
	 */
	private function getLastColumnResidualWidth():Number
	{
		var n:int = displayableColumns.length-1;
		var displayWidth:int = unscaledWidth - viewMetrics.right - viewMetrics.left;
		var totalWidth:Number = 0;
		var i:int;
		var numLockCols:int = Math.max(0, lockedColumnCount);
		
		//Find the scrollable width i.e displayWidth - { sum of width of locked columns}
		if (numLockCols > 0 && numLockCols < visibleColumns.length)
		{
			for (i = 0; i < numLockCols; i++)
			{
				displayWidth -= displayableColumns[i].width;
			}
		}
		
		// Starting from the right most column in the displayableColumns array
		// find out how many columns we will be able to 
		// accumulate and how much width they will take
		// when horizontal scroll bar is at the rightmost end
		if (n>=0)
		{
			totalWidth = (isNaN(displayableColumns[n].explicitWidth) ? displayableColumns[n].preferredWidth : displayableColumns[n].explicitWidth); 
		}
		
		for (i = n-1; i >= numLockCols; i--)
		{
			if (totalWidth + displayableColumns[i].width <= displayWidth)
				totalWidth += displayableColumns[i].width;
			else
				break;
		}
		
		// The residual width is the width which should be added to 
		// the last column apriori, so that in future when we have horizontally
		// scrolled to the right most position we don't need to create larger
		// items for that column
		return displayWidth - totalWidth;
	}
    
    // horizontal page up, page down
    /**
     *  @private
     */    
    override protected function moveSelectionHorizontally(code:uint,
                                                          shiftKey:Boolean,
                                                          ctrlKey:Boolean):void
    {
        // The new calculated value of the horizontal scroll position
        var newHorizontalScrollPosition:Number;
        // Has the horizontal scroll position actually changed?
        var bUpdateHorizontalScrollPosition:Boolean = false;
        // Max horizontal position
        var maxPosition:int;

        if (shiftKey && code == Keyboard.PAGE_UP)
        {
            newHorizontalScrollPosition = Math.max(
                horizontalScrollPosition - (visibleColumns.length - lockedColumnCount)
                , 0);

            if (newHorizontalScrollPosition != horizontalScrollPosition)
                bUpdateHorizontalScrollPosition = true;
        }
        else if (shiftKey && code == Keyboard.PAGE_DOWN)
        {
            // We don't want to exceed the max scroll value or the last column's index
            maxPosition = Math.min(maxHorizontalScrollPosition, _columns.length-1);
            newHorizontalScrollPosition = Math.min(
                horizontalScrollPosition + (visibleColumns.length - lockedColumnCount)
                , maxPosition);

            if (newHorizontalScrollPosition != horizontalScrollPosition)
                bUpdateHorizontalScrollPosition = true;
        }
        else
        {
            super.moveSelectionHorizontally(code, shiftKey, ctrlKey);
        }

        // Mark the event of the horizontal scroll position changing
        if (bUpdateHorizontalScrollPosition)
        {
            var scrollEvent:ScrollEvent = new ScrollEvent(ScrollEvent.SCROLL);
            scrollEvent.detail          = ScrollEventDetail.THUMB_POSITION;
            scrollEvent.direction       = ScrollEventDirection.HORIZONTAL;
            scrollEvent.delta           = newHorizontalScrollPosition - horizontalScrollPosition;
            scrollEvent.position        = newHorizontalScrollPosition;
            horizontalScrollPosition    = newHorizontalScrollPosition;
            dispatchEvent(scrollEvent);

            if (headerIndex != -1)
                unselectColumnHeader(headerIndex);
        }
    }

    /**
     *  @private
     */
    override protected function makeRowsAndColumns(left:Number, top:Number,
                                                   right:Number, bottom:Number,
                                                   firstCol:int, firstRow:int,
                                                   byCount:Boolean = false, rowsNeeded:uint = 0):Point
    {
        listContent.allowItemSizeChangeNotification = false;
        listSubContent.allowItemSizeChangeNotification = false;

        if (headerVisible && itemsSizeChanged)
            calculateHeaderHeight();

        var pt:Point = super.makeRowsAndColumns(left, top, right, bottom,
                                                firstCol, firstRow, byCount, rowsNeeded);
        var optimumColumns:Array = getOptimumColumns();
        if (itemEditorInstance)
        {
            itemEditorInstance.parent.setChildIndex(DisplayObject(itemEditorInstance),
                                                    itemEditorInstance.parent.numChildren - 1);
            var col:AdvancedDataGridColumn = optimumColumns[actualColIndex];
            var item:IListItemRenderer = listItems[actualRowIndex][actualColIndex];
            var rowData:ListRowInfo = rowInfo[actualRowIndex];
            if (item && !col.rendererIsEditor)
            {
                var dx:Number = col.editorXOffset;
                var dy:Number = col.editorYOffset;
                var dw:Number = col.editorWidthOffset;
                var dh:Number = col.editorHeightOffset;
                itemEditorInstance.move(item.x + dx, rowData.y + dy);
                itemEditorInstance.setActualSize(Math.min(col.width + dw, listContent.width - listContent.x - itemEditorInstance.x),
                                                 Math.min(rowData.height + dh, listContent.height - listContent.y - itemEditorInstance.y));
                // Commenting to show the item (with disclosure icon) behind the item editor
                //item.visible = false;

            }
        }

        var lines:Sprite = Sprite(listSubContent.getChildByName("lines"));
        if (lines)
            listSubContent.setChildIndex(lines, listSubContent.numChildren - 1);


        listContent.allowItemSizeChangeNotification = variableRowHeight;
        listSubContent.allowItemSizeChangeNotification = variableRowHeight;
        return pt;
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        if(columnsInvalid)
        {
            // initializeHeaderInfo need to be called only if columns array have been changed
            // no need to call it everytime columnsInvalid becomes true
            if(columnsChanged && !headerInfoInitialized)
            {
                headerInfos = initializeHeaderInfo(columns);
                headerInfoInitialized = true;
            }

            columnsChanged = false;
            
            visibleHeaderInfos = updateVisibleHeaders();
            updateHeaderSearchList();
        
            createDisplayableColumns();
            
            // It is possible that columns became invisible and the hsp is no longer valid.
            // Force visibleColumns to be recomputed now so if there are lockedColumns and
            // updateSubContent() is called before updateDisplayList() is called,
            // visibleColumns will be correct.
			if (visibleHeaderInfos)
			{
				if (horizontalScrollPosition > visibleHeaderInfos.length)
					horizontalScrollPosition = visibleHeaderInfos.length - 1;
			}
			else
			{
				horizontalScrollPosition = 0;
			}
        }

        super.commitProperties();

        measureItems();
    }

    /**
     *  @private
     *  Instead of measuring the items, we measure the visible columns instead.
     */
    override public function measureWidthOfItems(index:int = -1, count:int = 0):Number
    {
        var w:Number = 0;

        var n:int = _columns ? _columns.length : 0;
        for (var i:int = 0; i < n; i++)
        {
            if (_columns[i].visible)
                w += _columns[i].width;
        }

        return w;
    }

    /**
     *  @private
     */
    override public function measureHeightOfItems(index:int = -1, count:int = 0):Number
    {
        return measureHeightOfItemsUptoMaxHeight(index, count);
    }

    /**
     *  @private
     */
    override protected function calculateRowHeight(data:Object, hh:Number, skipVisible:Boolean = false):Number
    {
        var item:IListItemRenderer;
        var c:AdvancedDataGridColumn;

        var n:int = _columns.length;
        var i:int;
        var j:int = 0;

        if (skipVisible && visibleColumns.length == _columns.length)
            return hh;

        var paddingTop:Number = getStyle("paddingTop");
        var paddingBottom:Number = getStyle("paddingBottom");

        if (!measuringObjects)
            measuringObjects = new Dictionary(false);

        for (i = 0; i < n; i++)
        {
            // skip any columns that are visible
            if (skipVisible && j < visibleColumns.length && visibleColumns[j].colNum == _columns[i].colNum)
            {
                j++;
                continue;
            }
            c = _columns[i];

            if (!c.visible)
                continue;

            item = getMeasuringRenderer(c, false,data);
            setupRendererFromData(c, item, data);
            hh = Math.max(hh, item.getExplicitOrMeasuredHeight() + paddingBottom + paddingTop);
        }
        return hh;
    }

    /**
     *  @private
     */
    override protected function scrollHandler(event:Event):void
    {
        if (event.target == verticalScrollBar ||
            event.target == horizontalScrollBar)
        {
            // TextField.scroll bubbles so you might see it here
            if (event is ScrollEvent)
            {
                if (!liveScrolling &&
                    ScrollEvent(event).detail == ScrollEventDetail.THUMB_TRACK)
                {
                    return;
                }

                if (itemEditorInstance)
                    endEdit(AdvancedDataGridEventReason.OTHER);

                var scrollBar:ScrollBar = ScrollBar(event.target);
                var pos:Number = scrollBar.scrollPosition;

                if (scrollBar == verticalScrollBar)
                    verticalScrollPosition = pos;
                else if (scrollBar == horizontalScrollBar)
                    horizontalScrollPosition = pos;

                super.scrollHandler(event);
            }
        }
    }

    /**
     *  @private
     */
    override protected function configureScrollBars():void
    {
        var oldHorizontalScrollBar:Object = horizontalScrollBar;
        var oldVerticalScrollBar:Object = verticalScrollBar;

        var rowCount:int = listItems.length;
		// check whether the header items are present
		if (rowCount + getHeaderItemsLength() == 0)
        {
            // Get rid of any existing scrollbars.
            if (oldHorizontalScrollBar || oldVerticalScrollBar)
                setScrollBarProperties(0, 0, 0, 0);

            return;
        }

        var vScrollProperties:Array;
        var hScrollProperties:Array;

        // partial last rows don't count
        if (rowCount > 1 && rowInfo[rowCount - 1].y + rowInfo[rowCount - 1].height > listContent.height)
            rowCount--;

        // offset, when added to rowCount, is the index of the dataProvider
        // item for that row.  IOW, row 10 in listItems is showing dataProvider
        // item 10 + verticalScrollPosition - lockedRowCount;
        var offset:int = verticalScrollPosition - lockedRowCount;
        // don't count filler rows at the bottom either.
        var fillerRows:int = 0;
        while (rowCount && listItems[rowCount - 1].length == 0)
        {
            // as long as we're past the end of the collection, add up
            // fillerRows
            if (collection && rowCount + offset >= collection.length)
            {
                rowCount--;
                ++fillerRows;
            }
            else
            {
                break;
            }
        }

        // we have to scroll up.  We can't have filler rows unless the scrollPosition is 0
        if (verticalScrollPosition > 0 && fillerRows > 0)
        {
            if (adjustVerticalScrollPositionDownward(Math.max(rowCount, 1)))
                return;
        }

        vScrollProperties = [collection ? collection.length - lockedRowCount : 0,
                                        Math.max(rowCount - lockedRowCount, 1)];
         
        var colCount:int = visibleColumns.length;
        var lastHeaderInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(visibleColumns[visibleColumns.length - 1]);
        var headerPosX:int =  lastHeaderInfo.headerItem.x;
        if(visibleColumns.length - 1  > lockedColumnCount)
            headerPosX = getAdjustedXPos(headerPosX);
        
        // if the last column is visible and partially offscreen (but it isn't the only
        // column) then adjust the column count so we can scroll to see it
        if (colCount > 1 && visibleColumns[colCount - 1] == displayableColumns[displayableColumns.length - 1]
            && headerPosX + visibleColumns[colCount - 1].width > displayWidth)
        {
            colCount--;
        }
        
        hScrollProperties = [displayableColumns.length - lockedColumnCount,
                             Math.max(colCount - lockedColumnCount, 1)];

        
        //Finally set both the scroll bar properties
        setScrollBarProperties(hScrollProperties[0], hScrollProperties[1],
                               vScrollProperties[0], vScrollProperties[1]);
        
        if ((!verticalScrollBar || !verticalScrollBar.visible) && collection &&
            collection.length - lockedRowCount > rowCount - lockedRowCount)
            maxVerticalScrollPosition = collection.length - lockedRowCount - (rowCount - lockedRowCount);
        
        if ((!horizontalScrollBar || !horizontalScrollBar.visible) && 
            displayableColumns.length - lockedColumnCount  > colCount - lockedColumnCount)
            maxHorizontalScrollPosition = displayableColumns.length - lockedColumnCount - (colCount - lockedColumnCount);
    }

    /**
     *  @private
     */
    override protected function scrollVertically(pos:int, deltaPos:int, scrollUp:Boolean):void
    {
        // temporarily shift the cursor index to first movable row.
        iterator.seek(CursorBookmark.CURRENT, lockedRowCount);

        super.scrollVertically(pos, deltaPos, scrollUp);

        // move the cursor back to actual first row.
        iterator.seek(CursorBookmark.CURRENT, - lockedRowCount);
    }

    /**
     *  @private
     */
    override public function calculateDropIndex(event:DragEvent = null):int
    {
        if (event)
        {
            var item:IListItemRenderer;
            var pt:Point = new Point(event.localX, event.localY);
            pt = DisplayObject(event.target).localToGlobal(pt);
            pt = listContent.globalToLocal(pt);
            
            var n:int = listItems.length;
            for (var i:int = 0; i < n; i++)
            {
                if (rowInfo[i].y <= pt.y && pt.y <= rowInfo[i].y + rowInfo[i].height)
                {
                    item = listItems[i][0];
                    break;
                }
            }

            if (item)
                lastDropIndex = itemRendererToIndex(item);
            else
                lastDropIndex = collection ? collection.length : 0;
        }

        return lastDropIndex;
    }

    /**
     *  @private
     */
    override protected function calculateDropIndicatorY(rowCount:Number, rowNum:int):Number
    {
        var i:int;
        // we need to take care of headerHeight
        var yy:Number = headerVisible ? headerHeight : 0;

        if (rowCount && listItems[rowNum].length && listItems[rowNum][0])
        {
           return listItems[rowNum][0].y - 1
        }

        for (i = 0; i < rowCount; i++)
        {
            if (listItems[i].length)
                yy += rowInfo[i].height;
            else
                break;
        }
        return yy;
    }

    /**
     *  @private
     */
    override protected function drawRowBackgrounds():void
    {
        var rowBGs:Sprite = Sprite(listContent.getChildByName("rowBGs"));
        if (!rowBGs)
        {
            rowBGs = new FlexSprite();
            rowBGs.mouseEnabled = false;
            rowBGs.name = "rowBGs";
            listContent.addChildAt(rowBGs, 0);
        }

        var colors:Array;
		var colorsStyle:Object = getStyle("alternatingItemColors");
		
		if (colorsStyle)
			colors = (colorsStyle is Array) ? (colorsStyle as Array) : [colorsStyle];
		
        if (!colors || colors.length == 0)
            return;

        styleManager.getColorNames(colors);

        var curRow:int = 0;

        var i:int = 0;
        var actualRow:int = verticalScrollPosition;
        var actualLockedRow:int = 0;
        var n:int = listItems.length;

        // for Locked rows
        while (curRow < lockedRowCount && curRow < n)
        {
            drawRowBackground(rowBGs, i++, rowInfo[curRow].y, rowInfo[curRow].height, colors[actualLockedRow % colors.length], actualLockedRow);
            curRow++;
            actualLockedRow++;
            actualRow++;
        }
        
        // for unlocked rows
        while (curRow < n)
        {
            drawRowBackground(rowBGs, i++, rowInfo[curRow].y, rowInfo[curRow].height, colors[actualRow % colors.length], actualRow);
            curRow++;
            actualRow++;
        }

        while (rowBGs.numChildren > i)
        {
            rowBGs.removeChildAt(rowBGs.numChildren - 1);
        }
    }

    /**
     *  @private
     */
    override protected function mouseEventToItemRenderer(event:MouseEvent):IListItemRenderer
    {
        var r:IListItemRenderer;

        if (event.target == highlightIndicator || event.target == listContent)
        {
            var pt:Point = new Point(event.stageX, event.stageY);
            pt = listContent.globalToLocal(pt);

            var ww:Number = 0;

            // For headerItems
            // headerItems are created even if showHeader is false
            // dont look for header renderers if headerVisible is false
            if (headerVisible)
                r = findHeaderRenderer(pt);

            // For listItems
            // if ADG is empty then length of rowInfo is 0
            if (!r && rowInfo.length !=0)
                r = findRenderer(pt,listItems,rowInfo,rowInfo[0].y);
        }

        if (!r)
            r = super.mouseEventToItemRenderer(event);

        return r == itemEditorInstance ? null : r;
    }

    /**
     *  @private
     */
    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged(styleProp);

        var changed:Boolean = false;

        if (styleProp == "headerBackgroundSkin")
        {
            changed = true;
            headerBGSkinChanged = true;
        }
        else if (styleProp == "headerSortSeparatorSkin")
        {
            changed = true;
        }
        else if (styleProp == "headerSeparatorSkin")
        {
            headerSepSkinChanged = true;
            changed = true;
        }

        if (changed)
        {
            itemsSizeChanged = true;
        }
    }
    
    /**
     *  @private
     *  handle header selection
     */
    override protected function selectItem(item:IListItemRenderer,
                                  shiftKey:Boolean, ctrlKey:Boolean,
                                  transition:Boolean = true):Boolean
     {
        var val:Boolean = super.selectItem(item, shiftKey, ctrlKey, transition);
        
        // if item.data is AdvancedDataGridColumn, it means that a header is selected
        // selectedItem should be null
        if (item.data is AdvancedDataGridColumn)
            _selectedItem = null;
        
        return val;
     }
     
     /**
     *  @private
     *  handle header selection
     */
     override mx_internal function addSelectionData(uid:String, selectionData:ListBaseSelectionData):void
     {
        // if data is AdvancedDataGridColumn, it means that a header is selected
        // it should not be added into the list
        if (selectionData.data is AdvancedDataGridColumn)
            return ;
        super.addSelectionData(uid, selectionData);
     }
     
     /**
     *  @private
     *  used by ListBase.findString.  Shouldn't be used elsewhere
     *  because column's itemToLabel is preferred
     */
    override public function itemToLabel(data:Object):String
    {
        return displayableColumns[sortIndex == -1 ? 0 : sortIndex].itemToLabel(data);
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  When column width changes or horizontal scrolling happens
     *  we need to adjust the sub content area.
     */
    private function updateSubContent():void
    {
        if(!visibleColumns || getOptimumColumns() == visibleColumns)
        {
            listSubContent.scrollRect = null;
            listSubContent.x = 0;
            return ;
        }

        var lockedWidth:Number = 0;
        for(var i:int = 0; i < lockedColumnCount; ++i)
        {
            lockedWidth += displayableColumns[i].width;
        }

        var scrollWidth:Number = 0;
        if(visibleColumns.length > lockedColumnCount)
        {
            for(i = lockedColumnCount; i < lockedColumnCount+horizontalScrollPosition; ++i)
            {
                scrollWidth += displayableColumns[i].width;
            }
        }
        if (horizontalScrollPosition == 0)
        {
            //tmpMask.x = 0;
            listSubContent.scrollRect = null;
            listSubContent.x = 0;
        }
        else
        {
            if (lockedColumnCount > 0)
                listSubContent.x = lockedWidth;
            else
                listSubContent.x = 0;
            //tmpMask.x = lockedWidth;
            if (lockedWidth > 0)
                listSubContent.scrollRect = new Rectangle(lockedWidth+scrollWidth, 0, 
                                                          listContent.width - lockedWidth, listContent.height);
            else
                listSubContent.scrollRect = new Rectangle(scrollWidth, 0, 
                                                          listContent.width, listContent.height);
        }
    }

    /**
     *  @private
     */    
    protected function updateVisibleHeaders():Array
    {
        var visibleHeaderInfos:Array = [];

        var n:int = headerInfos ? headerInfos.length : 0;
        var i:int;
        var k:int= 0;;
        
        for ( i = 0; i < n; i++)
        {
            headerInfos[i].visible = headerInfos[i].column.visible;
            if(headerInfos[i].visible)
            {
                visibleHeaderInfos.push(headerInfos[i]);
                headerInfos[i].actualColNum = k++;
                headerInfos[i].columnSpan = 1;
            }
            else
            {
                headerInfos[i].actualColNum = NaN;
            }
        }
        return visibleHeaderInfos;
    }

    /**
     *  @private
     */    
    protected function updateHeaderSearchList():void
    {
        var n:int = visibleHeaderInfos? visibleHeaderInfos.length : 0;
        
        orderedHeadersList = [];
        for (var i:int = 0; i < n; i++)
        {
            orderedHeadersList.push(visibleHeaderInfos[i]);
        }
    }
    
    /**
     *  @private
	 * 
	 * Note columns may not of been committed at this point.
     */
    protected function initializeHeaderInfo(columns:Array):Array
    {
        var newArray:Array = [];
        var n:int = columns.length;
        for(var i:int = 0; i < n; i++)
        {
            var headerInfo:AdvancedDataGridHeaderInfo = new AdvancedDataGridHeaderInfo(columns[i],null,i, 0) ;
            newArray.push(headerInfo);
        }
        return newArray;
    }
	
	/**
	 * Get the length of the header items
	 * 
	 *  @private
	 */
	protected function getHeaderItemsLength():int
	{
		return headerItems.length;
	}
    
    /**
     *  @private
     */
    mx_internal function getMeasuringRenderer(c:AdvancedDataGridColumn, forHeader:Boolean, data:Object):IListItemRenderer
    {
        var factory:IFactory = columnItemRendererFactory(c,forHeader,data);
		
		if (!measuringObjects)
			measuringObjects = new Dictionary(false);
		
        var item:IListItemRenderer = measuringObjects[factory];
        if (!item)
        {
            item = columnItemRenderer(c, forHeader, data);
            item.visible = false;
            item.styleName = c;
            listContent.addChild(DisplayObject(item));
            measuringObjects[factory] = item;
        }

        return item;
    }

    mx_internal function setupRendererFromData(c:AdvancedDataGridColumn, item:IListItemRenderer, data:Object):void
    {
        var rowData:AdvancedDataGridListData =
            AdvancedDataGridListData(makeListData(data, itemToUID(data), 0, c.colNum, c));

        if (item is IDropInListItemRenderer)
        {
            if (data != null)
                IDropInListItemRenderer(item).listData = makeListData(data, itemToUID(data), 0 /* rowNum */, c.colNum, c);
            else
                IDropInListItemRenderer(item).listData = null;
        }

        item.data = data;

        if (item is IInvalidating)
            IInvalidating(item).invalidateSize();

        item.explicitWidth = getWidthOfItem(item, c, currentColNum);

        UIComponentGlobals.layoutManager.validateClient(item, true);
    }
    
    /**
     *  @private
     */
    mx_internal function measureHeightOfItemsUptoMaxHeight(index:int = -1, count:int = 0, maxHeight:Number = -1):Number
    {
        if (!_columns.length)
            return rowHeight * count;

        var h:Number = 0;

        var item:IListItemRenderer;
        var c:AdvancedDataGridColumn;
        var ch:Number = 0;
        var n:int;
        var j:int;

        var paddingTop:Number = getStyle("paddingTop");
        var paddingBottom:Number = getStyle("paddingBottom");

        if (!measuringObjects)
            measuringObjects = new Dictionary(false);

        var lockedCount:int = lockedRowCount;

        if (headerVisible && count > 0 && index == -1)
        {
            h = calculateHeaderHeight();

            if (maxHeight != -1 && h > maxHeight)
            {
                setRowCount(0);
                return 0;
            }

            // trace(this + " header preferredHeight = " + h);
        }

        var bookmark:CursorBookmark = (iterator) ? iterator.bookmark : null;

        var bMore:Boolean = iterator != null;
        if (index != -1 && iterator)
        {
            try
            {
                iterator.seek(CursorBookmark.FIRST, index);
            }
            catch (e:ItemPendingError)
            {
                bMore = false;
            }
        }

        if (lockedCount > 0 && collectionIterator)
        {
            try
            {
                collectionIterator.seek(CursorBookmark.FIRST,0);
            }
            catch (e:ItemPendingError)
            {
                bMore = false;
            }
        }

        for (var i:int = 0; i < count; i++)
        {
            var data:Object;
            if (bMore)
            {
                data = (lockedCount > 0) ? collectionIterator.current : iterator.current;
                ch = 0;
                n = _columns.length;
                for (j = 0; j < n; j++)
                {
                    c = _columns[j];

                    if (!c.visible)
                        continue;

                    item = getMeasuringRenderer(c, false,data);
                    setupRendererFromData(c, item, data);
                    ch = Math.max(ch, variableRowHeight ? item.getExplicitOrMeasuredHeight() + paddingBottom + paddingTop : rowHeight);
                }
            }

            if (maxHeight != -1 && (h + ch > maxHeight || !bMore))
            {
                try
                {
                    if (iterator)
                        iterator.seek(bookmark, 0);
                }
                catch (e:ItemPendingError)
                {
                    // we don't recover here since we'd only get here if the first seek failed.
                }
                count = i;
                setRowCount(count);
                return h;
            }

            h += ch;
            if (iterator)
            {
                try
                {
                    bMore = iterator.moveNext();
                    if (lockedCount > 0)
                    {
                        collectionIterator.moveNext();
                        lockedCount--;
                    }
                }
                catch (e:ItemPendingError)
                {
                    // if we run out of data, assume all remaining rows are the size of the previous row
                    bMore = false;
                }
            }
        }

        if (iterator)
        {
            try
            {
                iterator.seek(bookmark, 0);
            }
            catch (e:ItemPendingError)
            {
                // we don't recover here since we'd only get here if the first seek failed.
            }
        }

        // trace("calcheight = " + h);
        return h;
    }

    /**
     *  @private
     */
    protected function calculateHeaderHeight():Number
    {
        if (!_columns.length)
            return rowHeight;

        var item:IListItemRenderer;
        var c:AdvancedDataGridColumn;
        var rowData:AdvancedDataGridListData;
        var ch:Number = 0;
        var n:int;
        var j:int;

        var paddingTop:Number = getStyle("paddingTop");
        var paddingBottom:Number = getStyle("paddingBottom");

        if (!measuringObjects)
            measuringObjects = new Dictionary(false);

        if (headerVisible)
        {
            ch = 0;
            n = _columns.length;

            if (_headerWordWrapPresent)
            {
                _headerHeight = _originalHeaderHeight;
                _explicitHeaderHeight = _originalExplicitHeaderHeight;
            }

            for (j = 0; j < n; j++)
            {
                c = _columns[j];

                if (!c.visible)
                    continue;

                // passing data as null, as it is used for header renderer
                item = getMeasuringRenderer(c, true, null);
                rowData = AdvancedDataGridListData(makeListData(c, uid, 0, c.colNum, c));
                rowMap[item.name] = rowData;
                if (item is IDropInListItemRenderer)
                    IDropInListItemRenderer(item).listData = rowData;
                item.data = c;
                item.explicitWidth = c.width;
                UIComponentGlobals.layoutManager.validateClient(item, true);
                ch = Math.max(ch, _explicitHeaderHeight ? headerHeight : item.getExplicitOrMeasuredHeight() + paddingBottom + paddingTop);

                if (columnHeaderWordWrap(c))
                    _headerWordWrapPresent = true;
            }

            if (_headerWordWrapPresent)
            {
                // take backups
                _originalHeaderHeight = _headerHeight;
                _originalExplicitHeaderHeight = _explicitHeaderHeight;

                headerHeight = ch;
            }
        }
        return ch;
    }
    
    /**
     *  @private
     */
    protected function getAdjustedXPos(posx:int):int
    {
        if (listSubContent.scrollRect)
        {
            if (listSubContent.x == 0)
                posx -= listSubContent.scrollRect.x;
            else
                posx -= (listSubContent.scrollRect.x - listSubContent.x);
        }
        return posx;
    }

    /**
     *  @private
     */
    mx_internal function getHeaderInfo(col:AdvancedDataGridColumn):AdvancedDataGridHeaderInfo
    {
        return headerInfos[col.colNum];
    }

    /**
     *  @private
     */
    mx_internal function getHeaderInfoAt(colIndex:int):AdvancedDataGridHeaderInfo
    {
        if(headerInfos)
            return headerInfos[colIndex];
        return null;
    }

    /**
     *  @private
     */
    protected function getNumColumns():int
    {
        if(headerItems && headerItems[0])
            return headerItems[0].length;
        return -1;
    }
    
    /**
     *  @private
     *  Makes verticalScrollPosition smaller until it is 0 or there
     *  are no empty rows.  This is needed if we're scrolled to the
     *  bottom and something is deleted or the rows resize so more
     *  rows can be shown.
     */
    private function adjustVerticalScrollPositionDownward(rowCount:int):Boolean
    {
        var bookmark:CursorBookmark = iterator.bookmark;

        // add up how much space we're currently taking with valid items
        var h:Number = 0;

        var item:IListItemRenderer;
        var c:AdvancedDataGridColumn;
        var ch:Number = 0;
        var n:int;
        var j:int;

        var paddingTop:Number = getStyle("paddingTop");
        var paddingBottom:Number = getStyle("paddingBottom");

        h = rowInfo[rowCount - 1].y + rowInfo[rowCount - 1].height;
        h = listContent.height - h;

        // back up one
        var numRows:int = 0;
        try
        {
            if (iterator.afterLast)
                iterator.seek(CursorBookmark.LAST, 0)
            else
                var bMore:Boolean = iterator.movePrevious();
        }
        catch (e:ItemPendingError)
        {
            bMore = false;
        }
        if (!bMore)
        {
            // reset to 0;
            super.verticalScrollPosition = 0;
            try
            {
                iterator.seek(CursorBookmark.FIRST, 0);
                // sometimes, if the iterator is invalid we'll get lucky and succeed
                // here, then we have to make the iterator valid again
                if (!iteratorValid)
                {
                    iteratorValid = true;
                    lastSeekPending = null;
                }
            }
            catch (e:ItemPendingError)
            {
                lastSeekPending = new ListBaseSeekPending(CursorBookmark.FIRST, 0);
                e.addResponder(new ItemResponder(seekPendingResultHandler, seekPendingFailureHandler,
                                                 lastSeekPending));
                iteratorValid = false;
                invalidateList();
                return true;
            }
            updateList();
            return true;
        }

        // now work backwards to see how many more rows we need to create
        while (h > 0 && bMore)
        {
            var data:Object;
            if (bMore)
            {
                data = iterator.current;
                ch = 0;
                n = _columns.length;
                for (j = 0; j < n; j++)
                {
                    c = _columns[j];

                    if (!c.visible)
                        continue;

                    if (variableRowHeight)
                    {
                        item = getMeasuringRenderer(c, false,data);
                        setupRendererFromData(c, item, data);
                    }
                    ch = Math.max(ch, variableRowHeight ? item.getExplicitOrMeasuredHeight() + paddingBottom + paddingTop : rowHeight);
                }
            }
            h -= ch;
            try
            {
                bMore = iterator.movePrevious();
                numRows++;
            }
            catch (e:ItemPendingError)
            {
                // if we run out of data, assume all remaining rows are the size of the previous row
                bMore = false;
            }
        }
        // if we overrun, go back one.
        if (h < 0)
        {
            numRows--;
        }

        iterator.seek(bookmark, 0);
        verticalScrollPosition = Math.max(0, verticalScrollPosition - numRows);

        // make sure we get through configureScrollBars w/o coming in here.
        if (numRows > 0 && !variableRowHeight)
            configureScrollBars();

        return (numRows > 0);
    }
    
    /**
     *  @private
     *  Move a column to a new position in the columns array, shifting all
     *  other columns left or right and updating the sortIndex and
     *  lastSortIndex variables accordingly.
     */
    mx_internal function shiftColumns(oldIndex:int, newIndex:int,
                                      trigger:Event = null):void
    {
        var groupInfos:Array = headerInfos; //getPossibleDropPositions(movingColumn);
        if (newIndex >= 0 && oldIndex != newIndex)
        {
            var incr:int = oldIndex < newIndex ? 1 : -1;
            for (var i:int = oldIndex; i != newIndex; i += incr)
            {
                var j:int = i + incr;
                var c:AdvancedDataGridColumn = _columns[i];
                _columns[i] = _columns[j];
                _columns[j] = c;
                _columns[i].colNum = i;
                _columns[j].colNum = j;

                var cInfo:AdvancedDataGridHeaderInfo = groupInfos[i];
                groupInfos[i] = groupInfos[j];
                groupInfos[j] = cInfo;
                groupInfos[i].index -=incr;
                groupInfos[j].index += incr;
            }

            if (sortIndex == oldIndex)
                sortIndex += newIndex - oldIndex;
            else if ((oldIndex < sortIndex && sortIndex <= newIndex)
                     || (newIndex <= sortIndex && sortIndex < oldIndex))
                sortIndex -= incr;

            if (lastSortIndex == oldIndex)
                lastSortIndex += newIndex - oldIndex;
            else if ((oldIndex < lastSortIndex
                      && lastSortIndex <= newIndex)
                     || (newIndex <= lastSortIndex
                         && lastSortIndex < oldIndex))
                lastSortIndex -= incr;

            columnsInvalid = true;
            itemsSizeChanged = true;

            visibleHeaderInfos = updateVisibleHeaders();
            updateHeaderSearchList();
            createDisplayableColumns();

            invalidateDisplayList();
            var icEvent:IndexChangedEvent =
                new IndexChangedEvent(IndexChangedEvent.HEADER_SHIFT);
            icEvent.oldIndex = oldIndex;
            icEvent.newIndex = newIndex;
            icEvent.triggerEvent = trigger;
            dispatchEvent(icEvent);
        }
    }
    
    /**
     *  @private
     *  Searches the iterator to determine columns.
     */
    private function generateCols():void
    {
        if (collection.length > 0)
        {
            var col:AdvancedDataGridColumn;
            var newCols:Array = [];
            var cols:Array;
            if (dataProvider)
            {
                try
                {
                    iterator.seek(CursorBookmark.FIRST);
                }
                catch (e:ItemPendingError)
                {
                    lastSeekPending = new ListBaseSeekPending(CursorBookmark.FIRST, 0);
                    e.addResponder(new ItemResponder(generateColumnsPendingResultHandler, seekPendingFailureHandler,
                                                     lastSeekPending));
                    iteratorValid = false;
                    return;
                }
                var info:Object =
                    ObjectUtil.getClassInfo(iterator.current,
                                            ["uid", "mx_internal_uid"]);

                if(info)
                    cols = info.properties;
            }

            if (!cols)
            {
                // introspect the first item and use its fields
                var itmObj:Object = iterator.current;
                for (var p:String in itmObj)
                {
                    if (p != "uid")
                    {
                        col = new AdvancedDataGridColumn();
                        col.dataField = p;
                        newCols.push(col);
                    }
                }
            }
            else
            {
                // this is an old recordset - use its columns
                var n:int = cols.length;
                var colName:Object;
                for (var i:int = 0; i < n; i++)
                {
                    colName = cols[i];
                    if (colName is QName)
                        colName = QName(colName).localName;
                    col = new AdvancedDataGridColumn();
                    col.dataField = String(colName);
                    newCols.push(col);
                }
            }
            columns = newCols;
            generatedColumns = true;
        }
    }

    /**
     *  @private
     */
    private function generateColumnsPendingResultHandler(data:Object, info:ListBaseSeekPending):void
    {
        // generate cols if we haven't successfully generated them
        if (_columns.length == 0)
            generateCols();
        seekPendingResultHandler(data, info);
    }

    /**
     *  @private
     */
    protected function createDisplayableColumns():void
    {
        var i:int;
        var n:int;
        
        displayableColumns = null;
        n = _columns.length;
        for (i = 0; i < n; i++)
        {
            if (displayableColumns && _columns[i].visible)
            {
                displayableColumns.push(_columns[i]);
            }
            else if (!displayableColumns && !_columns[i].visible)
            {
                displayableColumns = new Array(i);
                for (var j:int = 0; j < i; j++)
                {
                    displayableColumns[j] = _columns[j];
                }
            }
        }
        // If there are no hidden columns, displayableColumns points to
            // _columns (we don't need a duplicate copy of _columns).
        if (!displayableColumns)
            displayableColumns = _columns;
    }
    
    /**
     *  @private
     */
    private function calculateColumnSizes():void
    {
        var delta:Number;
        var n:int;
        var i:int;
        var totalWidth:Number = 0;
        var col:AdvancedDataGridColumn;
        var cw:Number;

        if (_columns.length == 0)
        {
            visibleColumns = [];
            return;
        }

        // no columns are visible so figure out which ones
        // to make visible
        if (columnsInvalid)
        {
            columnsInvalid = false;
            visibleColumns = [];

            if (minColumnWidthInvalid)
            {
                n = _columns.length;
                for (i = 0; i < n; i++)
                {
                    _columns[i].minWidth = minColumnWidth;
                }
                minColumnWidthInvalid = false;
            }
            
            // if no hscroll, then pack columns in available space
            if (horizontalScrollPolicy == ScrollPolicy.OFF)
            {
                n = displayableColumns.length;
                for (i = 0; i < n; i++)
                {
                    visibleColumns.push(displayableColumns[i]);
                }
            }
            else
            {
                n = displayableColumns.length;
                for (i = 0; i < n; i++)
                {
                    if (i >= lockedColumnCount &&
                        i < lockedColumnCount + horizontalScrollPosition)
                    {
                        continue;
                    }

                    col = displayableColumns[i];
                    if (col.preferredWidth < col.minWidth)
                        col.preferredWidth = col.minWidth;

                    if (totalWidth < displayWidth)
                    {
                        visibleColumns.push(col);
                        totalWidth += isNaN(col.explicitWidth) ? col.preferredWidth : col.explicitWidth;
                        if (col.width != col.preferredWidth)
                            col.setWidth(col.preferredWidth);
                    }
                    else
                    {
                        if (visibleColumns.length == 0)
                            visibleColumns.push(displayableColumns[0]);
                        break;
                    }
                }
            }
        }

        var lastColumn:AdvancedDataGridColumn;
        var newSize:Number;

        // if no hscroll, then pack columns in available space
        if (horizontalScrollPolicy == ScrollPolicy.OFF)
        {
            var numResizable:int = 0;
            var fixedWidth:Number = 0;

            // trace("resizing columns");

            // count how many resizable columns and how wide they are
            n = visibleColumns.length;
            for (i = 0; i < n; i++)
            {
                // trace("column " + i + " width = " + visibleColumns[i].width);
                if (visibleColumns[i].resizable)
                {
                    // trace("    resizable");
                    if (!isNaN(visibleColumns[i].explicitWidth))
                    {
                        // trace("    explicit width " + visibleColumns[i].width);
                        fixedWidth += visibleColumns[i].width;
                    }
                    else
                    {
                        // trace("    implicitly resizable");
                        numResizable++;
                        fixedWidth += visibleColumns[i].minWidth;
                        // trace("    minWidth " + visibleColumns[i].minWidth);
                    }
                }
                else
                {
                    // trace("    not resizable");
                    fixedWidth += visibleColumns[i].width;
                }

                totalWidth += visibleColumns[i].width;
            }
            // trace("totalWidth = " + totalWidth);
            // trace("displayWidth = " + displayWidth);

            var ratio:Number;
            var newTotal:Number = displayWidth;
            var minWidth:Number;
            if (displayWidth > fixedWidth && numResizable)
            {
                // we have flexible columns and room to honor minwidths and non-resizable
                // trace("have enough room");

                // divide and distribute the excess among the resizable
                n = visibleColumns.length;
                for (i = 0; i < n; i++)
                {
                    if (visibleColumns[i].resizable && isNaN(visibleColumns[i].explicitWidth))
                    {
                        lastColumn = visibleColumns[i];
                        if (totalWidth > displayWidth)
                            ratio = (lastColumn.width - lastColumn.minWidth)/ (totalWidth - fixedWidth);
                        else
                            ratio = lastColumn.width / totalWidth;
                        newSize = lastColumn.width - (totalWidth - displayWidth) * ratio;
                        minWidth = visibleColumns[i].minWidth;
                        visibleColumns[i].setWidth(newSize > minWidth ? newSize : minWidth);
                        // trace("column " + i + " set to " + visibleColumns[i].width);
                    }
                    newTotal -= visibleColumns[i].width;
                }
                if (newTotal && lastColumn)
                {
                    // trace("excess = " + newTotal);
                    lastColumn.setWidth(lastColumn.width + newTotal);
                }
            }
            else // can't honor minwidth and non-resizables so just scale everybody
            {
                // trace("too small or too big");
                n = visibleColumns.length;
                for (i = 0; i < n; i++)
                {
                    lastColumn = visibleColumns[i];
                    ratio = lastColumn.width / totalWidth;
                    //totalWidth -= visibleColumns[i].width;
                    newSize = displayWidth * ratio;
                    lastColumn.setWidth(newSize);
                    lastColumn.explicitWidth = NaN;
                    // trace("column " + i + " set to " + visibleColumns[i].width);
                    newTotal -= newSize;
                }
                if (newTotal && lastColumn)
                {
                    // trace("excess = " + newTotal);
                    lastColumn.setWidth(lastColumn.width + newTotal);
                }
            }
        }
        else // we have or can have an horizontalScrollBar
        {
            totalWidth = 0;
            // drop any that completely overflow
            n = visibleColumns.length;
            for (i = 0; i < n; i++)
            {
                if (totalWidth > displayWidth)
                {
                    visibleColumns.splice(i);
                    break;
                }
                totalWidth += isNaN(visibleColumns[i].explicitWidth) ? visibleColumns[i].preferredWidth : visibleColumns[i].explicitWidth;
            }

            if (visibleColumns.length == 0)
                return;

            i = visibleColumns[visibleColumns.length - 1].colNum + 1;
            // add more if we have room
            if (totalWidth < displayWidth && i < displayableColumns.length)
            {
                n = displayableColumns.length;
                for (; i < n && totalWidth < displayWidth; i++)
                {
                    col = displayableColumns[i];

                    visibleColumns.push(col);
                    totalWidth += isNaN(col.explicitWidth) ? col.preferredWidth : col.explicitWidth;
                }
            }
            else if (totalWidth < displayWidth && horizontalScrollPosition > 0)
            {
                while (totalWidth < displayWidth && horizontalScrollPosition > 0)
                {
                    col = displayableColumns[lockedColumnCount + horizontalScrollPosition - 1];
                    cw = isNaN(col.explicitWidth) ? col.preferredWidth : col.explicitWidth;
                    if (cw < displayWidth - totalWidth)
                    {
                        visibleColumns.splice(lockedColumnCount, 0, col);
                        super.horizontalScrollPosition--;
                        totalWidth += cw;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            lastColumn = visibleColumns[visibleColumns.length - 1];
            cw = isNaN(lastColumn.explicitWidth) ? lastColumn.preferredWidth : lastColumn.explicitWidth;
            newSize = cw + displayWidth - totalWidth;

            if (lastColumn == displayableColumns[displayableColumns.length - 1]
                && lastColumn.resizable 
                && newSize >= lastColumn.minWidth
                && newSize > cw)
            {
                lastColumn.setWidth(newSize);
                maxHorizontalScrollPosition =
                    displayableColumns.length - visibleColumns.length;
            }
            else
            {
                if (visibleColumns.length == displayableColumns.length)
                {
                    // set scrollPosition to zero
                    maxHorizontalScrollPosition = 0;
                    super.horizontalScrollPosition = 0;
                }
                else if(lockedColumnCount < visibleColumns.length)
                {
                    maxHorizontalScrollPosition =
                        displayableColumns.length - visibleColumns.length + 1;
                }
                else
                {
                    maxHorizontalScrollPosition =
                        Math.max(0, displayableColumns.length - lockedColumnCount + 1);
                    super.horizontalScrollPosition = Math.min(horizontalScrollPosition, maxHorizontalScrollPosition);
                }
            }
        }
    }

    /**
     *  @private
     *  If there is no horizontal scroll bar, changes the display width of other columns when
     *  one column's width is changed.
     *  @param col column whose width is changed
     *  @param w width of column
     */
    mx_internal function resizeColumn(col:int, w:Number):void
    {
        // there's a window of time before we calccolumnsizes
        // that someone can set width in AS
        if (!visibleColumns || visibleColumns.length == 0)
        {
            _columns[col].setWidth(w);
            _columns[col].preferredWidth = w;
            return;
        }

        if (w < _columns[col].minWidth)
            w = _columns[col].minWidth;

        // hScrollBar is present
        if (_horizontalScrollPolicy == ScrollPolicy.ON ||
            _horizontalScrollPolicy == ScrollPolicy.AUTO)
        {
            // adjust the column's width
            _columns[col].setWidth(w);
            _columns[col].explicitWidth = w;
            _columns[col].preferredWidth = w;
            columnsInvalid = true;
        }
        else
        {
            // find the columns in the set of visible columns;
            var n:int = visibleColumns.length;
            var i:int;
            for (i = 0; i < n; i++)
            {
                if (col == visibleColumns[i].colNum)
                    break;
            }
            if (i >= visibleColumns.length)
                return;
            col = i;

            // we want all cols's new widths to the right of this to be in proportion
            // to what they were before the stretch.

            // get the original space to the right not taken up by the column
            var totalSpace:Number = 0;
            var lastColumn:AdvancedDataGridColumn;
            var newWidth:Number;
            //non-resizable columns don't count though
            var optimumColumns:Array = getOptimumColumns();
            for (i = col + 1; i < n; i++)
            {
                if (optimumColumns[i].resizable)
                    totalSpace += visibleColumns[i].width;
            }

            var newTotalSpace:Number = optimumColumns[col].width - w + totalSpace;
            if (totalSpace)
            {
                optimumColumns[col].setWidth(w);
                optimumColumns[col].explicitWidth = w;
            }

            var totX:Number = 0;
            // resize the columns to the right proportionally to what they were
            for (i = col + 1; i < n; i++)
            {
                if (optimumColumns[i].resizable)
                {
                    newWidth = Math.floor(visibleColumns[i].width
                                          * newTotalSpace / totalSpace);
                    if (newWidth < visibleColumns[i].minWidth)
                        newWidth = visibleColumns[i].minWidth;
                    optimumColumns[i].setWidth(newWidth);
                    totX += optimumColumns[i].width;
                    lastColumn = optimumColumns[i];
                }
            }

            if (totX > newTotalSpace)
            {
                // if excess then should be taken out only from changing column
                // cause others would have already gone to their minimum
                newWidth = optimumColumns[col].width - totX + newTotalSpace;
                if (newWidth < optimumColumns[col].minWidth)
                    newWidth = optimumColumns[col].minWidth;
                optimumColumns[col].setWidth(newWidth);
            }
            else if (lastColumn)
            {
                // if less then should be added in last column
                // dont need to check for minWidth as we are adding
                lastColumn.setWidth(lastColumn.width - totX + newTotalSpace);
            }
        }
        itemsSizeChanged = true;

        updateSubContent();

        invalidateDisplayList();
    }

    /**
     *  Draws the background of the headers into the given 
     *  UIComponent.  The graphics drawn can be scaled horizontally
     *  if the component's width changes, or this method will be
     *  called again to redraw at a different width and/or height
     *
     *  @param headerBG A UIComponent that will contain the header
     *  background graphics.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawHeaderBackground(headerBG:UIComponent):void
    {
        var tot:Number = displayWidth;

        // If we have vScroll only, extend the header over the scrollbar
        if (verticalScrollBar != null &&
            _horizontalScrollPolicy == ScrollPolicy.OFF &&
            headerVisible)
        {
            var bm:EdgeMetrics = borderMetrics;
            var adjustedWidth:Number = unscaledWidth - (bm.left + bm.right);
            tot = adjustedWidth;
            // Need to extend mask too.
            maskShape.width = adjustedWidth;
        }

        var hh:Number = headerRowInfo.length ? headerRowInfo[0].height : headerHeight;

        var g:Graphics = headerBG.graphics;
        g.clear();
        var colors:Array = getStyle("headerColors");
        styleManager.getColorNames(colors);

        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(tot, hh + 1, Math.PI/2, 0, 0);

        colors = [ colors[0], colors[0], colors[1] ];
        var ratios:Array = [ 0, 60, 255 ];
        var alphas:Array = [ 1.0, 1.0, 1.0 ];

        g.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix);
        g.lineStyle(0, 0x000000, 0);
        g.moveTo(0, 0);
        g.lineTo(tot, 0);
        g.lineTo(tot, hh - 0.5);
        g.lineStyle(0, getStyle("borderColor"), 100);
        g.lineTo(0, hh - 0.5);
        g.lineStyle(0, 0x000000, 0);
        g.endFill();
    }

    private function drawHeaderBackgroundSkin(headerBGSkin:IFlexDisplayObject):void
    {
        var tot:Number = displayWidth;

        // If we have vScroll only, extend the header over the scrollbar
        if (verticalScrollBar != null &&
            _horizontalScrollPolicy == ScrollPolicy.OFF &&
            headerVisible)
        {
            var bm:EdgeMetrics = borderMetrics;
            var adjustedWidth:Number = unscaledWidth - (bm.left + bm.right);
            tot = adjustedWidth;
            // Need to extend mask too.
            maskShape.width = adjustedWidth;
        }

        var hh:Number = headerRowInfo.length ? headerRowInfo[0].height : headerHeight;
        headerBGSkin.setActualSize(tot,hh);     
    }

    /**
     *  Draws a row background 
     *  at the position and height specified using the
     *  color specified.  This implementation creates a Shape as a
     *  child of the input Sprite and fills it with the appropriate color.
     *  This method also uses the <code>backgroundAlpha</code> style property 
     *  setting to determine the transparency of the background color.
     * 
     *  @param s A Sprite that will contain a display object
     *  that contains the graphics for that row.
     *
     *  @param rowIndex The row's index in the set of displayed rows.  The
     *  header does not count, the top most visible row has a row index of 0.
     *  This is used to keep track of the objects used for drawing
     *  backgrounds so a particular row can re-use the same display object
     *  even though the index of the item that row is rendering has changed.
     *
     *  @param y The suggested y position for the background.
     * 
     *  @param height The suggested height for the indicator.
     * 
     *  @param color The suggested color for the indicator.
     * 
     *  @param dataIndex The index of the item for that row in the
     *  data provider.  This can be used to color the tenth item differently,
     *  for example.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawRowBackground(s:Sprite, rowIndex:int,
                                         y:Number, height:Number, color:uint, dataIndex:int):void
    {
        var background:Shape;
        if (rowIndex < s.numChildren)
        {
            background = Shape(s.getChildAt(rowIndex));
        }
        else
        {
            background = new FlexShape();
            background.name = "background";
            s.addChild(background);
        }

        background.y = y;

        // Height is usually as tall is the items in the row, but not if
        // it would extend below the bottom of listContent
        var minHeight:Number = Math.min(height,
                                     listContent.height -
                                     y);

        var g:Graphics = background.graphics;
        g.clear();
        g.beginFill(color, getStyle("backgroundAlpha"));
        g.drawRect(0, 0, displayWidth, minHeight);
        g.endFill();
    }

    /**
     *  Draws a column background for a column with the suggested color.
     *  This implementation creates a Shape as a
     *  child of the input Sprite and fills it with the appropriate color.
     *
     *  @param s A Sprite that will contain a display object
     *  that contains the graphics for that column.
     *
     *  @param columnIndex The column's index in the set of displayed columns.  
     *  The left-most visible column has a column index of 0.
     *  This is used to keep track of the objects used for drawing
     *  backgrounds, so a particular column can re-use the same display object
     *  even though the index of the AdvancedDataGridColumn for that column has changed.
     *
     *  @param color The suggested color for the indicator.
     * 
     *  @param column The column of the AdvancedDataGrid control that you are drawing the background for.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawColumnBackground(s:Sprite, columnIndex:int,
                                            color:uint, column:AdvancedDataGridColumn):void
    {
        var background:Shape;
        background = Shape(s.getChildByName(columnIndex.toString()));
        if (!background)
        {
            background = new FlexShape();
            s.addChild(background);
            background.name = columnIndex.toString();
        }

        var g:Graphics = background.graphics;
        g.clear();

        if(columnIndex >= lockedColumnCount && 
           columnIndex < lockedColumnCount + horizontalScrollPosition)
            return;

        g.beginFill(color);

        var lastRow:Object = rowInfo[listItems.length - 1];
        var headerInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(getOptimumColumns()[columnIndex]);
        var xx:Number = headerInfo.headerItem.x;
        if(columnIndex >= lockedColumnCount)
            xx = getAdjustedXPos(xx);
        var yy:Number = headerRowInfo[0].y;

        if (headerVisible)
            yy += headerRowInfo[0].height;

        // Height is usually as tall is the items in the row, but not if
        // it would extend below the bottom of listContent
        var height:Number = Math.min(lastRow.y + lastRow.height,
                                     listContent.height - yy);

        g.drawRect(xx, yy, headerInfo.headerItem.width, height);
        g.endFill();
    }

    /**
     *  Creates and sizes the horizontalSeparator skins. If none have been specified, then draws the lines using
     *  drawHorizontalLine(). 
     *  
     *  @private
     */
    private function drawHorizontalSeparator(s:Sprite, rowIndex:int, color:uint, y:Number):void
    {
        var useLockedSeparator:Boolean = false;

        if (lockedRowCount > 0 && rowIndex == lockedRowCount - 1)
        {
            useLockedSeparator = true;
        }

        var hSepSkinName:String = "hSeparator" + rowIndex;
        var hLockedSepSkinName:String = "hLockedSeparator" + rowIndex;
        var createThisSkinName:String = useLockedSeparator ? hLockedSepSkinName : hSepSkinName;
        var createThisStyleName:String = useLockedSeparator ? "horizontalLockedSeparatorSkin" : "horizontalSeparatorSkin";

        var sepSkin:IFlexDisplayObject;
        var lockedSepSkin:IFlexDisplayObject;
        var deleteThisSkin:IFlexDisplayObject;
        var createThisSkin:IFlexDisplayObject;

        // Look for separator by name
        sepSkin = IFlexDisplayObject(s.getChildByName(hSepSkinName));
        lockedSepSkin = IFlexDisplayObject(s.getChildByName(hLockedSepSkinName));

        createThisSkin = useLockedSeparator ? lockedSepSkin : sepSkin;
        deleteThisSkin = useLockedSeparator ? sepSkin : lockedSepSkin;

        if (deleteThisSkin)
        {
            s.removeChild(DisplayObject(deleteThisSkin));
            //delete deleteThisSkin;
        }

        if (!createThisSkin)
        {
            var sepSkinClass:Class = Class(getStyle(createThisStyleName));

            if (sepSkinClass)
            {
                createThisSkin = IFlexDisplayObject(new sepSkinClass());
                createThisSkin.name = createThisSkinName;

                var styleableSkin:ISimpleStyleClient = createThisSkin as ISimpleStyleClient;
                if (styleableSkin)
                    styleableSkin.styleName = this;

                s.addChild(DisplayObject(createThisSkin));
            }
        }

        if (createThisSkin)
        {
            var mHeight:Number = !isNaN(createThisSkin.measuredHeight) ? createThisSkin.measuredHeight : 1;
            createThisSkin.setActualSize(displayWidth, mHeight); 
            createThisSkin.move(0, y);     
        }
        else // If we still don't have a sepSkin, then we have no skin style defined. Use the default function instead
        {
            drawHorizontalLine(s, rowIndex, color, y);
        }

    }

    /**
     *  Draws a line between rows.  This implementation draws a line
     *  directly into the given Sprite.  The Sprite has been cleared
     *  before lines are drawn into it.
     *
     *  @param s A Sprite that will contain a display object
     *  that contains the graphics for that row.
     *
     *  @param rowIndex The row's index in the set of displayed rows.  The
     *  header does not count; the top-most visible row has a row index of 0.
     *  This is used to keep track of the objects used for drawing
     *  backgrounds so a particular row can re-use the same display object
     *  even though the index of the item that row is rendering has changed.
     *
     *  @param color The suggested color for the indicator.
     * 
     *  @param y The suggested y position for the background.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawHorizontalLine(s:Sprite, rowIndex:int, color:uint, y:Number):void
    {
        var g:Graphics = s.graphics;

        if (lockedRowCount > 0 && rowIndex == lockedRowCount-1)
            g.lineStyle(1, 0);
        else
            g.lineStyle(1, color);
        
        g.moveTo(0, y);
        g.lineTo(displayWidth, y);
    }

    /**
     *  Creates and sizes the verticalSeparator skins. If none have been specified, then draws the lines using
     *  drawVerticalLine(). 
     *  
     *  @private
     */
    private function drawVerticalSeparator(s:Sprite, colIndex:int, color:uint, x:Number, y:Number):void
    {
        var useLockedSeparator:Boolean = false;

        if (lockedColumnCount > 0 && colIndex == lockedColumnCount-1)
        {
            useLockedSeparator = true;
        }

        var vSepSkinName:String = "vSeparator" + colIndex;
        var vLockedSepSkinName:String = "vLockedSeparator" + colIndex;
        var createThisSkinName:String = useLockedSeparator ? vLockedSepSkinName : vSepSkinName;
        var createThisStyleName:String = useLockedSeparator ? "verticalLockedSeparatorSkin" : "verticalSeparatorSkin";

        var sepSkin:IFlexDisplayObject;
        var lockedSepSkin:IFlexDisplayObject;
        var deleteThisSkin:IFlexDisplayObject;
        var createThisSkin:IFlexDisplayObject;

        // Look for separator by name
        sepSkin = IFlexDisplayObject(s.getChildByName(vSepSkinName));
        lockedSepSkin = IFlexDisplayObject(s.getChildByName(vLockedSepSkinName));

        createThisSkin = useLockedSeparator ? lockedSepSkin : sepSkin;
        deleteThisSkin = useLockedSeparator ? sepSkin : lockedSepSkin;

        if (deleteThisSkin)
        {
            s.removeChild(DisplayObject(deleteThisSkin));
            //delete deleteThisSkin;
        }

        if (!createThisSkin)
        {
            var sepSkinClass:Class = Class(getStyle(createThisStyleName));

            if (sepSkinClass)
            {
                createThisSkin = IFlexDisplayObject(new sepSkinClass());
                createThisSkin.name = createThisSkinName;

                var styleableSkin:ISimpleStyleClient = createThisSkin as ISimpleStyleClient;
                if (styleableSkin)
                    styleableSkin.styleName = this;

                s.addChild(DisplayObject(createThisSkin));
            }
        }

        if (createThisSkin)
        {
            var mWidth:Number = !isNaN(createThisSkin.measuredWidth) ? createThisSkin.measuredWidth : 1;
            createThisSkin.setActualSize(mWidth, listContent.height); 
            createThisSkin.move(x, y);     
        }
        else // If we still don't have a sepSkin, then we have no skin style defined. Use the default function instead
        {
            drawVerticalLine(s, colIndex, color, x);
        }

    }

    /**
     *  Draws lines between columns.  This implementation draws a line
     *  directly into the given Sprite.  The Sprite has been cleared
     *  before lines are drawn into it.
     *
     *  @param s A Sprite that will contain a display object
     *  that contains the graphics for that row.
     *
     *  @param columnIndex The column's index in the set of displayed columns.  
     *  The left most visible column has a column index of 0.
     *
     *  @param color The suggested color for the indicator.
     * 
     *  @param x The suggested x position for the background.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawVerticalLine(s:Sprite, colIndex:int, color:uint, x:Number):void
    {
        //draw our vertical lines
        var g:Graphics = s.graphics;
        if (lockedColumnCount > 0 && colIndex == lockedColumnCount - 1)
            g.lineStyle(1, 0, 100);
        else
            g.lineStyle(1, color, 100);
        
        var tempY:Number = 0;
        if(headerVisible)
        {
            //In case of lockedColumn line, we start it from the top, so that it comes
            //in the header area as well
            if(lockedColumnCount > 0 && colIndex == lockedColumnCount - 1)
            {
                g.moveTo(x, 1);
                g.lineTo(x, headerItems[0][colIndex].height);
            }
            else
                tempY = headerItems[0][colIndex].height;
                
        }

        // draw line from tempY to listContent's height
        g.moveTo(x, tempY);
        g.lineTo(x, listContent.height);
    }

    /**
     *  Draws lines between columns, and column backgrounds.
     *  This implementation calls the <code>drawHorizontalLine()</code>, 
     *  <code>drawVerticalLine()</code>,
     *  and <code>drawColumnBackground()</code> methods as needed.  
     *  It creates a
     *  Sprite that contains all of these graphics and adds it as a
     *  child of the <code>listContent</code> at the front of the z-order.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawLinesAndColumnBackgrounds():void
    {
        var lines:Sprite = getLines();
        lines.graphics.clear();

        var len:uint = getNumColumns();
        len = (len != -1)? len : visibleColumns.length;
        // defend against degenerate case when width == 0
        var optimumColumns:Array = getOptimumColumns();
        if (len > optimumColumns.length)
            len = optimumColumns.length;

        // draw horizontal lines
        drawHorizontalSeparators();

        // draw vertical lines
        drawVerticalSeparators();

        // draw column backgrounds
        if (headerInfos && hasHeaderItemsCreated(0) && hasHeaderItemsCreated(len-1))
        {
            var colBGs:Sprite = Sprite(listContent.getChildByName("colBGs"));
            // traverse the columns, set the sizes, draw the column backgrounds
            var lastChild:int = -1;
            for (var i:int = 0; i < len; i++)
            {
                var col:AdvancedDataGridColumn = optimumColumns[i];
                var bgCol:Object;
                if (enabled)
                    bgCol = col.getStyle("backgroundColor");
                else
                    bgCol = col.getStyle("backgroundDisabledColor");

                if (bgCol !== null && !isNaN(Number(bgCol)))
                {
                    if (!colBGs)
                    {
                        colBGs = new FlexSprite();
                        colBGs.mouseEnabled = false;
                        colBGs.name = "colBGs";
                        listContent.addChildAt(colBGs, listContent.getChildIndex(listContent.getChildByName("rowBGs")) + 1);
                    }
                    drawColumnBackground(colBGs, i, Number(bgCol), col);
                    lastChild = i;
                }
                else if (colBGs)
                {
                    var background:Shape = Shape(colBGs.getChildByName(i.toString()));
                    if (background)
                    {
                        var g:Graphics = background.graphics;
                        g.clear();
                        colBGs.removeChild(background);
                    }
                }
            }
            if (colBGs && colBGs.numChildren)
            {
                while (colBGs.numChildren)
                {
                    var bg:DisplayObject = colBGs.getChildAt(colBGs.numChildren - 1);
                    if (parseInt(bg.name) > lastChild)
                        colBGs.removeChild(bg);
                    else
                        break;
                }
            }
        }
    }

    /**
     *  @private
     * 
     *  Call drawHorizontalSeparator() to draw horizontal lines
     */
    protected function drawHorizontalSeparators():void
    {
        // draw horizontalGridlines if needed.
        var lineCol:uint = getStyle("horizontalGridLineColor");
        
        var lockedContent:Sprite = getLockedContent();

        // draw vertical lines in the locked column area        
        var lockedLinesBody:Sprite = Sprite(lockedContent.getChildByName("lockedHorizontalLines"));

        if (lockedLinesBody)
        {
            lockedLinesBody.graphics.clear();
        
            while (lockedLinesBody.numChildren)
            {
                lockedLinesBody.removeChildAt(0);
            }
        }

        //In case of horizontal lines we don't need to care
        //about column locking a line from 0-displayWidth will do
        if (getStyle("horizontalGridLines")
            || lockedRowCount > 0 && lockedRowCount < listItems.length)
        {
            if (!lockedLinesBody)
            {
                lockedLinesBody = new UIComponent();
                lockedLinesBody.name = "lockedHorizontalLines";
                lockedContent.addChild(lockedLinesBody);
            }
            
            if (getStyle("horizontalGridLines"))
            {
                var n:int = listItems.length;
                for (var i:int = 0; i < n; i++)
                {
                    drawHorizontalSeparator(lockedLinesBody, i, lineCol, rowInfo[i].y + rowInfo[i].height);
                }
            }
            else
            {
                drawHorizontalSeparator(lockedLinesBody, lockedRowCount - 1 , lineCol, rowInfo[lockedRowCount - 1].y + rowInfo[lockedRowCount - 1].height);
            }
        }
    }

    /**
     *  @private
     * 
     *  Call drawVerticalSeparator() to draw vertical lines
     */
    protected function drawVerticalSeparators():void
    {
        var lines:Sprite = getLines();

        var lockedContent:Sprite = getLockedContent();
        
        // draw vertical lines in the locked column area        
        var lockedLinesBody:Sprite = Sprite(lockedContent.getChildByName("lockedVerticalLines"));

        if (!lockedLinesBody)
        {
            lockedLinesBody = new UIComponent();
            lockedLinesBody.name = "lockedVerticalLines";
            lockedContent.addChild(lockedLinesBody);
        }
        
        // Make sure that the lockedLinesBody are on a higher index in the childList
        // of lockedContent as compared to resizing separators
        var child:UIComponent = UIComponent(lockedContent.getChildByName("lockedHeaderLines"));
        if(child)
        {
            var childIndex:int = lockedContent.getChildIndex(DisplayObject(child));
            if(childIndex > lockedContent.getChildIndex(DisplayObject(lockedLinesBody)))
                lockedContent.setChildIndex(lockedLinesBody, childIndex);
        }

        lockedLinesBody.graphics.clear();
        
        while (lockedLinesBody.numChildren)
        {
            lockedLinesBody.removeChildAt(0);
        }

        var yVal:Number = (headerVisible && headerRowInfo && headerRowInfo[0]) ? headerRowInfo[0].height : 0;
        var len:uint = Math.min((visibleColumns ? visibleColumns.length : 0), Math.max(0,lockedColumnCount));
        var vLines:Boolean = getStyle("verticalGridLines");
        var lineCol:uint = getStyle("verticalGridLineColor");
        if (vLines && len)
        {           
            for (var i:int = 0; i < len; i++)
            {
                drawVerticalSeparator(lockedLinesBody, i, lineCol, 
                                      getHeaderInfo(visibleColumns[i]).headerItem.x + visibleColumns[i].width, yVal);
            }
        }

        // draw vertical lines in the scrollable area
        var linesBody:Sprite = getLinesBody(lines, "verticalLines");

        // clear the vertical lines and draw them again
        linesBody.graphics.clear();
        
        while (linesBody.numChildren)
        {
            linesBody.removeChildAt(0);
        }

        len = visibleColumns.length;

        // defend against degenerate case when width == 0
        if (len > visibleColumns.length)
            len = visibleColumns.length;

        vLines = getStyle("verticalGridLines");
        lineCol = getStyle("verticalGridLineColor");

        if (vLines && headerInfos && hasHeaderItemsCreated(0) && hasHeaderItemsCreated(len - 1))
        {
            //Check against the negative case
            var lockedColCount:int = Math.max(0, lockedColumnCount);
            
            for (i = lockedColCount; i < len - 1; i++)
            {
                var headerInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(visibleColumns[i]);
                
                drawVerticalSeparator(linesBody, absoluteToVisibleColumnIndex(visibleColumns[i].colNum), lineCol, 
                                      headerInfo.headerItem.x + visibleColumns[i].width, yVal);
            }
        }

        // is this drawing the vertical locked column indicator?
        if (!vLines && lockedColumnCount > 0 && lockedColumnCount < len)
            drawVerticalSeparator(linesBody, lockedColumnCount - 1, lineCol, 
                                  getHeaderInfo(visibleColumns[lockedColumnCount-1]).headerItem.x 
                                  + visibleColumns[lockedColumnCount - 1].width, 0);
    }

    /**
     *  @private
     * 
     *  Get the 'lockedContent' Sprite 
     */
    private function getLockedContent():Sprite
    {
        var locked:Sprite = Sprite(listContent.getChildByName("lockedContent"));
        if (!locked)
        {
            locked = new UIComponent();
            locked.name = "lockedContent";
            locked.cacheAsBitmap = true;
            locked.mouseEnabled = false;
            listContent.addChild(locked);
        }
        listContent.setChildIndex(locked, listContent.numChildren - 1);

        return locked;
    }

    /**
     *  @private
     * 
     *  Get the 'lines' Sprite 
     */
    private function getLines():Sprite
    {
        var lines:Sprite = Sprite(listSubContent.getChildByName("lines"));
        if (!lines)
        {
            lines = new UIComponent();
            lines.name = "lines";
            lines.cacheAsBitmap = true;
            lines.mouseEnabled = false;
            listSubContent.addChild(lines);
        }
        listSubContent.setChildIndex(lines, listSubContent.numChildren - 1);

        return lines;
    }

    /**
     *  @private
     * 
     *  Get the Sprite for horizontal/vertical lines
     */
    private function getLinesBody(lines:Sprite, linesBodyName:String):Sprite
    {
        var linesBody:Sprite = Sprite(lines.getChildByName(linesBodyName));

        if (!linesBody)
        {
            linesBody = new UIComponent();
            linesBody.name = linesBodyName;
            lines.addChild(linesBody);
        }

        return linesBody;
    }

    /**
     *  Removes column header separators that you normally use
     *  to resize columns.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function clearSeparators():void
    {
        if (!separators)
            return;

        var lines:Sprite = Sprite(listSubContent.getChildByName("lines"));
        var headerLines:Sprite = Sprite(lines.getChildByName("header"));
        if (headerLines)
        {
            while (headerLines.numChildren)
            {
                headerLines.removeChildAt(headerLines.numChildren - 1);
                separators.pop();
            }
        }

        var lockedContent:Sprite = getLockedContent();
        headerLines = Sprite(lockedContent.getChildByName("lockedHeaderLines"));
        if (headerLines)
        {
            while (headerLines.numChildren)
            {
                headerLines.removeChildAt(headerLines.numChildren - 1);
                lockedSeparators.pop();
            }
        }
    }

    /**
     *  Creates and displays the column header separators that the user 
     *  normally uses to resize columns.  This implementation uses
     *  the same Sprite as the lines and column backgrounds, adds
     *  instances of the <code>headerSeparatorSkin</code>, and attaches mouse
     *  listeners to them in order to know when the user wants
     *  to resize a column.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawSeparators():void
    {
        var lines:Sprite = getLines();
        lines.graphics.clear();
        
        var optimumColumns:Array = getOptimumColumns();

        if (headerSepSkinChanged)
        {
            headerSepSkinChanged = false;
            clearSeparators();
        }

        if (!separators)
        {
            separators = [];
            lockedSeparators = [];
        }

        lines = Sprite(listSubContent.getChildByName("lines"));

        var actualLocked:int = 0;
        var allColsLocked:Boolean = false;
        var numUnLockedSeparators:int = Math.max(0, optimumColumns.length - 1);
        
        var lockedContent:Sprite = getLockedContent();
        var lockedHeaderLines:UIComponent = UIComponent(lockedContent.getChildByName("lockedHeaderLines"));
        var headerLines:UIComponent = UIComponent(lines.getChildByName("header"));
        
        if(optimumColumns && optimumColumns.length > 0)
        {
            if (lockedColumnCount > 0)
            {
                actualLocked = Math.min(lockedColumnCount, optimumColumns.length); 
                allColsLocked = (actualLocked == optimumColumns.length);

                // -1 because we need one less separator, thus when all columns are 
                // locked, we dont draw separator after last column
                if(allColsLocked)
                    actualLocked--;

                //Number of separators left to be drawn in the scrollable area have reduced by actualLocked
                numUnLockedSeparators = numUnLockedSeparators - actualLocked;

                // Drawing a separator at lockedColumn boundary is required for resize cursor to appear
                // when mouse is coming from right
                if(!allColsLocked)
                    numUnLockedSeparators++;

                //Create only if needed i.e lockedColumnCount > 0
                if (!lockedHeaderLines)
                {
                    lockedHeaderLines = new UIComponent();
                    lockedHeaderLines.name = "lockedHeaderLines";
                    lockedContent.addChild(lockedHeaderLines);
                }
            }
            
            if(lockedHeaderLines)
                createHeaderSeparators(actualLocked, lockedSeparators, lockedHeaderLines);

            if (!headerLines)
            {
                headerLines = new UIComponent();
                headerLines.name = "header";
                lines.addChild(headerLines);    
            }

            // Create separators for columns which are not locked
            // -1 because we need one less separator
            createHeaderSeparators(numUnLockedSeparators, separators, headerLines);
        }
        
        // remove extra locked separators
        if(lockedHeaderLines)
            removeExtraSeparators(actualLocked, lockedSeparators, lockedHeaderLines);
        
        // remove extra unlocked separators
        if (headerLines)
            removeExtraSeparators(numUnLockedSeparators, separators, headerLines);
    }

    /**
     *  Returns the header separators between column headers, 
     *  and populates the <code>separators</code> Array with the separators returned.
     * 
     *  @param i The number of separators to return.
     *
     *  @param seperators Array to be populated with the header objects.
     *
     *  @param headerLines The parent component of the header separators. 
     *  Flex calls the <code>headerLines.getChild()</code> method internally to return the separators.
     *
     *  @return The header separators between column headers.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */        
    protected function getSeparator(i:int, seperators:Array, headerLines:UIComponent):UIComponent
    {
        var sep:UIComponent;
        var sepSkin:IFlexDisplayObject;

        if (i < headerLines.numChildren)
        {
            sep = UIComponent(headerLines.getChildAt(i));
            sepSkin = IFlexDisplayObject(sep.getChildAt(0));
        }
        else
        {
            var headerSeparatorClass:Class =
                getStyle("headerSeparatorSkin");
            sepSkin = new headerSeparatorClass();
            if (sepSkin is ISimpleStyleClient)
                ISimpleStyleClient(sepSkin).styleName = this;
            sep = new UIComponent();
            sep.addChild(DisplayObject(sepSkin));
            headerLines.addChild(sep);
            DisplayObject(sep).addEventListener(
                MouseEvent.MOUSE_OVER, columnResizeMouseOverHandler);
            DisplayObject(sep).addEventListener(
                MouseEvent.MOUSE_OUT, columnResizeMouseOutHandler);
            DisplayObject(sep).addEventListener(
                MouseEvent.MOUSE_DOWN, columnResizeMouseDownHandler);
            seperators.push(sep);
        }
        return sep;
    }
    
    
    /**
     *  Creates the header separators between column headers, 
     *  and populates the <code>separators</code> Array with the separators created.
     * 
     *  @param n The number of separators to create.
     *
     *  @param seperators Array to be populated with the header objects.
     *
     *  @param headerLines The parent component of the header separators to which the separators are added. 
     *  That is, Flex calls the <code>headerLines.addChild()</code> method internally to add the separators to the display.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */        
    protected function createHeaderSeparators(n:int, seperators:Array, headerLines:UIComponent):void
    {
        var optimumColumns:Array = getOptimumColumns();

        for (var i:int = 0; i < n; i++)
        {
            var headerItemIndex:int = (lockedColumnCount > 0 && seperators != lockedSeparators) ? i+lockedColumnCount - 1 : i;
            
            var sep:UIComponent = getSeparator(i, seperators, headerLines);
            var sepSkin:IFlexDisplayObject = IFlexDisplayObject(sep.getChildAt(0));
            if (!headerItems || !headerItems[0] || !headerItems[0][headerItemIndex])
            {
                sep.visible = false;
                continue;
            }

            sep.visible = true;
            sep.x = headerItems[0][headerItemIndex].x +
                optimumColumns[headerItemIndex].width - Math.round(sep.measuredWidth / 2 + 0.5);

            if (i > 0)
            {
                sep.x = Math.max(sep.x,
                                 seperators[i - 1].x + Math.round(sep.measuredWidth / 2 + 0.5));
            }
            sep.y = 0;

            sepSkin.setActualSize(sepSkin.measuredWidth,
                                  headerRowInfo.length ?
                                  headerRowInfo[0].height :
                                  headerHeight);

            // Draw invisible background for separator affordance
            sep.graphics.clear();
            sep.graphics.beginFill(0xFFFFFF, 0);
            sep.graphics.drawRect(-separatorAffordance, 0, sepSkin.measuredWidth + separatorAffordance , headerHeight);
            sep.graphics.endFill();
        }
    }
    
    /**
     *  @private
     *  removes the extra separators
     */
    private function removeExtraSeparators(n:int, seperators:Array, headerLines:UIComponent):void
    {
        while (headerLines.numChildren > n)
        {
            headerLines.removeChildAt(headerLines.numChildren - 1);
            seperators.pop();
        }
    }

    /**
     *  @private
     *  Update sortIndex and sortDirection based on sort info availabled in
     *  underlying data provider.
     */
    private function updateSortIndexAndDirection():void
    {
        // Don't show sort indicator if sortableColumns is false or if the
        // column sorted on has sortable="false"

        if (!sortableColumns)
        {
            lastSortIndex = sortIndex;
            sortIndex = -1;

            if (lastSortIndex != sortIndex)
                invalidateDisplayList();

            return;
        }

        if (!dataProvider)
            return;

        var view:ICollectionView = ICollectionView(dataProvider);
        var sort:ISort = view.sort;
        if (!sort)
        {
            sortIndex = lastSortIndex = -1;
            return;
        }

        var fields:Array = sort.fields;
        if (!fields)
            return;

        if (fields.length != 1)
        {
            lastSortIndex = sortIndex;
            sortIndex = -1;

            if (lastSortIndex != sortIndex)
                invalidateDisplayList();

            return;
        }

        // fields.length == 1, so the collection is sorted on a single field.
        var sortField:ISortField = fields[0];
        var n:int = _columns.length;
        for (var i:int = 0; i < n; i++)
        {
            if (_columns[i].dataField == sortField.name)
            {
                sortIndex = _columns[i].sortable ? i : -1;
                sortDirection = sortField.descending ? "DESC" : "ASC";
                return;
            }
        }
    }

    /**
     *  @private
     */
    private function setEditedItemPosition(coord:Object):void
    {
        bEditedItemPositionChanged = true;
        _proposedEditedItemPosition = coord;
        invalidateDisplayList();
    }

    /**
     *  @private
     *  focus an item renderer in the grid - harder than it looks
     */
    private function commitEditedItemPosition(coord:Object):void
    {
        if (!enabled || !editable.length)
            return;

        // just give focus back to the itemEditorInstance
        if (itemEditorInstance && coord &&
            itemEditorInstance is IFocusManagerComponent &&
            _editedItemPosition.rowIndex == coord.rowIndex &&
            _editedItemPosition.columnIndex == coord.columnIndex)
        {
            IFocusManagerComponent(itemEditorInstance).setFocus();
            return;
        }

        // dispose of any existing editor, saving away its data first
        if (itemEditorInstance)
        {
            var reason:String;
            if (!coord)
            {
                reason = AdvancedDataGridEventReason.OTHER;
            }
            else
            {
                reason = (!editedItemPosition || coord.rowIndex == editedItemPosition.rowIndex) ?
                    AdvancedDataGridEventReason.NEW_COLUMN :
                    AdvancedDataGridEventReason.NEW_ROW;
            }
            if (!endEdit(reason) && reason != AdvancedDataGridEventReason.OTHER)
                return;
        }

        // store the value
        _editedItemPosition = coord;

        // allow setting of undefined to dispose item editor instance
        if (!coord)
            return;

        if (dontEdit)
        {
            return;
        }

        var rowIndex:int = coord.rowIndex;
        var colIndex:int = coord.columnIndex;
        if (displayableColumns.length != _columns.length)
        {
            var n:int = displayableColumns.length;
            for (var i:int = 0; i < n; i++)
            {
                if (displayableColumns[i].colNum >= colIndex)
                {
                    colIndex = i;
                    break;
                }
            }
            if (i == displayableColumns.length)
                colIndex = 0;
        }

        // trace("commitEditedItemPosition ", coord.rowIndex, selectedIndex);

        var needChangeEvent:Boolean = false;
        if (selectedIndex != coord.rowIndex)
        {
            commitSelectedIndex(coord.rowIndex);
            needChangeEvent = true;
        }

        var actualLockedRows:int = lockedRowCount;
        var lastRowIndex:int = verticalScrollPosition + listItems.length - 1;
        var partialRow:int = (rowInfo[listItems.length - 1].y + rowInfo[listItems.length - 1].height > listContent.height) ? 1 : 0;

        // actual row/column is the offset into listItems
        if (rowIndex > actualLockedRows)
        {
            // not a locked editable row make sure it is on screen
            if (rowIndex < verticalScrollPosition + actualLockedRows)
                verticalScrollPosition = rowIndex - actualLockedRows;
            else
            {
                // variable row heights means that we can't know how far to scroll sometimes so we loop
                // until we get it right
                while (rowIndex > lastRowIndex ||
                       // we're the last row, and we're partially visible, but we're not
                       // the top scrollable row already
                       (rowIndex == lastRowIndex && rowIndex > verticalScrollPosition + actualLockedRows &&
                        partialRow))
                {
                    if (verticalScrollPosition == maxVerticalScrollPosition)
                        break;
                    verticalScrollPosition = Math.min(verticalScrollPosition + (rowIndex > lastRowIndex ? rowIndex - lastRowIndex : partialRow), maxVerticalScrollPosition);
                    lastRowIndex = verticalScrollPosition + listItems.length - 1;
                    partialRow = (rowInfo[listItems.length - 1].y + rowInfo[listItems.length - 1].height > listContent.height) ? 1 : 0;
                }
            }
            actualRowIndex = rowIndex - verticalScrollPosition;
        }
        else
        {
            if (rowIndex == actualLockedRows)
                verticalScrollPosition = 0;

            actualRowIndex = rowIndex;
        }

        var bm:EdgeMetrics = borderMetrics;

        var len:uint = /*(headerItems && headerItems[0]) ? headerItems[0].length :*/ visibleColumns.length;
        var lastColIndex:int = horizontalScrollPosition + len - 1;

        // TODO with locked columns this won't give correct results?
        var headerInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(visibleColumns[visibleColumns.length-1]);
        var partialCol:int = (headerInfo.headerItem.x + headerInfo.column.width
                                > listContent.width) ? 1 : 0;

        if(colIndex > lockedColumnCount)
        {
            if (colIndex < horizontalScrollPosition + lockedColumnCount)
            {
                horizontalScrollPosition = colIndex - lockedColumnCount;
            }
            else
            {
                while (colIndex > lastColIndex ||
                       (colIndex == lastColIndex && colIndex > horizontalScrollPosition + lockedColumnCount &&
                        partialCol))
                {
                    if (horizontalScrollPosition == maxHorizontalScrollPosition)
                        break;
                    horizontalScrollPosition = Math.min(horizontalScrollPosition + (colIndex > lastColIndex ? colIndex - lastColIndex : partialCol), maxHorizontalScrollPosition);

                    lastColIndex = horizontalScrollPosition + visibleColumns.length - 1;
                    headerInfo = getHeaderInfo(visibleColumns[visibleColumns.length - 1]);
                    partialCol = (headerInfo.headerItem && headerInfo.headerItem.x + headerInfo.headerItem.width > listContent.width) ? 1 : 0;
                }
            }
            // Need to get the index in visibleColumns
            actualColIndex = absoluteToVisibleColumnIndex(displayToAbsoluteColumnIndex(colIndex));
        }
        else
        {
            if (colIndex == lockedColumnCount)
                horizontalScrollPosition = 0;

            actualColIndex = colIndex;
        }

        // get the actual references for the column, row, and item
        var item:IListItemRenderer;
        if (listItems[actualRowIndex] && listItems[actualRowIndex][actualColIndex])
            item = listItems[actualRowIndex][actualColIndex];
        if (!item)
        {
            // assume that editing was cancelled
            commitEditedItemPosition(null);
            return;
        }

        if (needChangeEvent)
        {
            var evt:ListEvent = new ListEvent(ListEvent.CHANGE);
            evt.columnIndex = coord.columnIndex;
            evt.rowIndex = coord.rowIndex;;
            evt.itemRenderer = item;
            dispatchEvent(evt);
        }

        var event:AdvancedDataGridEvent =
            new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_EDIT_BEGIN, false, true);
        // ITEM_EDIT events are cancelable
        event.columnIndex = displayableColumns[colIndex].colNum;
        event.rowIndex = _editedItemPosition.rowIndex;
        event.itemRenderer = item;
        dispatchEvent(event);

        lastEditedItemPosition = _editedItemPosition;

        // user may be trying to change the focused item renderer
        if (bEditedItemPositionChanged)
        {
            bEditedItemPositionChanged = false;
            commitEditedItemPosition(_proposedEditedItemPosition);
            _proposedEditedItemPosition = undefined;

        }

        if (!itemEditorInstance)
        {
            // assume that editing was cancelled
            commitEditedItemPosition(null);
        }
    }

    /**
     *  Creates the item editor for the item renderer at the
     *  <code>editedItemPosition</code> using the editor
     *  specified by the <code>itemEditor</code> property.
     *
     *  <p>This method sets the editor instance as the 
     *  <code>itemEditorInstance</code> property.</p>
     *
     *  <p>You may only call this method from within the event listener
     *  for the <code>itemEditBegin</code> event. 
     *  To create an editor at other times, set the
     *  <code>editedItemPosition</code> property to generate 
     *  the <code>itemEditBegin</code> event.</p>
     *
     *  @param colIndex The column index in the data provider of the item to be edited.
     *
     *  @param rowIndex The row index in the data provider of the item to be edited.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function createItemEditor(colIndex:int, rowIndex:int):void
    {
        if (displayableColumns.length != _columns.length)
        {
            var n:int = displayableColumns.length;
            for (var i:int = 0; i < n; i++)
            {
                if (displayableColumns[i].colNum >= colIndex)
                {
                    colIndex = i;
                    break;
                }
            }
            if (i == displayableColumns.length)
                colIndex = 0;
        }

        var col:AdvancedDataGridColumn = displayableColumns[colIndex];
        if (rowIndex > lockedRowCount)
            rowIndex -= verticalScrollPosition;

        if (colIndex > lockedColumnCount)
            colIndex -= horizontalScrollPosition;

        var item:IListItemRenderer;
        item = listItems[actualRowIndex][actualColIndex];
        
        var rowData:ListRowInfo = rowInfo[actualRowIndex];

        // Before the editor opens up, change the label to the original data
        // and not the label which is (possibly) formatted data.
        // See AdvancedDataGridColumn.itemToLabel() regarding formatter.
        if (item is IDropInListItemRenderer)
            IDropInListItemRenderer(item).listData.label = col.itemToLabel(item.data, false);

        if (!col.rendererIsEditor)
        {
            var dx:Number = 0;
            var dy:Number = -2;
            var dw:Number = 0;
            var dh:Number = 4;
            // if this isn't implemented, use an input control as editor
            if (!itemEditorInstance)
            {
                var itemEditor:IFactory = col.itemEditor;
                if (itemEditor == AdvancedDataGridColumn.defaultItemEditorFactory)
                {
                    // if it is the default factory, see if someone
                    // overrode it with this style
                    var c:Class = getStyle("defaultDataGridItemEditor");
                    if (c)
                    {
                        var fontName:String =
                            StringUtil.trimArrayElements(col.getStyle("fontFamily"), ",");
                        var fontWeight:String = col.getStyle("fontWeight");
                        var fontStyle:String = col.getStyle("fontStyle");
                        var bold:Boolean = (fontWeight == "bold");
                        var italic:Boolean = (fontStyle == "italic");
                        
                        var flexModuleFactory:IFlexModuleFactory =
                            getFontContext(fontName, bold, italic);
                        
                        itemEditor = col.itemEditor = new ContextualClassFactory(
                            c, flexModuleFactory);
                    }
                }
                
                dx = col.editorXOffset;
                dy = col.editorYOffset;
                dw = col.editorWidthOffset;
                dh = col.editorHeightOffset;
                itemEditorInstance = itemEditor.newInstance();
                itemEditorInstance.owner = this;
                itemEditorInstance.styleName = col;
                addRendererToContentArea(itemEditorInstance, col);
            }
            itemEditorInstance.parent.setChildIndex(DisplayObject(itemEditorInstance), 
                                                    itemEditorInstance.parent.numChildren - 1);
            // give it the right size, look and placement
            itemEditorInstance.visible = true;

            var itemXPos:Number = item.x + dx;
            
            itemEditorInstance.move(itemXPos, rowData.y + dy);

            // Original code:
            /*
              itemEditorInstance.setActualSize(Math.min(col.width + dw, 
              listContent.width - listContent.x - itemXPos),
              Math.min(rowData.height + dh, listContent.height - listContent.y - itemEditorInstance.y));
              DisplayObject(itemEditorInstance).addEventListener(FocusEvent.FOCUS_OUT, itemEditorFocusOutHandler);
              listContent.width - listContent.x - itemXPos),
              Math.min(rowData.height + dh, listContent.height - listContent.y - itemEditorInstance.y));
            */

            // To support column spanning:
            itemEditorInstance.setActualSize(editedItemRenderer.width + dw,
                                             Math.min(rowData.height + dh,
                                                      listContent.height - listContent.y - itemEditorInstance.y));

            DisplayObject(itemEditorInstance).addEventListener(FocusEvent.FOCUS_OUT, itemEditorFocusOutHandler);
            // Commenting to show the item (with disclosure icon) behind the item editor
            //item.visible = false;

            layoutItemEditor();
        }
        else
        {
            // if the item renderer is also the editor, we'll use it
            itemEditorInstance = item;
        }

        // listen for keyStrokes on the itemEditorInstance (which lets the grid supervise for ESC/ENTER)
        DisplayObject(itemEditorInstance).addEventListener(KeyboardEvent.KEY_DOWN, editorKeyDownHandler);
        // we disappear on any mouse down outside the editor
        systemManager.getSandboxRoot().
            addEventListener(MouseEvent.MOUSE_DOWN, editorMouseDownHandler, true, 0, true);
        systemManager.getSandboxRoot().
            addEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE, editorMouseDownHandler, false, 0, true);
        // we disappear if stage is resized
        systemManager.addEventListener(Event.RESIZE, editorStageResizeHandler, true, 0, true);
    }

    /**
     *  @private
     *  Determines the next item renderer to navigate to using the Tab key.
     *  If the item renderer to be focused falls out of range (the end or beginning
     *  of the grid) then move focus outside the grid.
     */
    private function findNextItemRenderer(shiftKey:Boolean):Boolean
    {
        if (!lastEditedItemPosition)
            return false;

        if (!editable.length)
        {
            loseFocus();
            return false;
        }

        // some other thing like a collection change has changed the
        // position, so bail and wait for commit to reset the editor.
        if (_proposedEditedItemPosition !== undefined)
            return true;

        _editedItemPosition = lastEditedItemPosition;

        var index:int = _editedItemPosition.rowIndex;
        var colIndex:int = _editedItemPosition.columnIndex;

        var found:Boolean = false;
        var incr:int = shiftKey ? -1 : 1;
        var maxIndex:int = collection.length - 1;
        var itemRenderer:IListItemRenderer;

        // cycle till we find something worth focusing, or the end of the grid
        while (!found)
        {
            // go to next column
            colIndex += incr;
            if (colIndex >= _columns.length || colIndex < 0)
            {
                // if we fall off the end of the columns, wrap around
                colIndex = (colIndex < 0) ? _columns.length - 1 : 0;
                // and increment/decrement the row index
                index += incr;
                if (index > maxIndex || index < 0)
                {
					if (endEdit(AdvancedDataGridEventReason.NEW_ROW))
					{
						// if we've fallen off the rows, we need to leave the grid. get rid of the editor
						setEditedItemPosition(null);
						
						// set focus back to the grid so default handler will move it to the next component
						deferFocus();
						return false;
					}
                    return true;
                }
            }

            // We have to skip cells where the item renderer is invisible so
            // that we handle column spanning i.e. we should not open editors
            // where column spanning is applied and the column should not be
            // considered.
            // TODO here we are checking for
            // existence even before scrolling.
            var visibleCoords:Object = absoluteToVisibleIndices(index, colIndex);
            var visibleRowIndex:int = visibleCoords.rowIndex;
            var visibleColIndex:int = visibleCoords.columnIndex;

            if (visibleColIndex > -1) // column.visible=false
            {
                // Assumption that item renderer is never invisible in the
                // first column! i.e. When in last row, skip to the new last row's
                // first column directly without checking the item renderer's
                // visibility.
                if (visibleRowIndex == listItems.length) // last row last column -> tab
                    visibleRowIndex -= 1;
                else if (visibleRowIndex == -1) // first row first column -> shift-tab
                    visibleRowIndex = 0;
                itemRenderer = null;
                if (listItems[visibleRowIndex] && listItems[visibleRowIndex][visibleColIndex])
                    itemRenderer = listItems[visibleRowIndex][visibleColIndex];
                if (itemRenderer && !itemRenderer.visible) // handle column-spanning
                    continue;
            }

            var newData:Object = rowNumberToData(index);
            if (newData == null)
                return true;
            if (!isDataEditable(newData))
                continue;

            // if we find a visible and editable column, move to it
            // if the item is visible, then only create item editor for it
            if (_columns[colIndex].editable && _columns[colIndex].visible)
            {
                found = true;
                // kill the old edit session
                var reason:String;
                reason = index == _editedItemPosition.rowIndex ?
                    AdvancedDataGridEventReason.NEW_COLUMN :
                    AdvancedDataGridEventReason.NEW_ROW;
                if (!itemEditorInstance || endEdit(reason))
                {
                    // send event to create the new one
                    var advancedDataGridEvent:AdvancedDataGridEvent =
                        new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_EDIT_BEGINNING, false, true);
                    // ITEM_EDIT events are cancelable
                    advancedDataGridEvent.columnIndex = colIndex;
                    advancedDataGridEvent.dataField = _columns[colIndex].dataField;
                    advancedDataGridEvent.rowIndex = index;
                    dispatchEvent(advancedDataGridEvent);
                }
            }
        }
        return found;
    }

    private function loseFocus():void
    {
        // if we've fallen off the rows, we need to leave the grid. get rid of the editor
        setEditedItemPosition(null);
        // set focus back to the grid so default handler will move it to the next component
        losingFocus = true;
        setFocus();
    }

    /**
     *  This method closes an item editor currently open on an item renderer. 
     *  You typically call this method only from within the event listener 
     *  for the <code>itemEditEnd</code> event, after
     *  you have already called the <code>preventDefault()</code> method to 
     *  prevent the default event listener from executing.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function destroyItemEditor():void
    {
        // trace("destroyItemEditor");
        if (itemEditorInstance)
        {
            DisplayObject(itemEditorInstance).removeEventListener(KeyboardEvent.KEY_DOWN, editorKeyDownHandler);
            systemManager.getSandboxRoot().
                removeEventListener(MouseEvent.MOUSE_DOWN, editorMouseDownHandler, true);
            systemManager.getSandboxRoot().
                removeEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE, editorMouseDownHandler);
            systemManager.removeEventListener(Event.RESIZE, editorStageResizeHandler, true);

            var event:AdvancedDataGridEvent =
                new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_FOCUS_OUT);
            event.columnIndex = _editedItemPosition.columnIndex;
            event.rowIndex = _editedItemPosition.rowIndex;
            event.itemRenderer = itemEditorInstance;
            dispatchEvent(event);

            if (! _columns[_editedItemPosition.columnIndex].rendererIsEditor)
            {
                // FocusManager.removeHandler() does not find
                // itemEditors in focusableObjects[] array
                // and hence does not remove the focusRectangle
                if (itemEditorInstance && itemEditorInstance is UIComponent)
                    UIComponent(itemEditorInstance).drawFocus(false);

				// setfocus back to us so something on stage has focus
				deferFocus();
				
				// must call removeChild() so FocusManager.lastFocus becomes null
				if (itemEditorInstance)
               		itemEditorInstance.parent.removeChild(DisplayObject(itemEditorInstance));

                // we are not setting the item renderer's visibility to false while creating an editor,
                // then why set its visibility to true
                // setting it visible will display the invisible item renderer in case of Custom Rows
                //editedItemRenderer.visible = true;
            }
            itemEditorInstance = null;
            _editedItemPosition = null;
        }
    }

    /**
     *  @private
     *  When the user finished editing an item, this method is called.
     *  It dispatches the AdvancedDataGridEvent.ITEM_EDIT_END event to start the process
     *  of copying the edited data from
     *  the itemEditorInstance to the data provider and hiding the itemEditorInstance.
     *  returns true if nobody called preventDefault.
     */
    protected function endEdit(reason:String):Boolean
    {
        // this happens if the renderer is removed asynchronously ususally with FDS
        if (!editedItemRenderer)
            return true;

        inEndEdit = true;

        var advancedDataGridEvent:AdvancedDataGridEvent =
            new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_EDIT_END, false, true);
        // ITEM_EDIT events are cancelable
        advancedDataGridEvent.columnIndex = editedItemPosition.columnIndex;
        advancedDataGridEvent.dataField = _columns[editedItemPosition.columnIndex].dataField;
        advancedDataGridEvent.rowIndex = editedItemPosition.rowIndex;
        advancedDataGridEvent.itemRenderer = editedItemRenderer;
        advancedDataGridEvent.reason = reason;
        dispatchEvent(advancedDataGridEvent);
        // set a flag to not open another edit session if the item editor is still up
        // this means somebody wants the old edit session to stay.
        dontEdit = itemEditorInstance != null;
        // trace("dontEdit", dontEdit);

        if (!dontEdit && reason == AdvancedDataGridEventReason.CANCELLED)
        {
            losingFocus = true;
            setFocus();
        }

        inEndEdit = false;

        return !(advancedDataGridEvent.isDefaultPrevented())
    }
	
	/**
	 *  @private
	 *  Sets focus back to the grid so default handler will move it to the 
	 *  next component.
	 */ 
	private function deferFocus():void
	{
		losingFocus = true;
		setFocus();
		losingFocus = false;
	}

    /**
     *  @private
     */
    mx_internal function columnRendererChanged(c:AdvancedDataGridColumn):void
    {
        var item:IListItemRenderer;

        var factory:IFactory = columnItemRendererFactory(c,true,null);
        if (measuringObjects)
        {
            item = measuringObjects[factory];
            if (item)
            {
                item.parent.removeChild(DisplayObject(item));
                measuringObjects[factory] = null;
            }
            // TODO - set valid item to be passed
            factory = columnItemRendererFactory(c,false,null);
            item = measuringObjects[factory];
            if (item)
            {
                item.parent.removeChild(DisplayObject(item));
                measuringObjects[factory] = null;
            }
        }
        if(freeItemRenderersTable[c])
        {
            // remove item renderers
            var freeRenderers:Array = freeItemRenderersTable[c][c.itemRenderer] as Array;
            if (freeRenderers)
            {
                while (freeRenderers.length)
                {
                    item = freeRenderers.pop();
                    item.parent.removeChild(DisplayObject(item));
                }
            }
            // remove header renderers
            freeRenderers = freeItemRenderersTable[c][c.headerRenderer ? c.headerRenderer : headerRenderer] as Array;
            if (freeRenderers)
            {
                while (freeRenderers.length)
                {
                    item = freeRenderers.pop();
                    item.parent.removeChild(DisplayObject(item));
                }
            }
        }
        rendererChanged = true;
        invalidateDisplayList();
    }

    /**
     *  @private
     */
    protected function getPossibleDropPositions(val:AdvancedDataGridColumn):Array
    {
        var n:int = visibleColumns ? visibleColumns.length : 0;

        var dropPositions:Array = [];
        for ( var i:int = 0; i < n; i++)
        {
            dropPositions.push(getHeaderInfo(visibleColumns[i]));
        }
        return dropPositions;
    }

    /**
     *  @private
     */
    protected function hasHeaderItemsCreated(index:int=-1):Boolean
    {
        if(index == -1)
            return (headerItems && headerItems[0] && headerItems[0][0]);
        return (headerItems && headerItems[0] && headerItems[0][index]);
    }

    /**
     *  @private
     */
    protected function columnDraggingMouseMoveHandler(event:MouseEvent):void
    {
        if (!event.buttonDown)
        {
            columnDraggingMouseUpHandler(event);
            return;
        }
        var item:IListItemRenderer;
        var c:AdvancedDataGridColumn = movingColumn;
        var s:Sprite;
        var i:int = 0;
        var n:int;
        if (isNaN(startX))
        {
            // If startX is not a number, dragging has just started.
            // Initialise and return without actually moving anything.

            startX = event.stageX;

            // Set this to null so sort doesn't happen.
            lastItemDown = null;

            // Create and position proxy.
            // passing data as null, as it is used for header renderer
            var proxy:IListItemRenderer = columnItemRenderer(c, true, null);
            proxy.name = "headerDragProxy";

            var rowData:AdvancedDataGridListData = AdvancedDataGridListData(makeListData(c, null, 0, c.colNum, c));
            if (proxy is IDropInListItemRenderer)
                IDropInListItemRenderer(proxy).listData = rowData;

            listContent.addChild(DisplayObject(proxy));

            n = orderedHeadersList.length;
            for (i = 0; i < n; i++)
            {
                item = orderedHeadersList[i].headerItem;
                if (item && item.data == movingColumn)
                    break;
            }

            var h:Number = item.height + cachedPaddingBottom + cachedPaddingTop;
            var w:Number = item.getExplicitOrMeasuredWidth();
            var x:Number = item.x;

            //In case we have scrolled the "selection" shown need to be shifted
            if(orderedHeadersList[i].actualColNum >= lockedColumnCount)
            {
                x = getAdjustedXPos(item.x);
                // In case of column grouping, it may be partially visible, so need to get the visible width as well as the
                //x pos from which it is visible
                if(horizontalScrollPosition > 0 && orderedHeadersList[i].actualColNum - horizontalScrollPosition < lockedColumnCount)
                {
                    var lockedWidth:Number = 0;
                    if(lockedColumnCount > 0)
                    {
                        var lastLockedInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(_columns[lockedColumnCount-1]);
                        lockedWidth = lastLockedInfo.headerItem.x + _columns[lockedColumnCount - 1].width;
                    }
                    else
                        lockedWidth = 0;
                    
                    w -= (lockedWidth - x);
                    x = lockedWidth;
                }
            }

            proxy.data = c;
            proxy.styleName = getStyle("headerDragProxyStyleName");
            UIComponentGlobals.layoutManager.validateClient(proxy, true);
            proxy.setActualSize(w, _explicitHeaderHeight ?
                                headerHeight : proxy.getExplicitOrMeasuredHeight());

            proxy.move(x, item.y);

            // Create, position and draw column overlay.
            s = new FlexSprite();
            s.name = "columnDragOverlay";
            s.alpha = 0.6;
            listContent.addChildAt(s, listContent.getChildIndex(selectionLayer));

            var vm:EdgeMetrics = viewMetrics;

            s.x = x;
            s.y = item.y - cachedPaddingTop;;

            if (w > 0)
            {
                var g:Graphics = s.graphics;
                g.beginFill(getStyle("disabledColor"));
                g.drawRect(0, 0, w,
                           unscaledHeight - vm.bottom - s.y);
                g.endFill();
            }

            s = Sprite(selectionLayer.getChildByName("headerSelection"));
            if (s)
                s.width = w;//movingColumn.width;

            if (!listContent.mask)
            {
                // Clip the contents so the header drag proxy doesn't show
                // outside the list.
                var bm:EdgeMetrics = borderMetrics;
                listContent.scrollRect = new Rectangle(0, 0,
                                                       unscaledWidth - bm.left - bm.right,
                                                       unscaledHeight - bm.top - bm.bottom);
            }

            return;
        }

        // Global coordinates.
        var deltaX:Number = event.stageX - startX;

        // If the mouse pointer over the right (layoutDirection=”ltr”) or 
        // left (layoutDirection=”rtl”) half of the column, the drop indicator 
        // should be shown before the next column.
        var deltaXInLocalCoordinates:Number = 
            (layoutDirection == LayoutDirection.LTR ? +deltaX : -deltaX);
        
        // Move header selection.
        s = Sprite(selectionLayer.getChildByName("headerSelection"));
        if (s)
            s.x += deltaXInLocalCoordinates;

        // Move header proxy.
        item = IListItemRenderer(listContent.getChildByName("headerDragProxy"));
        if (item)
            item.move(item.x + deltaXInLocalCoordinates, item.y);

        startX += deltaX;

        var pt:Point = new Point(event.stageX, event.stageY);
        pt = listContent.globalToLocal(pt);
        lastPt = pt;

        var headerSearchArray:Array = getPossibleDropPositions(movingColumn);
        n = headerSearchArray.length;
        var headerInfo:AdvancedDataGridHeaderInfo;
        var columnXPos:Number = headerSearchArray[0].headerItem.x;      
        
        var ww:Number = columnXPos;
        var notLocked:Boolean = false;

        dropIndexFound = false;

        for (var k:int = 0; k < n; ++k)
        {
            headerInfo = headerSearchArray[k];
            
            //Is the column getting checked is locked or not?
            if(headerInfo.actualColNum >= lockedColumnCount)
                notLocked = true;

            ww += headerInfo.column.width;

            //We are not interested in columns hidden in the left because of scrolling
            // interested in visibleColumns only
            if(notLocked && headerInfo.actualColNum + headerInfo.columnSpan - horizontalScrollPosition <= lockedColumnCount)
            {
                columnXPos = ww;
                continue;
            }

            if(notLocked)
                columnXPos = getAdjustedXPos(columnXPos);

            if (pt.x >= columnXPos && pt.x < columnXPos + headerInfo.column.width)
            {
                dropIndexFound = true;
                isHeaderDragOutside = false;

                // If the mouse pointer over the right (ltr) or left (rtl) half
                // of the column, the drop indicator should be shown before the next column.
                if (pt.x > (columnXPos + headerInfo.column.width/2) || 
                    //Column groups which are partially visible should 
                    //show drag indicator at the right end only
                    notLocked && headerInfo.actualColNum - horizontalScrollPosition < lockedColumnCount)
                {
                    columnXPos += headerInfo.column.width;
                    ++k;
                }

                if (dropColumnIndex != k)
                {
                    dropColumnIndex = k;

                    if (!columnDropIndicator)
                    {
                        var dropIndicatorClass:Class
                            = getStyle("columnDropIndicatorSkin");
                        if (!dropIndicatorClass)
                            dropIndicatorClass = DataGridColumnDropIndicator;
                        columnDropIndicator = IFlexDisplayObject(
                            new dropIndicatorClass());

                        if (columnDropIndicator is ISimpleStyleClient)
                            ISimpleStyleClient(columnDropIndicator).styleName = this;

                        listContent.addChild(
                            DisplayObject(columnDropIndicator));
                    }

                    listContent.setChildIndex(
                        DisplayObject(columnDropIndicator),
                        listContent.numChildren - 1);
                    columnDropIndicator.x = columnXPos - 2;
                    columnDropIndicator.y = item.y;

                    columnDropIndicator.setActualSize(3, listContent.height - item.y);
                }

                columnDropIndicator.visible = true;

                break;
            }
            columnXPos = ww;
        }

        // dispatch a headerDragOutside event if we have moved out
        // Need not dispatch if we are already out
        if(!dropIndexFound && isHeaderDragOutside == false)
        {
            isHeaderDragOutside = true;

            var advancedDataGridEvent:AdvancedDataGridEvent = new AdvancedDataGridEvent(
                AdvancedDataGridEvent.HEADER_DRAG_OUTSIDE,
                false, true);
            
            var movingColumnInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(movingColumn);

            advancedDataGridEvent.column = movingColumn;
            advancedDataGridEvent.columnIndex = -1;
            advancedDataGridEvent.itemRenderer = movingColumnInfo.headerItem;
            advancedDataGridEvent.triggerEvent = event;

            dispatchEvent(advancedDataGridEvent);
        }
    }

    /**
     *  @private
     */
    protected function columnDraggingMouseUpHandler(event:Event):void
    {
        if (!movingColumn)
            return;
        var origIndex:int = movingColumn.colNum;

        if (dropColumnIndex >= 0)
        {
            if (dropColumnIndex >= visibleColumns.length)
            {
                dropColumnIndex = visibleColumns.length - 1;
            }
            else
            {
                if (origIndex < visibleColumns[dropColumnIndex].colNum)
                    dropColumnIndex--;
            }
            
            // dropColumnIndex is actually the index into the visibleColumns
            // array.  Get the corresponding index into the _columns array.
            dropColumnIndex = visibleColumns[dropColumnIndex].colNum;
        }
        
        // Shift columns.
        shiftColumns(origIndex, dropColumnIndex, event as MouseEvent);
        unsetColumnDragParameters();
    }
    
    /**
     *  @private
     */
    protected function unsetColumnDragParameters():void
    {
        var sbRoot:DisplayObject = systemManager.getSandboxRoot();
        sbRoot.removeEventListener(MouseEvent.MOUSE_MOVE, columnDraggingMouseMoveHandler, true);
        sbRoot.removeEventListener(MouseEvent.MOUSE_UP, columnDraggingMouseUpHandler, true);
        sbRoot.removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, columnDraggingMouseUpHandler);
        systemManager.deployMouseShields(false);

        var proxy:IListItemRenderer =
            IListItemRenderer(listContent.getChildByName("headerDragProxy"));
        if (proxy)
            listContent.removeChild(DisplayObject(proxy));

        var s:Sprite = Sprite(selectionLayer.getChildByName("headerSelection"));
        if (s)
            selectionLayer.removeChild(s);

        if (columnDropIndicator)
            columnDropIndicator.visible = false;

        s = Sprite(listContent.getChildByName("columnDragOverlay"));
        if (s)
            listContent.removeChild(s);

        listContent.scrollRect = null;

        // Add the mask which was present before column dragging
        addClipMask(false);

        startX = NaN;
        movingColumn = null;
        dropColumnIndex = -1;
    }

    /**
     *  Checks if dragging is allowed for a particular column or not.
     *
     *  @param draggedColumn The column being dragged.
     *
     *  @return <code>true</code> if dragging is allowed for the column.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function isDraggingAllowed(draggedColumn:AdvancedDataGridColumn):Boolean
    {
        return draggedColumn.draggable;
    }

    /**
     *  Returns a SortInfo instance containing sorting information for the column.
     *
     *  @param column The column index.
     *
     *  @return A SortInfo instance.
     * 
     *  @see mx.controls.advancedDataGridClasses.SortInfo 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function getFieldSortInfo(column:AdvancedDataGridColumn):SortInfo
    {
        if (column && collection && collection.sort)
        {
            var colUID:String;
            //In case there is no dataField we will use the unique column uid to identify if the column is sorted
            if (!column.dataField)
                colUID = itemToUID(column);
                
            var n:int = collection.sort.fields.length;

            for (var i:int = 0; i < n; i++)
            {
                if (column.dataField && collection.sort.fields[i].name == column.dataField
                    || colUID &&  collection.sort.fields[i].name == colUID)
                {
                    // return 1-based, not 0-based sequence number
                    return new SortInfo(i + 1, collection.sort.fields[i].descending);
                }
            }
        }
        
        return null;
    }

    /**
     *  Checks if editing is allowed for a group or summary row.
     *
     *  @param data Data provider Object for the row.
     *
     *  @return <code>true</code> if editing is allowed for the group or summary row.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function isDataEditable(data:Object):Boolean
    {
        return true;
    }

    /**
     * @private
     *
     * Invalidate everything (properties, size, displaylist) for an IListItemRenderer if it is
     * IInvalidating.
    */
    protected function invalidateRenderer(renderer:IListItemRenderer):void
    {
        var i:IInvalidating = renderer as IInvalidating;
        if (i)
        {
            i.invalidateProperties();
            i.invalidateSize();
            i.invalidateDisplayList();
        }
    }

    /**
     * @private
     *
     * Reset the headers.
     */
    protected function invalidateHeaders():void
    {
        // Refresh the headers so that the separator line is removed or added
        var n:int = orderedHeadersList.length;
        for (var i:int = 0; i < n; i++)
        {
            invalidateRenderer(orderedHeadersList[i].headerItem);
        }
    }
    
    /**
     * @private
     * Given a row number, get the corresponding data in the dataProvider.
     */
    protected function rowNumberToData(rowNumber:int):Object
    {
        var iterator:IViewCursor = collection.createCursor();
        iterator.seek(CursorBookmark.FIRST, rowNumber);
        if (iterator.afterLast)
            return null;
        return iterator.current;
    }

    /**
     *  @private
     *  find the next item renderer down from the currently edited item renderer, and focus it.
     */
    private function findNextEnterItemRenderer(event:KeyboardEvent):void
    {
        // some other thing like a collection change has changed the
        // position, so bail and wait for commit to reset the editor.
        if (_proposedEditedItemPosition !== undefined)
            return;

        _editedItemPosition = lastEditedItemPosition;

        var rowIndex:int = _editedItemPosition.rowIndex;
        var columnIndex:int = _editedItemPosition.columnIndex;
        var newIndex:int = rowIndex;

        do
        {
            // modify direction with SHIFT (up or down)
            newIndex += (event.shiftKey ? -1 : 1);
            // only move if we're within range
            if (newIndex < collection.length && newIndex >= 0)
            {
                rowIndex = newIndex;
            }
            else
            {
                setEditedItemPosition(null);
                return;
            }

            var newData:Object = rowNumberToData(newIndex);
            if (newData == null)
            {
                setEditedItemPosition(null);
                return;
            }

            if (isDataEditable(newData))
                break;

        } while (true);

        // send event to create the new one
        var advancedDataGridEvent:AdvancedDataGridEvent =
            new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_EDIT_BEGINNING, false, true);
        // ITEM_EDIT events are cancelable
        advancedDataGridEvent.columnIndex = columnIndex;
        advancedDataGridEvent.dataField = _columns[columnIndex].dataField;
        advancedDataGridEvent.rowIndex = rowIndex;
        dispatchEvent(advancedDataGridEvent);
    }

    /**
     *  Returns the column index corresponding to the field name of a sortable field.
     *
     *  @param name The name of a sortable field of the data provider, as defined by 
     *  an instance of the SortField class.
     *
     *  @return The column index of the sortable field. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function findSortField(name:String):int
    {
        if (collection && collection.sort)
        {
            var n:int = collection.sort.fields.length;
            for (var i:int = 0; i < n; i++)
            {
                if (collection.sort.fields[i]["name"] == name)
                    return i;
            }
            
        }

        return -1;
    }
    
    /**
     *  Adds a data field to the list of sort fields. 
     *  Indicate the data field by specifying its column location.
     *
     *  @param columnName The name of the column that corresponds to the data field.
     *
     *  @param columnNumber The column index in the AdvancedDataGrid control.
     *
     *  @param collection The data collection that contains the data field.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function addSortField(columnName:String,
                                    columnNumber:int,
                                    collection:ICollectionView):void
    {
        var column:AdvancedDataGridColumn = _columns[columnNumber];

        if (!column.sortable)
            return;

         var desc:Boolean = column.sortDescending;
		 var fields:Array;
         
         var singleColumnSort:Boolean = false;
         if (!collection.sort || !collection.sort.fields)
         {
             singleColumnSort = true;
             var sort:ISort = new Sort();
             sort.fields = [];
             
             collection.sort = sort;
        }
        else if (collection.sort.fields.length == 0)
        {
            singleColumnSort = true;
        }

        if (singleColumnSort)
        {
            lastSortIndex = sortIndex;
            sortIndex     = columnNumber;
            sortColumn    = column;
            
            var dir:String = (desc) ? "DESC" : "ASC";
            sortDirection = dir;
        }
        else
        {
            lastSortIndex = -1;
            sortIndex = -1;
            sortColumn = null;
            sortDirection = null;
        }

        column.sortDescending = desc;
        var field:ISortField = new SortField(columnName, false, desc, null, column.sortCompareType, column.sortCompareFunction);

		fields = collection.sort.fields;
		if (fields == null)
			fields = [];
		fields.push(field);
		collection.sort.fields = fields;
    }

    /**
     *  Removes a data field from the list of sort fields. 
     *  Indicate the data field by specifying its column location.
     *
     *  @param columnName The name of the column that corresponds to the data field.
     *
     *  @param columnNumber The column index in the AdvancedDataGrid control.
     *
     *  @param collection The data collection that contains the data field.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function removeSortField(columnName:String,
                                    columnNumber:int,
                                    collection:ICollectionView):void
    {
        var column:AdvancedDataGridColumn = _columns[columnNumber];

        if (!collection || !collection.sort || !collection.sort.fields
                || !collection.sort.fields.length)
            return;

        var columnNumberToRemove:int = -1;
        var n:int = collection.sort.fields.length;

        for (var i:int = 0; i < n; i++)
        {
            if (collection.sort.fields[i].name == column.dataField)
            {
                columnNumberToRemove = i;
                break;
            }
        }

        if (columnNumberToRemove != -1)
            collection.sort.fields.splice(columnNumberToRemove, 1);
    }

    /**
     *  Flip the order from ascending <-> descending for the given column name
     *  in the sort fields list
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    private function flipSortOrder(columnName:String, columnNumber:int, collection:ICollectionView):String
    {
        if (collection.sort)
        {
            var column:AdvancedDataGridColumn = _columns[columnNumber];
            
            collection.sort.fields[findSortField(columnName)]["descending"]
                = ! collection.sort.fields[findSortField(columnName)]["descending"];

            if (collection.sort.fields[findSortField(columnName)]["descending"])
            {
                column.sortDescending = true;
                return "DESC";
            }
            else
            {
                column.sortDescending = false;
                return "ASC";
            }
        }

        return null;
    }
    
    /**
     *  A helper method to determine which item renderer is under the mouse.
     */    
    protected function findRenderer(pt:Point,items:Array,info:Array,yy:Number = 0):IListItemRenderer
    {
        var r:IListItemRenderer;
        var ww:Number = 0;
        var m:int = 0;
        var n:int = items.length;
        var optimumColumns:Array = getOptimumColumns();
        for (var i:int = 0; i < n; i++)
        {
            if (items[i].length)
            {
                if (pt.y < yy + info[i].height)
                {
                    m = items[i].length;
                    if (m == 1)
                    {
                        r = items[i][0];
                        break;
                    }

                    ww = 0;
                    for (var j:int = horizontalScrollPosition; j < m; j++)
                    {
                        ww += optimumColumns[j].width;
                        if (pt.x < ww)
                        {
                            r = items[i][j];
                            break;
                        }

                    }
                    if (r)
                        break;
                }
            }
            yy += info[i].height;
        }

        return r;
    }

    /**
     *  A helper method to determine which item renderer is under the mouse.
     */    
    protected function findHeaderRenderer(pt:Point):IListItemRenderer
    {
        var r:IListItemRenderer;
        var yy:Number = 0;
        var ww:Number = 0;
        var m:int = 0;
        var n:int = headerItems.length;
        var optimumColumns:Array = getOptimumColumns();
        for (var i:int = 0; i < n; i++)
        {
            if (headerItems[i].length)
            {
                if (pt.y < yy + headerRowInfo[i].height)
                {
                    m = headerItems[i].length;
                    if (m == 1)
                    {
                        r = headerItems[i][0];
                        break;
                    }

                    ww = 0;
                    for (var j:int = 0; j < lockedColumnCount; j++)
                    {
                        ww += optimumColumns[j].width;
                        if (pt.x < ww)
                        {
                            r = headerItems[i][j];
                            break;
                        }

                    }
                    if (r)
                        break;

                    for (j=lockedColumnCount + horizontalScrollPosition; j < m; j++)
                    {
                        ww += optimumColumns[j].width;
                        if (pt.x < ww)
                        {
                            r = headerItems[i][j];
                            break;
                        }

                    }

                }
            }
            yy += headerRowInfo[i].height;
        }

        return r;
    }
    
    /**
     *  @private
     */
    mx_internal function getSeparators():Array
    {
        return separators;
    }

    /**
     *  @private
     */
    mx_internal function getLockedSeparators():Array
    {
        return lockedSeparators;
    }
    
    /**
     *  @private
     */
    private function measureItems():void
    {
        if (itemsNeedMeasurement)
        {
            itemsNeedMeasurement = false;
			// fetch the itemRenderer so that it gets initialized
			var obj:Object = itemRenderer;
            if (isNaN(explicitRowHeight))
            {
                if (iterator && _columns.length > 0)
                {
                    if (!measuringObjects)
                        measuringObjects = new Dictionary(false);

                    //set AdvancedDataGridBase.visibleColumns to the set of 
                    //all columns
                    visibleColumns = columns;
                    columnsInvalid = true;

                    var paddingTop:Number = getStyle("paddingTop");
                    var paddingBottom:Number = getStyle("paddingBottom");

                    var data:Object = iterator.current;
                    var item:IListItemRenderer;
                    var c:AdvancedDataGridColumn;
                    var ch:Number = 0;
                    var n:int = _columns.length;
                    for (var i:int = 0; i < n; i++)
                    {
                        c = _columns[i];

                        if (!c.visible)
                            continue;

                        item = getMeasuringRenderer(c, false,data);
                        setupRendererFromData(c, item, data);
                        ch = Math.max(ch, item.getExplicitOrMeasuredHeight() + paddingBottom + paddingTop);
                    }

                    // unless specified otherwise, rowheight defaults to 20
                    setRowHeight(Math.max(ch, 20));
                }
                else
                    setRowHeight(20);
            }
        }
    }

    /**
     *  @private
     *  Set the itemEditor instance position according to the indentation of the item it is representing.
     */
    protected function layoutItemEditor():void
    {
    }

    /**
     *  Moves focus to the specified column header. 
     *
     *  @param columnIndex The index of the column to receive focus. 
     *  If you specify an invalid column index, the method returns without moving focus.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function moveFocusToHeader(columnIndex:int = -1):void
    {
        if (!headerVisible || headerIndex != -1)
            return;

        if (visibleColumns.length > 0)
        {
            if (columnIndex == -1)
                columnIndex = visibleColumns[0].colNum;

            selectedHeaderInfo = getHeaderInfo(_columns[columnIndex]);
            headerIndex = columnIndex;
            selectColumnHeader(headerIndex);
        }
    }

    /**
     *  Selects the specified column header.
     *
     *  @param columnNumber The index of the column to receive focus. 
     *  If you specify an invalid column index, the method returns without moving focus.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function selectColumnHeader(columnNumber:int):void
    {
        var visibleColumnNumber:int = -1;
        var n:int = visibleColumns.length;
        for (var i:int = 0; i < n; i++)
        {
            if (visibleColumns[i].colNum == columnNumber)
            {
                visibleColumnNumber = i;
                break;
            }
        }

        // For example, if a column header is selected but we have horizontally
        // scrolled such that it is not visible, then we select the first visible header item
        if (visibleColumnNumber == -1)
        {
            visibleColumnNumber = 0;
            headerIndex = visibleColumns[0].colNum;
        }

        var s:Sprite = Sprite( selectionLayer.getChildByName("headerKeyboardSelection") );
        // Copied from function mouseOverHandler
        if (! s)
        {
            s = new FlexSprite();
            s.name = "headerKeyboardSelection";
            selectionLayer.addChild(s);
        }

        var r:IListItemRenderer = selectedHeaderInfo.headerItem;        
        if (r)
        {
            var g:Graphics = s.graphics;
            g.clear();
            g.beginFill( (isPressed || isKeyPressed) ? getStyle("selectionColor") : getStyle("rollOverColor") );
            g.drawRect(0, 0, visibleColumns[visibleColumnNumber].width, r.height+cachedPaddingTop+cachedPaddingBottom - 0.5);
            g.endFill();
    
            s.x = getAdjustedXPos(r.x);
            s.y = r.y - cachedPaddingTop;           
    
            // Make sure other selection is removed
            caretIndex = -1;
            isPressed = false;
            selectItem(selectedHeaderInfo.headerItem, false, false);
        }
    }

    /**
     *  Deselects the specified column header.
     *
     *  @param columnNumber The index of the column. 
     *  If you specify an invalid column index, the method does nothing.
     *
     *  @param completely If <code>true</code>, clear the <code>caretIndex</code> property
     *  and selects the first column header in the control. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function unselectColumnHeader(columnNumber:int, completely:Boolean=false):void
    {
        var s:Sprite = Sprite( selectionLayer.getChildByName("headerKeyboardSelection") );
        if (s)
            selectionLayer.removeChild(s);
        selectedHeaderInfo = null;
        if (completely)
        {
            caretIndex = 0;
            isPressed = false;
            selectItem(listItems[caretIndex][0], false, false);
        }
    }

    /**
     *  Helper function to figure out if the item renderer is renderering a
     *  header.
     *
     *  @private
     */
    protected function isHeaderItemRenderer(item:IListItemRenderer):Boolean
    {
        // data is set to AdvancedDataGridColumn for header items
        if (item != null && item.data is AdvancedDataGridColumn)
            return true;

        return false;
    }

    /**
     *  Converts an absolute column index to the corresponding index in the
     *  displayed columns. Because users can reorder columns, the 
     *  absolute column index may be different from the index of the
     *  displayed column.
     *
     *  @param columnIndex Absolute index of the column.
     *
     *  @return The index of the column as it is currently displayed, 
     *  or -1 if <code>columnIndex</code> is not found.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function absoluteToDisplayColumnIndex(columnIndex:int):int
    {
        var n:int = displayableColumns.length;
        for (var i:int = 0; i < n; i++)
        {
            if (displayableColumns[i].colNum == columnIndex)
                return i;
        }

        return -1;
    }

    /**
     *  Converts the current display column index of a column to 
     *  its corresponding absolute index. 
     *  Because users can reorder columns, the 
     *  absolute column index may be different from the index of the
     *  displayed column.
     *
     *  @param columnIndex Index of the column as it is currently displayed by the control.
     *
     *  @return The absolute index of the column.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function displayToAbsoluteColumnIndex(columnIndex:int):int
    {
		var noColumns:int = displayableColumns.length;
		
		if (columnIndex >= 0 && columnIndex < noColumns) {
			return displayableColumns[columnIndex].colNum;
		}
		else {
			return -1;
		}
    }

    /**
     *  Converts an absolute column index to the corresponding index in the
     *  visible columns. Because users can reorder columns, the 
     *  absolute column index may be different from the index of the
     *  visible column.
     *
     *  @param columnIndex Absolute index of the column.
     *
     *  @return The index of the column as it is currently visible, 
     *  or -1 if <code>columnIndex</code> is not currently visible.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function absoluteToVisibleColumnIndex(columnIndex:int):int
    {
        var optimumColumns:Array = getOptimumColumns();
        var n:int = optimumColumns.length;
        for (var i:int = 0; i < n; i++)
        {
            if (optimumColumns[i].colNum == columnIndex)
                return i;
        }
        return -1;
    }

    /**
     *  Converts the current visible column index of a column to 
     *  its corresponding absolute index. 
     *  Because users can reorder columns, the 
     *  absolute column index may be different from the index of the
     *  visible column.
     *
     *  @param columnIndex Index of a currently visible column in the control.
     *
     *  @return The absolute index of the column.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function visibleToAbsoluteColumnIndex(columnIndex:int):int
    {
        var optimumColumns:Array = getOptimumColumns();
        return optimumColumns[columnIndex].colNum;
    }

    /**
     *  Returns <code>true</code> if the specified row in a column is visible.
     *
     *  @param columnIndex The column index. 
     *
     *  @param rowIndex A row index in the column. If omitted, the method uses the 
     *  current value of the <code>verticalScrollPosition</code> property.
     *
     *  @return <code>true</code> if the specified row in the column is visible.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function isColumnFullyVisible(columnIndex:int, rowIndex:int = -1):Boolean
    {
        if (rowIndex == -1)
            rowIndex = verticalScrollPosition;

        var visibleCoords:Object = absoluteToVisibleIndices(rowIndex, columnIndex);
        var visibleRowIndex:int = visibleCoords.rowIndex;
        var visibleColIndex:int = visibleCoords.columnIndex;

        if (visibleRowIndex < 0)
            return false;

        // First, check for presence in visibleColumns
        var isFullyVisible:Boolean = (visibleColIndex != -1);

        if (isFullyVisible)
        {
            if (listItems.length >= 1 && visibleColumns.length >= 1)
            {
                var adjustedX:Number = listItems[visibleRowIndex][visibleColIndex].x;
                if(getOptimumColumns() == displayableColumns && visibleColIndex > lockedColumnCount)
                    adjustedX = getAdjustedXPos(adjustedX);

                // Second, check if it is fully visible
                // (a valid check if it is the last column)
                if (adjustedX + listItems[visibleRowIndex][visibleColIndex].width
                    > listContent.width)
                    isFullyVisible = false;
            }
        }

        return isFullyVisible;
    }

    /**
     *  Figure out which visible column is available at an offset from the
     *  current visible column.
     *
     *  Use with care, because it scrolls the new column into view.
     *
     *  @private
     */
    protected function viewDisplayableColumnAtOffset(columnIndex:int,
                                                     offset:int,
                                                     rowIndex:int=-1,
                                                     scroll:Boolean=true)
                                                     :int
    {
        var displayColumnIndex:int = absoluteToDisplayColumnIndex(columnIndex);
        if (displayColumnIndex == -1)
            return -1;

        var n:int = displayableColumns.length;

        for (var newDisplayColumnIndex:int = displayColumnIndex + offset;
             newDisplayColumnIndex >= 0 && newDisplayColumnIndex <= n-1;
             newDisplayColumnIndex += offset)
        {
            if (rowIndex > -1)
            {
                // If rowIndex is given and item renderer is present,
                // then it must be visible
                var visibleCoord:Object
                    = absoluteToVisibleIndices(rowIndex,
                                    displayToAbsoluteColumnIndex(newDisplayColumnIndex));
                var listItem:IListItemRenderer;
                if (listItems[visibleCoord.rowIndex])
                    listItem = listItems[visibleCoord.rowIndex][visibleCoord.columnIndex];
                if (listItem && !listItem.visible)
                    continue;
            }

            var newAbsoluteColumnIndex:int = displayToAbsoluteColumnIndex(newDisplayColumnIndex);
            if (newAbsoluteColumnIndex < 0 || newAbsoluteColumnIndex > _columns.length-1)
                return -1;

            if (scroll)
            {
                if (!isColumnFullyVisible(newAbsoluteColumnIndex))
                    scrollToViewColumn(newAbsoluteColumnIndex, columnIndex);
            }

            return newAbsoluteColumnIndex;
        }

        return -1;
    }

    /**
     *  Changes the value of the <code>horizontalScrollPosition</code> property 
     *  to make the specified column visible.
     *  This method is useful when all columns of the control are not currently visible.
     *
     *  @param newColumnIndex The desired index of the column in the currently displayed columns.
     *
     *  @param columnIndex The index of the column to display.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function scrollToViewColumn(newColumnIndex:int, columnIndex:int):void
    {
        var i:int, n:int;
        if (newColumnIndex == columnIndex)
            return;

        var newDisplayColumnIndex:int = absoluteToDisplayColumnIndex(newColumnIndex);
        var displayColumnIndex:int    = absoluteToDisplayColumnIndex(columnIndex);

        var delta:int = newDisplayColumnIndex - displayColumnIndex;
        var newHorizontalScrollPosition:int = Math.max(0,horizontalScrollPosition + delta);

        // If moving from locked column area to unlocked column area, then
        // change horizontal scroll position to zero so that we can bring the
        // first unlocked column to view.
        if (lockedColumnCount > 0 && columnIndex == lockedColumnCount-1)
            newHorizontalScrollPosition = 0;

        var scrollEvent:ScrollEvent = new ScrollEvent(ScrollEvent.SCROLL);
        scrollEvent.detail          = ScrollEventDetail.THUMB_POSITION;
        scrollEvent.direction       = ScrollEventDirection.HORIZONTAL;
        scrollEvent.delta           = delta;
        scrollEvent.position        = newHorizontalScrollPosition;
        dispatchEvent(scrollEvent);

        horizontalScrollPosition    = newHorizontalScrollPosition;
    }

    /**
     *  Convert an absolute row index and column index into the corresponding 
     *  row index and column index of the item as it is currently displayed by the control.
     *
     *  @param rowIndex An absolute row index.
     *
     *  @param columnIndex An absolute column index.
     *
     *  @return An Object containing two fields, <code>rowIndex</code> and <code>columnIndex</code>, 
     *  that contain the row index and column index of the item as it is currently displayed by the control.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function absoluteToVisibleIndices(rowIndex:int, columnIndex:int):Object
    {
        var visibleRowIndex:int = -1;
        var visibleColIndex:int = -1;

        // Check row display
        if ( (rowIndex < lockedRowCount || rowIndex >= verticalScrollPosition)
                && rowIndex <= verticalScrollPosition
                    + (listItems.length ? listItems.length - 1 : 0))
        {
            if (rowIndex >= lockedRowCount && rowIndex >= verticalScrollPosition)
                visibleRowIndex = rowIndex - verticalScrollPosition;
            else
                visibleRowIndex = rowIndex;
        }

        // Check column display (optimization: calculate only if row is valid)
        if (visibleRowIndex > -1)
        {
            var columnsOnScreen:Array = visibleColumns;
            if (columnsOnScreen && columnsOnScreen.length > 0)
            {
                if (columnIndex >= columnsOnScreen[0].colNum
                        && columnIndex <= columnsOnScreen[columnsOnScreen.length-1].colNum)
                {
                    if (columnIndex >= lockedColumnCount)
                        visibleColIndex = absoluteToVisibleColumnIndex(columnIndex);
                    else
                        visibleColIndex = columnIndex;
                }
            }
        }

        return  {
                    rowIndex : visibleRowIndex,
                    columnIndex : visibleColIndex
                };
    }

    /**
     *  Returns the index of a column as it is currently displayed.
     *  This method is useful when all columns of the control are not currently visible.
     *
     *  @param colNum Absolute index of the column.
     *
     *  @return The index of the column as it is currently displayed, 
     *  or -1 if <code>colNum</code> is not found.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function colNumToIndex(colNum:int):int
    {
        if (getOptimumColumns() == visibleColumns)
            return absoluteToVisibleColumnIndex(colNum);
        else if (getOptimumColumns() == displayableColumns)
            return absoluteToDisplayColumnIndex(colNum);
        else
            return -1;
    }

    /**
     *  Returns the column number of a currently displayed column 
     *  as it is currently displayed. 
     *  This method is useful when all columns of the control are not currently visible.
     *
     *  @param columnIndex The index of the column as it is currently displayed.
     *
     *  @return The column number of the displayed column in the control, 
     *  or -1 if <code>columnIndex</code> is not found.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function indexToColNum(columnIndex:int):int
    {
        if (getOptimumColumns() == visibleColumns)
            return visibleToAbsoluteColumnIndex(columnIndex);
        else if (getOptimumColumns() == displayableColumns)
            return displayToAbsoluteColumnIndex(columnIndex);
        else
            return -1;
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden event handlers
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Catches any events from the model. Optimized for editing one item.
     *  Creates columns when there are none. Inherited from list.
     *  @param event
     */
    override protected function collectionChangeHandler(event:Event):void
    {
        //if the iterator is null that indicates we havent been validated yet so we'll bail. 
        if (iterator == null)
            return;

        if (event is CollectionEvent)
        {
            var ceEvent:CollectionEvent = CollectionEvent(event)
            if (ceEvent.kind == CollectionEventKind.mx_internal::EXPAND)
            {
                //we ignore expand in list/tree
                event.stopPropagation();
            }
            if (ceEvent.kind == CollectionEventKind.UPDATE)
            {
                //this prevents listbase from invalidating the displaylist too early. 
                event.stopPropagation();
                //we only want to update the displaylist if an updated item was visible
                //but dont have a sufficient test for that yet
                itemsSizeChanged = true;
                invalidateDisplayList();
            }

            if (ceEvent.kind == CollectionEventKind.RESET)
            {
                if (generatedColumns)
                    generateCols();
                updateSortIndexAndDirection();
            }
            else if (ceEvent.kind == CollectionEventKind.REFRESH && !manualSort)
            {
                updateSortIndexAndDirection();
            }
            else
            {
                // if we get a remove while editing adjust the editPosition
                if (ceEvent.kind == CollectionEventKind.REMOVE)
                {
                    if (editedItemPosition)
                    {
                        if (collection.length == 0)
                        {
                            if (itemEditorInstance)
                                endEdit(AdvancedDataGridEventReason.CANCELLED);
                            setEditedItemPosition(null); // nothing left to edit
                        }
                        else if (ceEvent.location <= editedItemPosition.rowIndex)
                        {
                            var curEditedItemPosition:Object = editedItemPosition;

                            // if the editor is up on the item going away, cancel the session
                            if (ceEvent.location == editedItemPosition.rowIndex && itemEditorInstance)
                                endEdit(AdvancedDataGridEventReason.CANCELLED);

                            if (inEndEdit)
                                _editedItemPosition = { columnIndex : editedItemPosition.columnIndex, 
                                                        rowIndex : Math.max(0, editedItemPosition.rowIndex - ceEvent.items.length)};
                            else
                                setEditedItemPosition({ columnIndex : curEditedItemPosition.columnIndex, 
                                                            rowIndex : Math.max(0, curEditedItemPosition.rowIndex - ceEvent.items.length)});
                        }
                    }
                }
                else if (ceEvent.kind == CollectionEventKind.REPLACE)
                {
                    if (editedItemPosition)
                    {
                        // if the editor is up on the item going away, cancel the session
                        if (ceEvent.location == editedItemPosition.rowIndex && itemEditorInstance)
                            endEdit(AdvancedDataGridEventReason.CANCELLED);
                    }
                }
            }
        }

        super.collectionChangeHandler(event);

        if (event is CollectionEvent)
        {
            // trace("ListBase collectionEvent");
            var ce:CollectionEvent = CollectionEvent(event);
            if (ce.kind == CollectionEventKind.ADD)
            {
                // added first item, generate columns for it if needed
                if (collection.length == 1)
                    if (generatedColumns)
                        generateCols();
            }
        }

//      if (event.eventName != "sort" && bRowsChanged)
//          invInitHeaders = true;
    }

    /**
     *  @private
     */
    override protected function mouseOverHandler(event:MouseEvent):void
    {
        if (movingColumn)
            return;

        if (!enabled || !selectable)
            return;

        var r:IListItemRenderer;
        var n:int;
        if (enabled && headerVisible && getNumColumns() //headerItems.length
            && !isPressed)
        {
            r = mouseEventToItemRenderer(event);
            n = orderedHeadersList.length;

            var headerItem:IListItemRenderer;
            var headerInfo:AdvancedDataGridHeaderInfo;
            var i:int;
            for( i = 0; i < n && r; i++)
            {
                headerItem = orderedHeadersList[i].headerItem;
                if(headerItem == r)
                {
                    headerInfo = orderedHeadersList[i];
                    if(orderedHeadersList[i].column.sortable)
                    {
                        var s:Sprite = Sprite(
                            selectionLayer.getChildByName("headerSelection"));
                        if (!s)
                        {
                            s = new FlexSprite();
                            s.name = "headerSelection";
                            selectionLayer.addChild(s);
                        }

                        var h:Number = r.height + cachedPaddingBottom + cachedPaddingTop;
                        var w:Number = r.getExplicitOrMeasuredWidth();
                        var x:Number = r.x;
                        
                        //In case we have scrolled the "selection" shown need to be shifted
                        if(headerInfo.actualColNum >= lockedColumnCount)
                        {
                            x = getAdjustedXPos(r.x);
                            // In case of column grouping, it may be partially visible, so need to get the visible width as well as the
                            //x pos from which it is visible
                            if(horizontalScrollPosition > 0 && headerInfo.actualColNum - horizontalScrollPosition < lockedColumnCount)
                            {
                                var lockedWidth:Number = 0;
                                if(lockedColumnCount > 0)
                                {
                                    var lastLockedInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(_columns[lockedColumnCount-1]);
                                    lockedWidth = lastLockedInfo.headerItem.x + _columns[lockedColumnCount - 1].width;
                                }
                                else
                                    lockedWidth = 0;

                                w -= (lockedWidth - x);
                                x = lockedWidth;
                            }
                        }
                        
                        var g:Graphics = s.graphics;
                        g.clear();
                        g.beginFill(getStyle("rollOverColor"));
                        g.drawRect(0, 0, w, h - 0.5);
                        g.endFill();

                        s.x = x;
                        s.y = r.y - cachedPaddingTop;
                    }
                    return;
                }
            }

        }

        if (event.buttonDown)
            lastItemDown = r;
        else
            lastItemDown = null;

        super.mouseOverHandler(event);
    }

    /**
     *  @private
     */
    override protected function mouseOutHandler(event:MouseEvent):void
    {
        if (movingColumn)
            return;

        var r:IListItemRenderer;
        var optimumColumns:Array = getOptimumColumns();
        var n:int;
        if (enabled && headerVisible && listItems.length)
        {
            r = mouseEventToItemRenderer(event);

            if(!r)
            {
                n = optimumColumns.length;
                for (var i:int = 0; i < n; i++)
                {
                    if(optimumColumns[i].colNum == sortIndex)
                        r = getHeaderInfo(optimumColumns[i]).headerItem;
                }
            }

            n = orderedHeadersList.length;
            var headerItem:IListItemRenderer;
            for( i = 0; i < n && r; i++)
            {
                headerItem = orderedHeadersList[i].headerItem;
                if(headerItem == r)
                {
                    if(orderedHeadersList[i].column.sortable)
                    {
                        var s:Sprite = Sprite(
                            selectionLayer.getChildByName("headerSelection"));
                        if (s)
                            selectionLayer.removeChild(s);
                    }
                    return;
                }
            }
        }
        if (event.buttonDown)
            lastItemDown = r;
        else
            lastItemDown = null;

        super.mouseOutHandler(event);
    }

    /**
     *  @private
     */
    override protected function mouseDownHandler(event:MouseEvent):void
    {
        // trace(">>mouseDownHandler");
        var r:IListItemRenderer;
        var s:Sprite;
        r = mouseEventToItemRenderer(event);

        var optimumColumns:Array = getOptimumColumns();
        // if headers are visible and clickable for sorting
        if (enabled && (sortableColumns || draggableColumns)
            && headerVisible && hasHeaderItemsCreated())
        {
            // find out if we clicked on a header
            var n:int = orderedHeadersList.length;
            var headerItem:IListItemRenderer;
            for( var i:int = 0; i < n && r; i++)
            {
                headerItem = orderedHeadersList[i].headerItem;
                // if we did click on a header
                if(headerItem == r)
                {
                    var headerInfo:AdvancedDataGridHeaderInfo = orderedHeadersList[i];
                    // dispose the editor
                    if (itemEditorInstance)
                        endEdit(AdvancedDataGridEventReason.OTHER);
                    var c:AdvancedDataGridColumn = orderedHeadersList[i].column;

                    if (sortableColumns && c.sortable)
                    {
                        lastItemDown = r;
                        s = Sprite(selectionLayer.getChildByName("headerSelection"));
                        if (!s)
                        {
                            s = new FlexSprite();
                            s.name = "headerSelection";
                            selectionLayer.addChild(s);
                        }

                        var h:Number = r.height + cachedPaddingBottom + cachedPaddingTop;
                        var w:Number = r.getExplicitOrMeasuredWidth();
                        var x:Number = r.x;

                        //In case we have scrolled the "selection" shown need to be shifted
                        if(headerInfo.actualColNum >= lockedColumnCount)
                        {
                            x = getAdjustedXPos(r.x);
                            // In case of column grouping, it may be partially visible, so need to get the visible width as well as the
                            //x pos from which it is visible
                            if(horizontalScrollPosition > 0 && headerInfo.actualColNum - horizontalScrollPosition < lockedColumnCount)
                            {
                                var lockedWidth:Number = 0;
                                if(lockedColumnCount > 0)
                                {
                                    var lastLockedInfo:AdvancedDataGridHeaderInfo = getHeaderInfo(_columns[lockedColumnCount-1]);
                                    lockedWidth = lastLockedInfo.headerItem.x + _columns[lockedColumnCount - 1].width;
                                }
                                else
                                {
                                    lockedWidth = 0;
                                }

                                w -= (lockedWidth - x);
                                x = lockedWidth;
                            }
                        }

                        var g:Graphics = s.graphics;
                        g.clear();
                        g.beginFill(getStyle("selectionColor"));
                        g.drawRect(0, 0, w, h - 0.5);
                        g.endFill();

                        s.x = x;
                        s.y = r.y - cachedPaddingTop;
                    }
                    isPressed = true;
                    // begin column dragging
                    if (draggableColumns && isDraggingAllowed(c))
                    {
                        startX = NaN;
                        var sbRoot:DisplayObject = systemManager.getSandboxRoot();
                        sbRoot.addEventListener(MouseEvent.MOUSE_MOVE, columnDraggingMouseMoveHandler, true);
                        sbRoot.addEventListener(MouseEvent.MOUSE_UP, columnDraggingMouseUpHandler, true);
                        sbRoot.addEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, columnDraggingMouseUpHandler);
                        systemManager.deployMouseShields(true);
                        movingColumn = c;
                    }

                    return;
                }
            }
        }
        lastItemDown = null;

        var isItemEditor:Boolean = itemRendererContains(itemEditorInstance, DisplayObject(event.target));

        // If it isn't an item renderer, or an item editor do default behavior
        if (!isItemEditor)
        {
            var pos:Point;
            if (r && r.data)
            {
                lastItemDown = r;

                pos = itemRendererToIndices(r);

                var bEndedEdit:Boolean = true;

                if (itemEditorInstance)
                {
                    //for header renderers pos would be null
                    if (pos == null || displayableColumns[pos.x].editable == false)
                        bEndedEdit = endEdit(AdvancedDataGridEventReason.OTHER);
                    else
                        bEndedEdit = endEdit(editedItemPosition.rowIndex == pos.y ?
                                             AdvancedDataGridEventReason.NEW_COLUMN :
                                             AdvancedDataGridEventReason.NEW_ROW);
                }

                // if we didn't end edit session, don't do default behavior (call super)
                if (!bEndedEdit)
                    return;
            }
            else
            {
                // trace("end edit?");
                if (itemEditorInstance)
                    endEdit(AdvancedDataGridEventReason.OTHER);
            }

            // Move focus out of header if mouse pressed on any list item
            if (headerIndex != -1)
            {
                var pt:Point = itemRendererToIndices(r);
                if (pt)
                {
                    unselectColumnHeader(headerIndex, true);
                    headerIndex = -1;
                    caretIndex = pt.y;
                }
            }

            super.mouseDownHandler(event);
            
            if (r)
            {
                if (pos && displayableColumns[pos.x].rendererIsEditor)
                    resetDragScrolling();
            }
        }
        else
            resetDragScrolling();
        // trace("<<mouseDownHandler");
    }

    /**
     *  @private
     */
    override protected function mouseUpHandler(event:MouseEvent):void
    {
        if (!collection || !collection.length)
            return;

        var advancedDataGridEvent:AdvancedDataGridEvent;
        var r:IListItemRenderer;
        var s:Sprite;
        var n:int;
        var i:int;
        var pos:Point;

        r = mouseEventToItemRenderer(event);

        if (enabled && (sortableColumns || draggableColumns)
            && collection && headerVisible && hasHeaderItemsCreated())
        {
            n = orderedHeadersList.length;
            for (i = 0; i < n; i++)
            {
                if (r && r == orderedHeadersList[i].headerItem)
                {
                    var c:AdvancedDataGridColumn = orderedHeadersList[i].column;
                    if (sortableColumns && c.sortable && lastItemDown == r)
                    {
                        lastItemDown = null;
                        advancedDataGridEvent= new AdvancedDataGridEvent(
                            AdvancedDataGridEvent.HEADER_RELEASE,
                            false, true);
                        // HEADER_RELEASE event is cancelable
                        if(c.colNum == -1 || isNaN(c.colNum))
                            advancedDataGridEvent.columnIndex = -1;
                        else
                            advancedDataGridEvent.columnIndex = c.colNum;
                        advancedDataGridEvent.dataField = c.dataField;
                        advancedDataGridEvent.itemRenderer = r;
                        advancedDataGridEvent.triggerEvent = event;
                        if (Object(r).hasOwnProperty("mouseEventToHeaderPart"))
                            advancedDataGridEvent.headerPart = Object(r).mouseEventToHeaderPart(event);
                        dispatchEvent(advancedDataGridEvent);
                    }
                    isPressed = false;
                    return;
                }
            }
        }

        if (movingColumn)
            return;

        super.mouseUpHandler(event);

        // if the item is visible, then only create item editor for it
        if (r && r.data && r != itemEditorInstance && lastItemDown == r && r.visible
                && isDataEditable(r.data))
        {
            pos = itemRendererToIndices(r);

            if (pos && pos.y >= 0 && !dontEdit)
            {
				if (displayableColumns[pos.x].editable)
				{
	                advancedDataGridEvent = new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_EDIT_BEGINNING, false, true);
	                // ITEM_EDIT events are cancelable
	                advancedDataGridEvent.columnIndex = displayableColumns[pos.x].colNum;
	                advancedDataGridEvent.dataField = displayableColumns[pos.x].dataField;
	                advancedDataGridEvent.rowIndex = pos.y;
	                advancedDataGridEvent.itemRenderer = r;
	                dispatchEvent(advancedDataGridEvent);
				}
				else
				{
					// if the item is not editable, set lastPosition to it anyways
					// so future tabbing starts from there
					lastEditedItemPosition = { columnIndex: displayableColumns[pos.x].colNum, rowIndex: pos.y };
				}
            }
        }
        else if (lastItemDown && lastItemDown != itemEditorInstance)
        {
            pos = itemRendererToIndices(lastItemDown);

            if (pos && pos.y >= 0 && editable && !dontEdit)
            {
                if (displayableColumns[pos.x].editable)
                {
                    advancedDataGridEvent = new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_EDIT_BEGINNING, false, true);
                    // ITEM_EDIT events are cancelable
                    advancedDataGridEvent.columnIndex = displayableColumns[pos.x].colNum;
                    advancedDataGridEvent.dataField = displayableColumns[pos.x].dataField;
                    advancedDataGridEvent.rowIndex = pos.y;
                    advancedDataGridEvent.itemRenderer = lastItemDown;
                    dispatchEvent(advancedDataGridEvent);
                }
                else
                {
                    // if the item is not editable, set lastPosition to it any
                    // so future tabbing starts from there
                    lastEditedItemPosition = { columnIndex: pos.x, rowIndex: pos.y };
                }
            }
        }

        lastItemDown = null;
    }

    /**
     *  @private
     *  when the grid gets focus, focus an item renderer
     */
    override protected function focusInHandler(event:FocusEvent):void
    {
        // trace(">>DGFocusIn ", selectedIndex);

        if (losingFocus)
        {
            losingFocus = false;
            // trace("losing focus via tab");
            // trace("<<DGFocusIn ");
            return;
        }

        if (editable.length)
        {
            addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
            addEventListener(MouseEvent.MOUSE_DOWN, mouseFocusChangeHandler);
        }

        if (event.target != this)
        {
            // trace("subcomponent got focus ignoring");
            // trace("<<DGFocusIn ");
            return;
        }

        super.focusInHandler(event);

        if (editable && editable.length && !isPressed) // don't do this if we're mouse focused
        {
            _editedItemPosition = lastEditedItemPosition;

            var foundOne:Boolean = false;

            // start somewhere
            if (!_editedItemPosition)
                _editedItemPosition = { rowIndex: 0, columnIndex: 0 };

            for (;
                 _editedItemPosition.columnIndex != _columns.length;
                 _editedItemPosition.columnIndex++)
            {
                // If the editedItemPosition is valid, focus it,
                // otherwise find one.
                if (_columns[_editedItemPosition.columnIndex].editable &&
                    _columns[_editedItemPosition.columnIndex].visible)
                {
					var row:Array = listItems[_editedItemPosition.rowIndex];
					if (row && row[_editedItemPosition.columnIndex])
					{
						foundOne = true;
						break;
					}
                }
            }
			
			// leave at last column or an RTE can occur
			if (_editedItemPosition.columnIndex >= _columns.length)
				_editedItemPosition.columnIndex = _columns.length - 1;

            if (foundOne)
            {
                // trace("setting focus", _editedItemPosition.columnIndex, _editedItemPosition.rowIndex);
                setEditedItemPosition(_editedItemPosition);
            }

        }

        // trace("<<DGFocusIn ");
    }

    /**
     *  @private
     *  when the grid loses focus, close the editor
     */
    override protected function focusOutHandler(event:FocusEvent):void
    {
        // trace(">>DGFocusOut " + itemEditorInstance + " " + event.relatedObject, event.target);
        if (event.target == this)
            super.focusOutHandler(event);

        // just leave if item editor is losing focus back to grid.  Usually happens
        // when someone clicks out of the editor onto a new item renderer.
        if (event.relatedObject == this && itemRendererContains(itemEditorInstance, DisplayObject(event.target)))
            return;

        // just leave if the cell renderer is losing focus to nothing while its editor exists. 
        // this happens when we make the cell renderer invisible as we put up the editor
        // if the renderer can have focus.
        if (event.relatedObject == null && itemRendererContains(editedItemRenderer, DisplayObject(event.target)))
            return;

        // just leave if item editor is losing focus to nothing.  Usually happens
        // when someone clicks out of the textfield
        if (event.relatedObject == null && itemRendererContains(itemEditorInstance, DisplayObject(event.target)))
            return;

        // however, if we're losing focus to anything other than the editor or the grid
        // hide the editor;
        if (itemEditorInstance && (!event.relatedObject || !itemRendererContains(itemEditorInstance, event.relatedObject)))
        {
            // trace("call endEdit from focus out");
            endEdit(AdvancedDataGridEventReason.OTHER);
            removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
            removeEventListener(MouseEvent.MOUSE_DOWN, mouseFocusChangeHandler);
        }
        // trace("<<DGFocusOut " + itemEditorInstance + " " + event.relatedObject);
    }

    /**
     *  @private
     */
    override protected function keyDownHandler(event:KeyboardEvent):void
    {
        if (itemEditorInstance || event.target != event.currentTarget)
            return;

        if (headerIndex != -1) // header navigation via keyboard
        {
            headerNavigationHandler(event);
            return;
        }
        // hit esc to move focus back to the grid itself
        else if (event.keyCode == Keyboard.ESCAPE)
        {
            // no more editing
            setEditedItemPosition(null);
            // make sure there is nothing to jump back to
            lastEditedItemPosition = null;
            // lose focus
            endEdit(AdvancedDataGridEventReason.CANCELLED);
            return;
        }
        // Handle keyboard access to the header i.e. up key when in the first row
        else if (headerVisible && selectedIndex == 0 && caretIndex == 0
                 && event.keyCode == Keyboard.UP
                 && !event.ctrlKey && !event.shiftKey)
        {
            moveFocusToHeader();
        }
        else if (event.keyCode == Keyboard.UP && caretIndex == 0 && selectedIndex == -1)
        {
            // Bug 202639 Pressing up arrow after a shift-arrow row selection should move to header
            moveFocusToHeader();
        }
        else if ( event.shiftKey
                  && (event.keyCode == Keyboard.PAGE_UP || event.keyCode == Keyboard.PAGE_DOWN) )
        {
            moveSelectionHorizontally(event.keyCode, event.shiftKey, event.ctrlKey);
        }

        if (event.keyCode != Keyboard.SPACE)
        {
            super.keyDownHandler(event);
        }
        else if (caretIndex != -1)
        {
            moveSelectionVertically(event.keyCode, event.shiftKey, event.ctrlKey);
        }
    }

    /**
     *  @private
     */
    override protected function keyUpHandler(event:KeyboardEvent):void
    {
        if (isKeyPressed && headerIndex != -1)
        {
            isKeyPressed = false;
            selectedHeaderInfo = getHeaderInfo(_columns[headerIndex]);
            selectColumnHeader(headerIndex);
        }
    }
    
    /**
     *  @private
     */
    override protected function mouseWheelHandler(event:MouseEvent):void
    {
        if (itemEditorInstance)
            endEdit(AdvancedDataGridEventReason.OTHER);

        super.mouseWheelHandler(event);
    }
    
    /**
     *  @private
     *  if some drags from the same row as an editor we can be left
     *  with updates disabled
     */
    override protected function dragStartHandler(event:DragEvent):void
    {
        if (collectionUpdatesDisabled)
        {
            collection.enableAutoUpdate();
            collectionUpdatesDisabled = false;
        }
        super.dragStartHandler(event);
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private function columnResizeMouseOverHandler(event:MouseEvent):void
    {
        if (!enabled || !resizableColumns)
            return;
        var target:DisplayObject = DisplayObject(event.target);
        var index:int = target.parent.getChildIndex(target);
        var optimumColumns:Array = getOptimumColumns();
		if (index < 0 || index >= optimumColumns.length)
			return;
        if (!optimumColumns[index].resizable)
            return;

        // hide the mouse, attach and show the cursor
        var stretchCursorClass:Class = getStyle("stretchCursor");
        resizeCursorID = cursorManager.setCursor(stretchCursorClass,
                                                 CursorManagerPriority.HIGH);
    }

    /**
     *  @private
     */
    private function columnResizeMouseOutHandler(event:MouseEvent):void
    {
        if (!enabled || !resizableColumns)
            return;

        var target:DisplayObject = DisplayObject(event.target);
		var parent:DisplayObjectContainer = target.parent;
		if (!parent)
			return;
		var index:int = parent.getChildIndex(target);
		var optimumColumns:Array = getOptimumColumns();
		if (index < 0 || index >= optimumColumns.length)
			return;
		if (!optimumColumns[index] || !optimumColumns[index].resizable)
            return;
		
		if (resizeCursorID != CursorManager.NO_CURSOR) {
			cursorManager.removeCursor(resizeCursorID);
			resizeCursorID =  CursorManager.NO_CURSOR;
		}
    }

    /**
     *  @private
     *  Indicates where the right side of a resized column appears.
     */
    private function columnResizeMouseDownHandler(event:MouseEvent):void
    {
        if (!enabled || !resizableColumns)
            return;

        var target:DisplayObject = DisplayObject(event.target);
		var parent:DisplayObjectContainer = target.parent;
		if (!parent)
			return;
        var index:int = parent.getChildIndex(target);
        
        // If the separator is not in locked region, column index need to be adjusted
        if (lockedColumnCount > 0 &&
           parent == UIComponent(getLines().getChildByName("header")))
            index += (lockedColumnCount - 1);

        var optimumColumns:Array = getOptimumColumns();
		if (index < 0 || index >= optimumColumns.length)
			return;
		if (!optimumColumns[index] || !optimumColumns[index].resizable)
			return;

        if (itemEditorInstance)
            endEdit(AdvancedDataGridEventReason.OTHER);

        startX = DisplayObject(event.target).x;
        lastPt = new Point(event.stageX, event.stageY);
        lastPt = listContent.globalToLocal(lastPt);

        /*      var n:int = separators.length;
            for (var i:int = 0; i < n; i++)
            {
            if (separators[i] == event.target)
            {
            resizingColumn = optimumColumns[i];
            break;
            }
            }
        
            if (!resizingColumn)
            return;
        */

        resizingColumn = optimumColumns[index];
        var headerItem:IListItemRenderer = getHeaderInfo(optimumColumns[index]).headerItem;

        if (index > lockedColumnCount)
        {
            minX = getAdjustedXPos(headerItem.x);
            startX = getAdjustedXPos(startX);
        }
        else
        {
            minX = headerItem.x;
        }

        minX += resizingColumn.minWidth;
        isPressed = true;

        var sbRoot:DisplayObject = systemManager.getSandboxRoot();
        sbRoot.addEventListener(MouseEvent.MOUSE_MOVE, columnResizingHandler, true);
        sbRoot.addEventListener(MouseEvent.MOUSE_UP, columnResizeMouseUpHandler, true);
        sbRoot.addEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, columnResizeMouseUpHandler);
        systemManager.deployMouseShields(true);

        var resizeSkinClass:Class = getStyle("columnResizeSkin");
        resizeGraphic = new resizeSkinClass();
        listContent.addChild(DisplayObject(resizeGraphic));

        var pt:Point = new Point(event.stageX, event.stageY);
        pt = listContent.globalToLocal(pt);
        
        resizeGraphic.move(pt.x, target.y);
        resizeGraphic.setActualSize(resizeGraphic.measuredWidth,
                                    unscaledHeight-target.y);
    }

    /**
     *  @private
     */
    private function columnResizingHandler(event:MouseEvent):void
    {
        if (!MouseEvent(event).buttonDown)
        {
            columnResizeMouseUpHandler(event);
            // return from here, as the resizingColumn
            // set to null.
            return;
        }

        var vsw:int = verticalScrollBar ? verticalScrollBar.width : 0;

        var pt:Point = new Point(event.stageX, event.stageY);
        pt = listContent.globalToLocal(pt);
        lastPt = pt;
        
        var separatorWidth:Number = 0;
        if (lockedSeparators && lockedSeparators.length > 0)
            separatorWidth = lockedSeparators[0].width;
        else if (separators && separators.length > 0)
            separatorWidth = separators[0].width;
            
        // substract the separators width,
        // so that separator will be visible after column resizing
        // TODO - we should substract the resized column separatos's width 
        var maxWidth:Number = unscaledWidth - separatorWidth - vsw ;
        var index:int;
        if (getOptimumColumns() == visibleColumns)
            index = absoluteToVisibleColumnIndex(resizingColumn.colNum);
        else
            index = absoluteToDisplayColumnIndex(resizingColumn.colNum);

        resizeGraphic.move(Math.min(Math.max(minX, pt.x), maxWidth), resizeGraphic.y);
    }

    /**
     *  @private
     *  Determines how much to resize the column.
     */
    private function columnResizeMouseUpHandler(event:Event):void
    {
        if (!enabled || !resizableColumns)
            return;

        isPressed = false;
        
        var sbRoot:DisplayObject = systemManager.getSandboxRoot();
        sbRoot.removeEventListener(MouseEvent.MOUSE_MOVE, columnResizingHandler, true);
        sbRoot.removeEventListener(MouseEvent.MOUSE_UP, columnResizeMouseUpHandler, true);
        sbRoot.removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, columnResizeMouseUpHandler);
        systemManager.deployMouseShields(false);

        listContent.removeChild(DisplayObject(resizeGraphic));

		if (resizeCursorID != CursorManager.NO_CURSOR) {
			cursorManager.removeCursor(resizeCursorID);
			resizeCursorID =  CursorManager.NO_CURSOR;
		}

        var c:AdvancedDataGridColumn = resizingColumn;
        resizingColumn = null;

        // need to find the visible column index here.
//        var n:int = displayableColumns.length;
//        var i:int;
//        for (i = 0; i < n; i++)
//        {
//            if (c == displayableColumns[i])
//                break;
//        }
//        if (i >= displayableColumns.length)
//            return;

        var vsw:int = verticalScrollBar ? verticalScrollBar.width : 0;
        
        var mouseEvent:MouseEvent = event as MouseEvent;

        var pt:Point;
        
        if (mouseEvent)
        {
            pt = new Point(mouseEvent.stageX, mouseEvent.stageY);
            pt = listContent.globalToLocal(pt);
        }
        else
        {
            pt = lastPt;
        }

        var separatorWidth:Number = 0;
        if (lockedSeparators && lockedSeparators.length > 0)
            separatorWidth = lockedSeparators[0].width;
        else if (separators && separators.length > 0)
            separatorWidth = separators[0].width;
        
        // substract the separators width,
        // so that separator will be visible after column resizing
        // TODO - we should substract the resized column separatos's width  
        var maxWidth:Number = unscaledWidth - separatorWidth - vsw ;

        // resize the column
        var widthChange:Number = Math.min(Math.max(minX, pt.x), maxWidth) - startX;
        resizeColumn(c.colNum, Math.floor(c.width + widthChange));

        // event
        var advancedDataGridEvent:AdvancedDataGridEvent =
            new AdvancedDataGridEvent(AdvancedDataGridEvent.COLUMN_STRETCH);
        advancedDataGridEvent.columnIndex = c.colNum;
        advancedDataGridEvent.dataField = c.dataField;
        advancedDataGridEvent.localX = pt.x;
        dispatchEvent(advancedDataGridEvent);
    }

    /**
     *  @private
     */
    private function editorMouseDownHandler(event:Event):void
    {
        if(event is MouseEvent && owns(DisplayObject(event.target)))
            return;
            
        endEdit(AdvancedDataGridEventReason.OTHER);
    }

    /**
     *  @private
     */
    protected function editorKeyDownHandler(event:KeyboardEvent):void
    {
        // ESC just kills the editor, no new data
        if (event.keyCode == Keyboard.ESCAPE)
        {
            endEdit(AdvancedDataGridEventReason.CANCELLED);
        }
        else if (event.ctrlKey && event.charCode == 46)
        {   // Check for Ctrl-.
            endEdit(AdvancedDataGridEventReason.CANCELLED);
        }
        else if (event.charCode == Keyboard.ENTER && event.keyCode != 229)
        {
            // multiline editors can take the enter key.
            if (_columns[_editedItemPosition.columnIndex].editorUsesEnterKey)
                return;

            // Enter edits the item, moves down a row
            // The 229 keyCode is for IME compatability. When entering an IME expression,
            // the enter key is down, but the keyCode is 229 instead of the enter key code.
            // Thanks to Yukari for this little trick...
            if (endEdit(AdvancedDataGridEventReason.NEW_ROW) && !dontEdit)
                findNextEnterItemRenderer(event);
        }
    }

    /**
     *  @private
     */
    private function editorStageResizeHandler(event:Event):void
    {
        if (event.target is DisplayObjectContainer &&
            DisplayObjectContainer(event.target).contains(this))
            endEdit(AdvancedDataGridEventReason.OTHER);
    }

    /**
     *  @private
     *  This gets called when the tab key is hit.
     */
    private function mouseFocusChangeHandler(event:MouseEvent):void
    {
        // trace("mouseFocus handled by " + this);

        if (itemEditorInstance &&
            !event.isDefaultPrevented() &&
            itemRendererContains(itemEditorInstance, DisplayObject(event.target)))
        {
            event.preventDefault();
        }
    }

    /**
     *  @private
     *  This gets called when the tab key is hit.
     */
    private function keyFocusChangeHandler(event:FocusEvent):void
    {
        // trace("tabHandled by " + this);

        if (event.keyCode == Keyboard.TAB &&
            ! event.isDefaultPrevented() &&
            findNextItemRenderer(event.shiftKey))
        {
            event.preventDefault();
        }
    }

    /**
     *  @private
     *  Hides the itemEditorInstance.
     */
    private function itemEditorFocusOutHandler(event:FocusEvent):void
    {
        // trace("itemEditorFocusOut " + event.relatedObject);
        if (event.relatedObject && contains(event.relatedObject))
            return;

        // ignore textfields losing focus on mousedowns
        if (!event.relatedObject)
            return;

        // trace("endEdit from itemEditorFocusOut");
        if (itemEditorInstance)
            endEdit(AdvancedDataGridEventReason.OTHER);
    }

    /**
     *  @private
     */
    private function itemEditorItemEditBeginningHandler(event:AdvancedDataGridEvent):void
    {
        // trace("itemEditorItemEditBeginningHandler");
        if (!event.isDefaultPrevented())
            setEditedItemPosition({columnIndex: event.columnIndex, rowIndex: event.rowIndex});
        else if (!itemEditorInstance)
        {
            _editedItemPosition = null;
            setFocus();
        }
    }

    /**
     *  @private
     *  focus an item renderer in the grid - harder than it looks
     */
    private function itemEditorItemEditBeginHandler(event:AdvancedDataGridEvent):void
    {
        // weak reference for deactivation
        if (root)
            systemManager.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);

        // if not prevented and if data is not null (might be from dataservices)
        if (!event.isDefaultPrevented() && listItems[actualRowIndex][actualColIndex].data != null)
        {
            createItemEditor(event.columnIndex, event.rowIndex);

            if (editedItemRenderer is IDropInListItemRenderer && itemEditorInstance is IDropInListItemRenderer)
                IDropInListItemRenderer(itemEditorInstance).listData = IDropInListItemRenderer(editedItemRenderer).listData;
            // if rendererIsEditor, don't apply the data as the data may have already changed in some way.
            // This can happen if clicking on a checkbox rendererIsEditor as the checkbox will try to change
            // its value as we try to stuff in an old value here.
            if (!_columns[event.columnIndex].rendererIsEditor)
                itemEditorInstance.data = editedItemRenderer.data;

            if (itemEditorInstance is IInvalidating)
                IInvalidating(itemEditorInstance).validateNow();

            if (itemEditorInstance is IIMESupport)
                IIMESupport(itemEditorInstance).imeMode =
                    (_columns[event.columnIndex].imeMode == null) ? _imeMode : _columns[event.columnIndex].imeMode;

            var fm:IFocusManager = focusManager;
            // trace("setting focus to item editor");
            if (itemEditorInstance is IFocusManagerComponent)
                fm.setFocus(IFocusManagerComponent(itemEditorInstance));
            fm.defaultButtonEnabled = false;

            var itemFocusInEvent:AdvancedDataGridEvent =
                new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_FOCUS_IN);
            itemFocusInEvent.columnIndex = _editedItemPosition.columnIndex;
            itemFocusInEvent.rowIndex = _editedItemPosition.rowIndex;
            itemFocusInEvent.itemRenderer = itemEditorInstance;
            dispatchEvent(itemFocusInEvent);
        }
    }

    /**
     *  @private
     */
    private function itemEditorItemEditEndHandler(event:AdvancedDataGridEvent):void
    {
        if (!event.isDefaultPrevented())
        {
            var bChanged:Boolean = false;

            if (event.reason == AdvancedDataGridEventReason.NEW_COLUMN)
            {
                if (!collectionUpdatesDisabled)
                {
                    collection.disableAutoUpdate();
                    collectionUpdatesDisabled = true;
                }
            }
            else
            {
                if (collectionUpdatesDisabled)
                {
                    collection.enableAutoUpdate();
                    collectionUpdatesDisabled = false;
                }
            }

            if (itemEditorInstance && event.reason != AdvancedDataGridEventReason.CANCELLED)
            {
                var newData:Object = itemEditorInstance[_columns[event.columnIndex].editorDataField];
                var property:String = _columns[event.columnIndex].dataField;
                var data:Object = event.itemRenderer.data;
                var typeInfo:String = "";
                for each(var variable:XML in describeType(data).variable)
                {
                    if (property == variable.@name.toString())
                    {
                        typeInfo = variable.@type.toString();
                        break;
                    }
                }

                if (typeInfo == "String")
                {
                    if (!(newData is String))
                        newData = newData.toString();
                }
                else if (typeInfo == "uint")
                {
                    if (!(newData is uint))
                        newData = uint(newData);
                }
                else if (typeInfo == "int")
                {
                    if (!(newData is int))
                        newData = int(newData);
                }
                else if (typeInfo == "Number")
                {
                    if (!(newData is int))
                        newData = Number(newData);
                }
                if (data[property] != newData)
                {
                    bChanged = true;
                    data[property] = newData;
                }
                if (bChanged && !(data is IPropertyChangeNotifier))
                {
                    collection.itemUpdated(data, property);
                }
                if (event.itemRenderer is IDropInListItemRenderer)
                {
                    var listData:AdvancedDataGridListData = AdvancedDataGridListData(IDropInListItemRenderer(event.itemRenderer).listData);
                    listData.label = _columns[event.columnIndex].itemToLabel(data);
                    IDropInListItemRenderer(event.itemRenderer).listData = listData;
                }
                event.itemRenderer.data = data;
            }
        }
        else
        {
            if (event.reason != AdvancedDataGridEventReason.OTHER)
            {
                if (itemEditorInstance && _editedItemPosition)
                {
                    // edit session is continued so restore focus and selection
                    if (selectedIndex != _editedItemPosition.rowIndex)
                        selectedIndex = _editedItemPosition.rowIndex;
                    var fm:IFocusManager = focusManager;
                    // trace("setting focus to itemEditorInstance", selectedIndex);
                    if (itemEditorInstance is IFocusManagerComponent)
                        fm.setFocus(IFocusManagerComponent(itemEditorInstance));
                }
            }
        }

        if (event.reason == AdvancedDataGridEventReason.OTHER || !event.isDefaultPrevented())
        {
			if (_editedItemPosition
				&& event.rowIndex == _editedItemPosition.rowIndex
				&& event.columnIndex == _editedItemPosition.columnIndex)
            	destroyItemEditor();
        }
    }

    /**
     *  @private
     */
    protected function headerReleaseHandler(event:AdvancedDataGridEvent):void
    {
        if (! event.isDefaultPrevented())
        {
            if (itemEditorInstance)
                endEdit(AdvancedDataGridEventReason.OTHER);

            var advancedDataGridEvent:AdvancedDataGridEvent =
                new AdvancedDataGridEvent(AdvancedDataGridEvent.SORT, false, true);

            advancedDataGridEvent.columnIndex     = event.columnIndex;
            advancedDataGridEvent.dataField       = event.dataField;
            advancedDataGridEvent.triggerEvent    = event.triggerEvent;
            if (event.triggerEvent)
            {
                var mouseEvent:MouseEvent = event.triggerEvent as MouseEvent;
                if (mouseEvent)
                {
                    advancedDataGridEvent.multiColumnSort      = mouseEvent.ctrlKey;
                    advancedDataGridEvent.removeColumnFromSort = mouseEvent.shiftKey;
                }
            }

            dispatchEvent(advancedDataGridEvent);
        }
    }

    /**
     *  @private
     */
    protected function sortHandler(event:AdvancedDataGridEvent):void
    {
        var columnName:String = event.dataField;
        var columnNumber:int  = event.columnIndex;
        var sortFields:Array;
        var sort:ISort;

        if (!sortableColumns || !_columns[columnNumber].sortable)
            return;

        //In case there is no dataField we will use the unique column uid to identify if the column is sorted
        if (columnName == null)
            columnName = itemToUID(_columns[columnNumber]);

        // If normal click for single column sort
        // or
        // If ctrl+click when there is no previous sorting
        if (!event.multiColumnSort)
        {
            if (collection.sort && collection.sort.fields.length == 1 
                && (columnName && findSortField(columnName) > -1))
            {
                    // 1. Flipping order of single column sort
                    //
                    // Not allowed in default UI. You can't flip the sort order of a single
                    // column sort using the header text part (i.e. multiColumnSort==false).
                    // You can only flip by clicking on the icon part
                    // (i.e. multiColumnSort==true), see below.
                    if (sortExpertMode == true)
                        sortDirection = flipSortOrder(columnName, columnNumber, collection);
            }
            else
            {
                // 2. Single column sort
                collection.sort = null;
                addSortField(columnName, columnNumber, collection);
            }
        }
        else
        {
            if (event.removeColumnFromSort)
            {
                removeSortField(columnName, columnNumber, collection);
            }
            // Ctrl+click without any previous sort is same as single column sort
            // Or New column added to multi column sort
            else if (findSortField(columnName) == -1)
            {
                addSortField(columnName, columnNumber, collection);
            }
            else if (findSortField(columnName) > -1) // Flipping order in multi column sort
            {
                if (collection.sort.fields.length == 1)
                {
                    // 4. Flipping the order of a column in single column sort
                    sortDirection = flipSortOrder(columnName, columnNumber, collection);
                }
                else
                {
                    // 5. Flipping the order of a column in multi column sort
                    // descending <-> ascending
                    flipSortOrder(columnName, columnNumber, collection);
                    sortDirection = null;
                }
            }
        }

        collection.refresh();

        // If navigating header via keyboard, and you mouse click on some
        // other header to sort it, then move the keyboard navigation focus
        // to that column header.
        if (headerIndex != -1)
        {
            selectedHeaderInfo = getHeaderInfo(_columns[event.columnIndex]);
            headerIndex = event.columnIndex;
            selectColumnHeader(headerIndex);
        }

        invalidateHeaders();
    }
    
    /**
     *  @private
     */
    private function deactivateHandler(event:Event):void
    {
        // if stage losing activation, set focus to DG so when we get it back
        // we popup an editor again
        if (itemEditorInstance)
        {
            endEdit(AdvancedDataGridEventReason.OTHER);
			losingFocus = true;
			setFocus();
        }
    }

    /**
     *  @private
     */
    protected function headerNavigationHandler(event:KeyboardEvent):void
    {
        if (headerIndex == -1)
            return;

        // If rtl layout, need to swap LEFT and RIGHT so correct action
        // is done.
        var keyCode:uint = mapKeycodeForLayoutDirection(event);
        
        var newColumnIndex:int;

        if (keyCode == Keyboard.DOWN)
        {
            unselectColumnHeader(headerIndex, true);
            headerIndex = -1;
        }
        else if (keyCode == Keyboard.LEFT)
        {
            newColumnIndex = viewDisplayableColumnAtOffset(headerIndex, -1);
            if (newColumnIndex != -1)
            {
                unselectColumnHeader(headerIndex);
                
                selectedHeaderInfo = getHeaderInfo(_columns[newColumnIndex]);
                headerIndex = newColumnIndex;
                selectColumnHeader(headerIndex);
            }
        }
        else if (keyCode == Keyboard.RIGHT)
        {
            newColumnIndex = viewDisplayableColumnAtOffset(headerIndex, +1);
            if (newColumnIndex != -1)
            {
                unselectColumnHeader(headerIndex);
                selectedHeaderInfo = getHeaderInfo(_columns[newColumnIndex]);
                headerIndex = newColumnIndex;
                selectColumnHeader(headerIndex);
            }
        }
        else if (keyCode == Keyboard.SPACE)
        {
            if (sortableColumns && _columns[headerIndex].sortable)
            {
                isKeyPressed = true;
                selectedHeaderInfo = getHeaderInfo(_columns[headerIndex]);
                selectColumnHeader(headerIndex);
    
                var advancedDataGridEvent:AdvancedDataGridEvent =
                    new AdvancedDataGridEvent(AdvancedDataGridEvent.SORT, false, true);
    
                advancedDataGridEvent.columnIndex     = headerIndex;
                advancedDataGridEvent.dataField       = _columns[headerIndex].dataField;
                advancedDataGridEvent.multiColumnSort      = event.ctrlKey;
                advancedDataGridEvent.removeColumnFromSort = event.shiftKey;
    
                dispatchEvent(advancedDataGridEvent);
            }
        }
        // horizontal scrolling when focus is on header
        else if ( event.shiftKey
                  && (keyCode == Keyboard.PAGE_UP
                      || keyCode == Keyboard.PAGE_DOWN) )
        {
            moveSelectionHorizontally(keyCode, event.shiftKey, event.ctrlKey);
        }

        event.stopPropagation();
    }
}

}
