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

package spark.components.gridClasses
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.IEventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Keyboard;
import flash.utils.Timer;

import mx.core.ClassFactory;
import mx.core.EventPriority;
import mx.core.IFactory;
import mx.core.IIMESupport;
import mx.core.IInvalidating;
import mx.core.IUIComponent;
import mx.core.IVisualElement;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.events.SandboxMouseEvent;
import mx.managers.FocusManager;
import mx.managers.IFocusManager;
import mx.managers.IFocusManagerComponent;
import mx.styles.ISimpleStyleClient;

import spark.components.DataGrid;
import spark.components.Grid;
import spark.components.gridClasses.GridItemEditorActivationMouseEvent;
import spark.events.GridEvent;
import spark.events.GridItemEditorEvent;

use namespace mx_internal;


/**
 *  The DataGridEditor contains all the logic and event handling needed to 
 *  manage the life cycle of an item editor. 
 *  A DataGridEditor is owned by a 
 *  specified DataGrid. The owning DataGrid is responsible for calling
 *  initialize() to enable editing and uninitialize() when editing is no 
 *  longer needed.
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
public class DataGridEditor
{
    include "../../core/Version.as";    

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor
     * 
     *  @param dataGrid The owner of this editor.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function DataGridEditor(dataGrid:DataGrid)
    {
        _dataGrid = dataGrid;
        
    }
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------
    /**
     *  @private
     *  Timer used to cancel edits if a double click occurs.
     */
    private var doubleClickTimer:Timer;
    
    /**
     *  @private
     *  True if we have received double click event since the last click.
     */
    private var gotDoubleClickEvent:Boolean;

    /**
     *  @private
     *  True if we have received a FlexEvent.ENTER.
     */
    private var gotFlexEnterEvent:Boolean;
    
    /**
     *  @private
     */
    private var lastEvent:Event;

    /**
     *  @private
     *  Position of the last item renderer that was clicked.
     */
    private var lastItemClickedPosition:Object;
    
    /**
     *  @private
     *  Used to make sure the mouse up is on the same item
     *  renderer as the mouse down.
     */
    private var lastItemDown:IVisualElement;
    
    /**
     *  @private
     *  the last editedItemPosition and the last
     *  position where editing was attempted if editing
     *  was cancelled.  
     */
    private var lastEditedItemPosition:*;
    
    /**
     *  @private
     *  Determines if the hasFocusableChildren flags are restored when
     *  an editor is destroyed. This is set to false when we know we will
     *  be starting up another editor immeditiately. By not restoring
     *  the tab children flag we will be saving FocusManager from removing
     *  and then adding all the focusable children of the data grid.
     */
    private var restoreFocusableChildren:Boolean = true;

    /**
     *  @private
     *  Used to restore the value of DataGrid's hasFocusableChildren.
     */
    private var saveDataGridHasFocusableChildren:Boolean;
    
    /**
     *  @private
     *  Used to restore the value of scroller's hasFocusableChildren.
     */
    private var saveScrollerHasFocusableChildren:Boolean;

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

    /**
     *  @private
     */
    private var _dataGrid:DataGrid;

    /**
     *  Reference to the <code>DataGrid</code> that created the editor.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get dataGrid():DataGrid
    {
        return _dataGrid;    
    }
    
    /**
     *  Convenience property to get the <code>Grid</code> associated with the parent <code>DataGrid</code>.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get grid():Grid
    {
        return _dataGrid.grid;        
    }

    //----------------------------------
    //  editedItemPosition
    //----------------------------------
    
    /**
     *  @private
     */
    private var _editedItemPosition:Object;
    
    /**
     *  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;
    }
    
    /**
     *  Sets the edited item position based on the grids <code>rowIndex</code> and <code>columnIndex</code>.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function set editedItemPosition(value:Object):void
    {
        if (!value)
        {
            setEditedItemPosition(null);
            return;
        }
        
        var newValue:Object = {rowIndex: value.rowIndex,
            columnIndex: value.columnIndex};
        
        setEditedItemPosition(newValue);
    }
    
    /**
     *  @private
     */
    private function setEditedItemPosition(coord:Object):void
    {
        if (!grid.enabled || !dataGrid.editable)
            return;
        
        if (!grid.dataProvider || grid.dataProvider.length == 0)
            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)
        {
            if (!dataGrid.endItemEditorSession())
                return;
        }
        
        // store the value
        _editedItemPosition = coord;
        
        // allow setting of undefined to dispose item editor instance
        if (!coord)
            return;
        
        var rowIndex:int = coord.rowIndex;
        var columnIndex:int = coord.columnIndex;
        
        dataGrid.ensureCellIsVisible(rowIndex, columnIndex);
        
        createItemEditor(rowIndex, columnIndex);
        
        if (itemEditorInstance is IInvalidating)
            IInvalidating(itemEditorInstance).validateNow();
        
        var column:GridColumn = dataGrid.columns.getItemAt(columnIndex) as GridColumn;
        if (itemEditorInstance is IIMESupport)
            IIMESupport(itemEditorInstance).imeMode =
                (column.imeMode == null) ? dataGrid.imeMode : column.imeMode;
        
        var fm:IFocusManager = grid.focusManager;
        if (itemEditorInstance is IFocusManagerComponent)
        {
            // Temporarily remove the FOCUS_OUT handler: if we give the editor the focus and
            // it immediately vectors it to a non-editor descendant, like to the mobile soft 
            // keyboard, we don't want to end the editor session.
            
            itemEditorInstance.removeEventListener(FocusEvent.FOCUS_OUT, editor_focusOutHandler);            
            fm.setFocus(IFocusManagerComponent(itemEditorInstance));
            itemEditorInstance.addEventListener(FocusEvent.FOCUS_OUT, editor_focusOutHandler);             
        }
        
        lastEditedItemPosition = _editedItemPosition;
        
        // Notify event that a new editor is starting.
        // Don't dispatch life cycle events for item renderers.
        var dataGridEvent:GridItemEditorEvent = null;
        
        if (column.rendererIsEditable == false)
            dataGridEvent = new GridItemEditorEvent(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_START);
        
        if (dataGridEvent)
        {
            dataGridEvent.columnIndex = editedItemPosition.columnIndex;
            dataGridEvent.column = column;
            dataGridEvent.rowIndex = editedItemPosition.rowIndex;
            dataGrid.dispatchEvent(dataGridEvent);
        }
    }

    /**
     *  @private
     *  true if we're in the endEdit call.  Used to handle
     *  some timing issues with collection updates
     */
    private var inEndEdit:Boolean = false;
    
    /**
     *  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>DataGridColumn.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:IGridItemEditor;
    
    
    /**
     *  @private
     */
    private var _editedItemRenderer:IVisualElement;
    
    /**
     *  A reference to the item renderer
     *  in the DataGrid 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():IVisualElement
    {
        return _editedItemRenderer;
    }
    
    //----------------------------------
    //  editorColumnIndex
    //----------------------------------
    
    /**
     *  The zero-based column index of the cell that is being edited. The 
     *  value is -1 if no cell is being edited.
     * 
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 4.5
     */
    public function get editorColumnIndex():int
    {
        if (editedItemPosition)
            return editedItemPosition.columnIndex;
        
        return -1;
    }
    
    //----------------------------------
    //  editorRowIndex
    //----------------------------------
    
    /**
     *  The zero-based row index of the cell that is being edited. The 
     *  value is -1 if no cell is being edited.
     * 
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 4.5
     */
    public function get editorRowIndex():int
    {
        if (editedItemPosition)
            return editedItemPosition.rowIndex;
        
        return -1;
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Called by the <code>DataGrid</code> after construction to initialize the editor. No
     *  item editors can be created until after this method is called.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */  
    public function initialize():void
    {
        // add listeners to enable cell editing
        var grid:Grid = dataGrid.grid;

        dataGrid.addEventListener(KeyboardEvent.KEY_DOWN, dataGrid_keyboardDownHandler);
        
        // Make sure we get first shot at mouse events before selection is changed. We use 
        // this is test if you are clicking on a selected row or not.
        grid.addEventListener(GridEvent.GRID_MOUSE_DOWN, grid_gridMouseDownHandler, false, 1000);
        grid.addEventListener(GridEvent.GRID_MOUSE_UP, grid_gridMouseUpHandler, false, 1000);
        grid.addEventListener(GridEvent.GRID_DOUBLE_CLICK, grid_gridDoubleClickHandler);
        grid.addEventListener(MouseEvent.MOUSE_WHEEL, grid_gridMouseWheelHandler, false, 0);
    }
    
    /**
     *  The method is called to disable item editing on the <code>DataGrid</code>.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */ 
    public function uninitialize():void
    {
        // remove listeners to disable cell editing   
        grid.removeEventListener(KeyboardEvent.KEY_DOWN, dataGrid_keyboardDownHandler);
        grid.removeEventListener(GridEvent.GRID_MOUSE_DOWN, grid_gridMouseDownHandler);
        grid.removeEventListener(GridEvent.GRID_MOUSE_UP, grid_gridMouseUpHandler);
        grid.removeEventListener(GridEvent.GRID_DOUBLE_CLICK, grid_gridDoubleClickHandler);
        grid.removeEventListener(MouseEvent.MOUSE_WHEEL, grid_gridMouseWheelHandler);
    }
    
    /**
     *  @private
     *  
     *  This method closes an item editor currently open on an item renderer. 
     *  You typically only call this method 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
     */
    mx_internal function destroyItemEditor():void
    {
        // trace("destroyItemEditor");
        if (grid.root)
            grid.systemManager.removeEventListener(Event.DEACTIVATE, deactivateHandler);
        
        grid.systemManager.getSandboxRoot().
            removeEventListener(MouseEvent.MOUSE_DOWN, sandBoxRoot_mouseDownHandler, true);
        grid.systemManager.getSandboxRoot().
            removeEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE, sandBoxRoot_mouseDownHandler);
        grid.systemManager.removeEventListener(Event.RESIZE, editorAncestorResizeHandler);
        dataGrid.removeEventListener(Event.RESIZE, editorAncestorResizeHandler);
        
        if (itemEditorInstance || editedItemRenderer)
        {
            if (itemEditorInstance)
                itemEditorInstance.discard();
            
            var o:IVisualElement = (itemEditorInstance ? 
                                    itemEditorInstance : editedItemRenderer);
            
            o.removeEventListener(KeyboardEvent.KEY_DOWN, editor_keyDownHandler);
            o.removeEventListener(FocusEvent.FOCUS_OUT, editor_focusOutHandler);
            o.removeEventListener(Event.REMOVED_FROM_STAGE, editor_removedFromStageHandler);
            o.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, editor_keyFocusChangeHandler);
            addRemoveFlexEventEnterListener(DisplayObject(o), false);
            
            if (grid.focusManager)
                grid.focusManager.defaultButtonEnabled = true;
            
            // setfocus back to us so something on stage has focus
            dataGrid.setFocus();
            
            // defer focus can cause focusOutHandler to destroy the editor
            // and make itemEditorInstance null
            if (itemEditorInstance)
                grid.removeElement(itemEditorInstance);
            else
                grid.invalidateDisplayList();   // force the editorIndicator to be redrawn
            
            if (restoreFocusableChildren)
            {
                restoreFocusableChildrenFlags();
            }
            
            itemEditorInstance = null;
            _editedItemRenderer = null;
            _editedItemPosition = null;
        }
    }
    
    /**
     *  @private
     * 
     *  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>
     *
     *  @param rowIndex The row index in the data provider of the item to be edited.
     *  @param columnIndex The column index in the data provider of the item to be edited.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal function createItemEditor(rowIndex:int, columnIndex:int):void
    {
        // check for bad values
        if (columnIndex >= grid.columns.length)
            return;
        
        var col:GridColumn = grid.columns.getItemAt(columnIndex) as GridColumn;
        var item:IGridItemRenderer = grid.getItemRendererAt(rowIndex, columnIndex);
        var cellBounds:Rectangle = grid.getCellBounds(rowIndex,columnIndex);
        var localCellOrigin:Point = cellBounds.topLeft;
        
        _editedItemRenderer = item;
        
        // Need to turn on focusable children flag so focus manager will
        // allow focus into the data grid's children.
        if (restoreFocusableChildren)
            saveDataGridHasFocusableChildren = dataGrid.hasFocusableChildren; 
        dataGrid.hasFocusableChildren = true;
        
        if (dataGrid.scroller)
        {
            //Correct the item edit positioning based on the scroll position.
            localCellOrigin.x -= grid.horizontalScrollPosition;
            localCellOrigin.y -= grid.verticalScrollPosition;

            if (restoreFocusableChildren)
                saveScrollerHasFocusableChildren = dataGrid.scroller.hasFocusableChildren; 
            dataGrid.scroller.hasFocusableChildren = true;
        }
        
        restoreFocusableChildren = true;
        
        if (!col.rendererIsEditable)
        {
            // First use the column's itemEditor.
            // If that is unspecified try the dataGrid's itemEditor.
            // If that is unspecified then use the default itemEditor
            // set on the column.
            var itemEditor:IFactory = col.itemEditor;
            if (!itemEditor)
                itemEditor = dataGrid.itemEditor;
            if (!itemEditor)
                itemEditor = GridColumn.defaultItemEditorFactory;
            
            if (itemEditor == GridColumn.defaultItemEditorFactory)
            {
                // if it is the default factory, see if someone
                // overrode it with this style
                var c:Class = dataGrid.getStyle("defaultDataGridItemEditor");
                if (c)
                {
                    itemEditor = col.itemEditor = new ClassFactory(c);
                }
            }
            
            itemEditorInstance = itemEditor.newInstance();
            itemEditorInstance.owner = dataGrid;
            itemEditorInstance.rowIndex = rowIndex;
            itemEditorInstance.column = col;
            itemEditorInstance.hasFocusableChildren = true;

            if (itemEditorInstance is ISimpleStyleClient)
                ISimpleStyleClient(itemEditorInstance).styleName = item;
            
            // Add the editor to the grid before setting the data so that
            // the editor's children will be created.
            grid.addElement(itemEditorInstance);
            
            itemEditorInstance.data = item.data;
            
            // The editor will overlay the cell, covering the first pixel of the 
            // cell separators. This is done so that a cell editor with borders 
            // will overlay the cell separators. It prevents the cell separators
            // from adding borders to the editor for the common case when the cell
            // separators are only 1 pixel wide.
            itemEditorInstance.width = cellBounds.width + 1;
            itemEditorInstance.height = cellBounds.height + 1;
            itemEditorInstance.setLayoutBoundsPosition(localCellOrigin.x, localCellOrigin.y);
            
            if (itemEditorInstance is IInvalidating)
                IInvalidating(itemEditorInstance).validateNow();
            
            // Allow the user code to make any final adjustments and make the editor visible.
            itemEditorInstance.prepare();
            itemEditorInstance.visible = true;
        }
        else
        {
            setFocusInItemRenderer(item);
        }
        
        if (itemEditorInstance || editedItemRenderer)
        {
            var editor:IEventDispatcher = itemEditorInstance ? itemEditorInstance : editedItemRenderer;
            
            editor.addEventListener(FocusEvent.FOCUS_OUT, editor_focusOutHandler);
			editor.addEventListener(Event.REMOVED_FROM_STAGE, editor_removedFromStageHandler);
            // listen for keyStrokes on the itemEditorInstance (which lets the grid supervise for ESC/ENTER)
            editor.addEventListener(KeyboardEvent.KEY_DOWN, editor_keyDownHandler);
            editor.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, editor_keyFocusChangeHandler, false, 1000);
            addRemoveFlexEventEnterListener(DisplayObject(editor), true);
            
        }
        
        if (grid.focusManager)
            grid.focusManager.defaultButtonEnabled = false;

        // Invalidate the grid so the editor indicator will be shown.
        grid.invalidateDisplayList();
        
        if (grid.root)
            grid.systemManager.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);
        
        // we disappear on any mouse down outside the editor
        grid.systemManager.getSandboxRoot().
            addEventListener(MouseEvent.MOUSE_DOWN, sandBoxRoot_mouseDownHandler, true, 0, true);
        grid.systemManager.getSandboxRoot().
            addEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE, sandBoxRoot_mouseDownHandler, false, 0, true);
        // we disappear if stage or our grid is resized
        grid.systemManager.addEventListener(Event.RESIZE, editorAncestorResizeHandler);
        grid.addEventListener(Event.RESIZE, editorAncestorResizeHandler);        
    }
    
    /**
     *  @private
     */ 
    private function setFocusInItemRenderer(item:IGridItemRenderer):void
    {
        // if the item renderer is editable then set focus
        // to the first item that should get focus.
        if (grid.focusManager && grid.focusManager is FocusManager)
        {
            var fm:FocusManager = grid.focusManager as FocusManager;
            var o:DisplayObject = item as DisplayObject;
            var firstComponent:DisplayObject = null;
            var found:Boolean = false;
            
            // find the first component to take focus inside the renderer.
            do
            {
                fm.fauxFocus = o;
                o = fm.getNextFocusManagerComponent(false) as DisplayObject;
                if (o == item || 
                    item is DisplayObjectContainer && 
                    DisplayObjectContainer(item).contains(o))
                {
                    found = true;
                    break;
                }

                // prevent infinite loop
                if (!firstComponent)
                    firstComponent = o;
                else if (firstComponent == o)
                    break;
                
            } while (o && dataGrid.contains(o));
            
            // if we are moving backward then put focus on the last
            // item in the renderer instead of the first.
            if (found && wasLastEventMovingBackward())
            {
                // put focus on last item in cell editor instead of first.
                var lastItem:DisplayObject = o;
                do
                {
                    fm.fauxFocus = o;
                    lastItem = o;
                    o = fm.getNextFocusManagerComponent(false) as DisplayObject;
                } while (o && DisplayObjectContainer(item).contains(o));
                
                o = lastItem;
            }
            
            fm.fauxFocus = null;
            
            if (found)
            {
                fm.setFocus(IFocusManagerComponent(o));
                
                // Since we may have gotton here with the F2 key show the focus
                // indicator to make it obvious which control has focus.
                fm.showFocus();
            }
        }
    }
    
    /**
     *  @private
     */
    private function wasLastEventMovingBackward():Boolean
    {
        if (lastEvent)
        {
            // Last event was a key focus change moving backward.
            if (lastEvent.type == FocusEvent.KEY_FOCUS_CHANGE &&
                FocusEvent(lastEvent).shiftKey)
            {
                return true;
            }
            
            // Last event was Shift+TAB
            if (lastEvent.type == KeyboardEvent.KEY_DOWN && 
                KeyboardEvent(lastEvent).keyCode == Keyboard.TAB &&
                KeyboardEvent(lastEvent).shiftKey)
            {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     *  Start editing a cell for a specified row and column index.
     *  
     *  Dispatches a <code>GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_STARTING
     *  </code> event. 
     * 
     *  @param rowIndex The zero-based row index of the cell to edit.
     * 
     *  @param columnIndex The zero-based column index of the cell to edit.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function startItemEditorSession(rowIndex:int, columnIndex:int):Boolean
    {
        
        // validate row and column index
        if (!isValidCellPosition(rowIndex, columnIndex))
            return false;
            
        dataGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_STARTING,
                                  dataGrid_gridItemEditorSessionStartingHandler,
                                  false, EventPriority.DEFAULT_HANDLER);
        
        var column:GridColumn = grid.columns.getItemAt(columnIndex) as GridColumn;
        
        if (!column || !column.visible)
            return false;
        
        // The START_GRID_ITEM_EDITOR_SESSION event is cancelable
        var dataGridEvent:GridItemEditorEvent = new GridItemEditorEvent(
                                                        GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_STARTING, 
                                                        false, true); 
        dataGridEvent.rowIndex = Math.min(rowIndex, grid.dataProvider.length - 1);
        dataGridEvent.columnIndex = Math.min(columnIndex, grid.columns.length - 1);
        dataGridEvent.column = column;

        // Don't send a life cycle event if the cell contains an item renderer.
        var editorStarted:Boolean = false;
        if (column.rendererIsEditable == true)
        {
            dataGrid_gridItemEditorSessionStartingHandler(dataGridEvent);   // start editor session without the option to cancel
            editorStarted = true;
        }
        else 
        {
            editorStarted = dataGrid.dispatchEvent(dataGridEvent);         
        }
            
        if (editorStarted) 
        {
            lastEditedItemPosition = { columnIndex: columnIndex, rowIndex: rowIndex };
            
            dataGrid.grid.caretRowIndex = rowIndex;
            dataGrid.grid.caretColumnIndex = columnIndex;
        }
        
        restoreFocusableChildren = true;
        dataGrid.removeEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_STARTING,
                                     dataGrid_gridItemEditorSessionStartingHandler);
        
        return editorStarted;
    }
    
    /**
     *  Closes the currently active editor and optionally saves the editor's value
     *  by calling the item editor's save() method.  If the cancel parameter is true,
     *  then the editor's cancel() method is called instead.
     * 
     *  @param cancel if true then the data in the editor is discarded, 
     *  otherwise it's saved.
     * 
     *  @return true if the data in the editor was saved, false otherwise.
     * 
     *  @see spark.components.IGridItemEditor
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.0
     *  @productversion Flex 4.5
     */ 
    public function endItemEditorSession(cancel:Boolean = false):Boolean
    {
        if (cancel)
        {
            cancelEdit();
            return false;
        }
        else
        {
            return endEdit();
        }
    }
    
    /**
     *  @private
     * 
     *  Close the item editor without saving the data.
     */
    mx_internal function cancelEdit():Boolean
    {
        if (itemEditorInstance)
        {
            if (itemEditorInstance.cancel())
            {
                // send the cancel event and tear down the editor.
                dispatchCancelEvent();
                destroyItemEditor();
            }
            else
            {
                return false;
            }
        }
        else if (editedItemRenderer)
        {
            // cancel focus in an item editor by setting focus back to the grid.
            destroyItemEditor();
        }

        return true;                   

    }

    
    /**
     *  @private
     * 
     *  Notify event that the editor session is cancelled.
     *  This event cannot be cancelled.
     */
    private function dispatchCancelEvent():void
    {
        var dataGridEvent:GridItemEditorEvent =
            new GridItemEditorEvent(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_CANCEL);
        
        dataGridEvent.columnIndex = editedItemPosition.columnIndex;
        dataGridEvent.column = itemEditorInstance.column;
        dataGridEvent.rowIndex = dataGrid.dataProvider ? dataGrid.dataProvider.getItemIndex(itemEditorInstance.data) : -1;
        dataGrid.dispatchEvent(dataGridEvent);
    }
    
    /**
     *  @private
     * 
     *  When the user finished editing an item, this method is called to close 
     *  the editor and save the data.
     *  
     */
    private function endEdit():Boolean
    {
        // Focus is inside an item renderer
        if (!itemEditorInstance && editedItemRenderer)
        {
            inEndEdit = true;
            destroyItemEditor();
            inEndEdit = false;
            return true;
        }
        
        // this happens if the renderer is removed asynchronously ususally with FDS
        if (!itemEditorInstance)
            return false;
        
        inEndEdit = true;
        
        var itemPosition:Object = editedItemPosition;
        var editedItem:Object = itemEditorInstance.data;
        if (!saveItemEditorSession())
        {
            // The save was cancelled so check if the editor can be cancelled.
            // If it can then dispatch a cancel event.
            if (itemEditorInstance.cancel())
                dispatchCancelEvent();
            
            inEndEdit = false;
            return false;
        }
        
        var dataGridEvent:GridItemEditorEvent =
            new GridItemEditorEvent(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE);
        
        // GRID_ITEM_EDITOR_SESSION_SAVE events are NOT cancelable
        dataGridEvent.columnIndex = itemPosition.columnIndex;
        dataGridEvent.column = dataGrid.columns.getItemAt(itemPosition.columnIndex) as GridColumn;
        dataGridEvent.rowIndex = dataGrid.dataProvider ? dataGrid.dataProvider.getItemIndex(editedItem) : -1;
        dataGrid.dispatchEvent(dataGridEvent);

        inEndEdit = false;
        
        return true;
    }
    
    /**
     *  @private
     *  Save the editor session. The developer can still cancel out so the 
     *  data may not be saved.
     * 
     *  @return true if the data is saved, false otherwise.
     */
    private function saveItemEditorSession():Boolean
    {
        var dataSaved:Boolean = false;
        
        if (itemEditorInstance)
        {
            dataSaved = itemEditorInstance.save();
            
            if (dataSaved)
                destroyItemEditor();
        }
        
        return dataSaved;
    }
    
    /**
     *  @private
     *  Start an editor session in the next editable cell. 
     *
     *  @param rowIndex zero-based row index to start search from, inclusive.
     *  @param columnIndex zero-based column index to start search from, not inclusive. 
     *  @param backward - if true move backward column by column and then row by row.
     *  If false, then move forward column by column, row by row.
     * 
     *  @return true if an editor was opened, false otherwise.
     * 
     */
    private function openEditorInNextEditableCell(rowIndex:int, columnIndex:int, backward:Boolean):Boolean
    {
        var nextCell:Point = new Point(rowIndex, columnIndex);
        var openedEditor:Boolean = false;
        
        do
        {
            nextCell = getNextEditableCell(nextCell.x, nextCell.y, backward);
            
            if (nextCell)
                openedEditor = dataGrid.startItemEditorSession(nextCell.x, nextCell.y);                
        } while (nextCell && !openedEditor);
        
        return openedEditor;
    }
    
    /**
     *  @private
     *  Find the next editable cell. 
     * 
     *  @param rowIndex zero-based row index to start search from, inclusive.
     *  @param columnIndex zero-based column index to start search from, not inclusive. 
     *  @param backward - if true move backward column by column and then row by row.
     *  If false, then move forward column by column, row by row.
     * 
     *  @return If an editable cell was found then return a Point with the x property
     *  containing the rowIndex and the y property containing the column index. If no
     *  editable cell was found then null is returned.
     */
    private function getNextEditableCell(rowIndex:int, columnIndex:int, backward:Boolean):Point
    {
        // what is the next cell?
        // increment is -1 if we are moving backward and 1 if moving
        // forward.
        const increment:int = backward ? -1 : 1;
        //var rowIndex:int = rowIndex;
        //var columnIndex:int = columnIndex;
        do {
            var nextColumn:int = columnIndex + increment;
            if (nextColumn >= 0 && nextColumn < dataGrid.columns.length)
            {
                columnIndex += increment;    
            }
            else
            {
                // move to next row.
                columnIndex = backward ? dataGrid.grid.columns.length - 1: 0;
                var nextRow:int = rowIndex + increment;
                if (nextRow >= 0 && nextRow < dataGrid.dataProvider.length)
                    rowIndex += increment;
                else
                    return null;
            }
        } while (!canEditColumn(columnIndex));
        
        return new Point(rowIndex, columnIndex);
    }
    
    
    /**
     *  @private
     * 
     *  @param columnIndex
     * 
     *  @return true if the column can be edited, false otherwise.
     */ 
    private function canEditColumn(columnIndex:int):Boolean
    {
        var column:GridColumn = grid.columns.getItemAt(columnIndex) as GridColumn; 
        return (dataGrid.editable && 
                column.editable &&
                column.visible);
    }
    
    /**
     *  @private
     * 
     *  Test if the cell was selected at the last selection snapshot.
     */
    private function wasCellPreviouslySelected(rowIndex:int, columnIndex:int):Boolean
    {
        if (dataGrid.isRowSelectionMode())
            return dataGrid.selectionContainsIndex(rowIndex);
        else if (dataGrid.isCellSelectionMode())
            return dataGrid.selectionContainsCell(rowIndex, columnIndex);
        
        return false;
    }

    /**
     *  @private
     *
     *  Determine if a cell position is valid.
     * 
     *  @return true if valid, false otherwise.  
     */
    private function isValidCellPosition(rowIndex:int, cellIndex:int):Boolean
    {
        if (rowIndex >= 0 && rowIndex < dataGrid.dataProvider.length &&
            cellIndex >= 0 && cellIndex < dataGrid.columns.length)
        { 
            return true;
        }
        
        return false;
    }
    
    /**
     *  @private
     *  
     *  Add a FlexEvent.ENTER listener to all child IVisualElements.
     * 
     *  @param element add listener to element and its children.
     *  @param addListener if true add a listener, otherwise remove a listener.
     */
    private function addRemoveFlexEventEnterListener(element:DisplayObject, addListener:Boolean):void
    {
        if (addListener)
            element.addEventListener(FlexEvent.ENTER, editor_enterHandler);
        else
            element.removeEventListener(FlexEvent.ENTER, editor_enterHandler);
        
        if (element is DisplayObjectContainer)
        {
            var container:DisplayObjectContainer = DisplayObjectContainer(element);
            var n:int = container.numChildren;
            for (var i:int = 0; i < n; i++)
            {
                var child:DisplayObject = container.getChildAt(i);
                
                if (child is DisplayObjectContainer)
                {
                    addRemoveFlexEventEnterListener(child, addListener);
                }
                else
                {
                    if (addListener)
                        child.addEventListener(FlexEvent.ENTER, editor_enterHandler);
                    else
                        child.removeEventListener(FlexEvent.ENTER, editor_enterHandler);
                }
            }
        }
        
    }
    
    /**
     *  @private
     *  Check if a mouse click occured within the editor.
     * 
     *  @param event A MouseEvent or a SandboxMouseEvent
     * 
     *  @return true if the target is within the editor, false otherwise.
     */ 
    private function editorOwnsClick(event:Event):Boolean
    {
        if (event is MouseEvent)
        {
            var target:IUIComponent = getIUIComponent(DisplayObject(event.target));
            if (target)
                return editorOwns(target);
        }

        return false;
    }
    
    /**
     *  @private
     *  Check if a child is contained within the editor using the owns() method.
     *  The editor can be either editedItemRenderer or itemEditorInstance.
     * 
     *  @param child child to test.
     *  @return true if the child is owned by the editor.
     */ 
    private function editorOwns(child:IUIComponent):Boolean
    {
        return (itemEditorInstance &&
                (itemEditorInstance == child || 
                    IUIComponent(itemEditorInstance).owns(DisplayObject(child))) ||
            (editedItemRenderer &&
                (editedItemRenderer == child || 
                     IUIComponent(editedItemRenderer).owns(DisplayObject(child)))));
    }
 
    /**
     *  @private
     *  The IUIComponent related to a given object. If the object is not a IUIComponent
     *  then work up the display list until we find a IUIComponent. 
     *  @param  displayObject The object to get a IUIComponet from.
     *  @return returns the displayObject if it is a display object or its 
     *  closest parent that is a display object. 
     */ 
    private function getIUIComponent(displayObject:DisplayObject):IUIComponent
    {
        if (displayObject is IUIComponent)
            return IUIComponent(displayObject);
        
        var current:DisplayObject = displayObject.parent;
        while (current)
        {
            if (current is IUIComponent)
                return IUIComponent(current);
            
            current = current.parent;
        }
        
        return null;
    }
    
    /**
     *  @private
     * 
     *  Restore the focusable children flags.
     */ 
    private function restoreFocusableChildrenFlags():void
    {
        dataGrid.hasFocusableChildren = saveDataGridHasFocusableChildren;
        
        if (dataGrid.scroller)
            dataGrid.scroller.hasFocusableChildren = saveScrollerHasFocusableChildren;

    }
    
    /**
     *  @private
     * 
     *  Get the effective mouse event that activates an editor.
     *  If the column has a setting, then use it. Otherwise use the setting on
     *  the data grid.
     */ 
    private function getEditorActivationMouseEvent(columnIndex:int):String
    {
        var editorActivationMouseEvent:String = null;
        
        if (columnIndex >= 0 && columnIndex < dataGrid.columns.length)
        {
            var column:GridColumn = grid.columns.getItemAt(columnIndex) as GridColumn; 
            editorActivationMouseEvent = column.editorActivationMouseEvent;    
        }
        
        if (!editorActivationMouseEvent)
            editorActivationMouseEvent = dataGrid.editorActivationMouseEvent;
        
        return editorActivationMouseEvent;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     * 
     *  Default handler for the startItemEditorSession event.
     * 
     */
    private function dataGrid_gridItemEditorSessionStartingHandler(event:GridItemEditorEvent):void
    {
        // trace("itemEditorItemEditBeginningHandler");
        if (!event.isDefaultPrevented())
        {
            setEditedItemPosition({columnIndex: event.column.columnIndex, rowIndex: event.rowIndex});
        }
        else if (!itemEditorInstance)
        {
            _editedItemPosition = null;
            
            // return focus to the grid w/o selecting an item
            dataGrid.setFocus();
        }
    }
    
    /**
     *  @private
     * 
     *  Handle the F2 key to start editing a cell.
     */
    private function dataGrid_keyboardDownHandler(event:KeyboardEvent):void
    {
        if (!dataGrid.editable || dataGrid.selectionMode == GridSelectionMode.NONE)
            return;
        
        if (event.isDefaultPrevented())
            return;
        
        lastEvent = event;
        
        if (event.keyCode == dataGrid.editKey)
        {
            // ignore F2 if we are already editing a cell or the column is not
            // editable
            if (itemEditorInstance)
                return;
            
            // Edit the last column edited. If no last column then try to 
            // edit the first column.
            var nextCell:Point = null;
            if (dataGrid.isRowSelectionMode())
            {
                var lastColumn:int = lastEditedItemPosition ? lastEditedItemPosition.columnIndex : 0;
                openEditorInNextEditableCell(dataGrid.grid.caretRowIndex, 
                                                        lastColumn - 1,
                                                        false);
                return;
            }
            else if (canEditColumn(grid.caretColumnIndex))
            {
                dataGrid.startItemEditorSession(grid.caretRowIndex, grid.caretColumnIndex);                
            }
        }            
    }
    
    /**
     *  @private
     * 
     */
    private function grid_gridMouseDownHandler(event:GridEvent):void
    {
        //trace("grid_gridMouseDownHandler");
        gotDoubleClickEvent = false;

        // check if the mouse was clicked outside of the editor. If it was
        // then end the editing session.
        if (!dataGrid.editable || editorOwnsClick(event))
            return;

        if (!isValidCellPosition(event.rowIndex, event.columnIndex))
            return;
        
        lastEvent = event;
        
        const rowIndex:int = event.rowIndex;
        const columnIndex:int = event.columnIndex;
        
        //trace("grid_gridMouseDownHandler: (rowIndex, columnIndex) = (" + rowIndex + "," + columnIndex + ")");
        
        // item editor handling
        var r:IGridItemRenderer = event.itemRenderer;
        
        lastItemDown = null;
        
        // if selection is being modified with shift or ctrl keys then
        // don't start up an editor session.
        if (event.shiftKey || event.ctrlKey)
            return;
        
        // if an editor is already up, close it without starting a new editor.
        if (itemEditorInstance)
        {
            // if the user clicks outside the cell but we can't save the data,
            // say, because the data was invalid, then cancel the save.
            if (!dataGrid.endItemEditorSession())
            {
                dataGrid.endItemEditorSession(true);
            }
            return;
        }
        
        var editorActivationMouseEvent:String = getEditorActivationMouseEvent(columnIndex);
        if (editorActivationMouseEvent != GridItemEditorActivationMouseEvent.SINGLE_CLICK && 
            editorActivationMouseEvent != GridItemEditorActivationMouseEvent.SINGLE_CLICK_ON_SELECTED_CELL)
        {
            return;     // not allowed to start editor on a single click
        }
        
        // Don't open and editor if the click was not on a previously selected 
        // cell, unless that cell is an item renderer. We don't want to stop 
        // the item renderer from getting focus so start an edit session.
        const column:GridColumn = dataGrid.columns.getItemAt(columnIndex) as GridColumn;
        if (r && 
            (column.rendererIsEditable || 
             (wasCellPreviouslySelected(rowIndex, columnIndex) && 
                 editorActivationMouseEvent == GridItemEditorActivationMouseEvent.SINGLE_CLICK_ON_SELECTED_CELL) ||
             editorActivationMouseEvent == GridItemEditorActivationMouseEvent.SINGLE_CLICK))
        {
            //trace("cell was previously selected: (" + rowIndex + "," + columnIndex + ")");  
            lastItemDown = r;
        }
        
    }
    
    /**
     *  @private
     * 
     *  If clicked on a the same cell as mouse down then start editing the cell.
     */
    private function grid_gridMouseUpHandler(event:GridEvent):void
    {
        //trace("grid_gridMouseUpHandler");
        
        if (!dataGrid.editable)
            return;

        if (!isValidCellPosition(event.rowIndex, event.columnIndex))
            return;
        
        lastEvent = event;
        
        const eventRowIndex:int = event.rowIndex;
        const eventColumnIndex:int = event.columnIndex;
        
        // Only start an edit if the row is the only selected row.
        // Only start editing when one row is selected.
        if (dataGrid.selectionLength != 1)
            return;
        
        const rowIndex:int = eventRowIndex;
        var columnIndex:int = eventColumnIndex;
        
        var editorActivationMouseEvent:String = getEditorActivationMouseEvent(columnIndex);
        if (editorActivationMouseEvent != GridItemEditorActivationMouseEvent.SINGLE_CLICK && 
            editorActivationMouseEvent != GridItemEditorActivationMouseEvent.SINGLE_CLICK_ON_SELECTED_CELL)
        {
            return;     // not allowed to start editor on a single click
        }
        
        var r:IVisualElement = event.itemRenderer;
        //trace("grid_gridMouseUpHandler: itemRenderer = " + event.itemRenderer);  
        if (r && r != editedItemRenderer && 
            lastItemDown && lastItemDown == r)
        {
            if (columnIndex >= 0)
            {
                if (grid.columns.getItemAt(columnIndex).editable)
                {
                    // Check if clicking again on the same item
                    if (doubleClickTimer)
                    {
                        if (rowIndex == lastItemClickedPosition.rowIndex &&
                            columnIndex == lastItemClickedPosition.columnIndex)
                        {
                            // Clicked on the same item again and we 
                            // already have a timer. Wait on the existing timer.
                            lastItemDown == null;
                            return;
                        }
                        else 
                        {
                            // Clicked on a different item. Stop the timer and start a new one
                            doubleClickTimer.stop();
                            doubleClickTimer = null;
                        }
                    }
                    
                    lastItemClickedPosition = { columnIndex: columnIndex, rowIndex: rowIndex};
                    
                    // If double click is not enabled or we want a double click to open an
                    // editor, then open the editor directly now. Otherwise start a timer
                    // and wait to see if a double click comes in that will cancel the edit.
                    if (dataGrid.editOnDoubleClick || 
                        InteractiveObject(lastItemDown).doubleClickEnabled == false)
                    {
                        // we don't need to wait on the time since editing double click is ok.
                        dataGrid.startItemEditorSession(rowIndex, columnIndex);
                    }
                    else 
                    {
                        doubleClickTimer = new Timer(dataGrid.doubleClickTime, 1);
                        doubleClickTimer.addEventListener(TimerEvent.TIMER, doubleClickTimerHandler);
                        doubleClickTimer.start();                        
                    }
                }
            }
        }
        
        lastItemDown = null;            
    }


    /**
     *  Grid MouseWheel event handler.  Used to end the itemeditor when scrolling on the grid.
     *  Default action is to save the edited contents.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 11.8
     *  @playerversion AIR 3.8
     *  @productversion Flex 4.11
     */
    protected function grid_gridMouseWheelHandler(event:MouseEvent):void
    {
        endEdit();
    }


    /**
     *  @private
     * 
     *  If clicked on a the same cell as mouse down then start editing the cell.
     */
    private function grid_gridDoubleClickHandler(event:GridEvent):void
    {
        //trace("grid_gridDoubleClickHandler: got double click");
        
        if (!dataGrid.editable)
            return;
        
        if (!isValidCellPosition(event.rowIndex, event.columnIndex))
            return;
        
        lastEvent = event;
        
        gotDoubleClickEvent = true;
        
        // If double-click editing is enabled then start up and editor session.
        var editorActivationMouseEvent:String = getEditorActivationMouseEvent(event.columnIndex);
        if (editorActivationMouseEvent == GridItemEditorActivationMouseEvent.DOUBLE_CLICK)
            dataGrid.startItemEditorSession(event.rowIndex, event.columnIndex);
            
    }
    
    /**
     *  @private
     * 
     *  Timer for double click events.
     */
    private function doubleClickTimerHandler(event:TimerEvent):void
    {
        //trace("doubleClickTimerHandler");
        
        doubleClickTimer.removeEventListener(TimerEvent.TIMER, doubleClickTimerHandler);
        doubleClickTimer = null;
        
        if (!gotDoubleClickEvent)
        {
            dataGrid.startItemEditorSession(lastItemClickedPosition.rowIndex, lastItemClickedPosition.columnIndex);
        }

        gotDoubleClickEvent = false;
    }
    
    
    /**
     *  @private
     */
    private function deactivateHandler(event:Event):void
    {
        // If stage losing activation, set focus to DG close the editor and set
        // focus back to the dataGrid.
        if (itemEditorInstance || editedItemRenderer)
        {
            // If we can't save the data, say, because the data was invalid, 
            // then cancel the save.
            if (!dataGrid.endItemEditorSession())
            {
                dataGrid.endItemEditorSession(true);
            }
            dataGrid.setFocus();
        }
    }
    
    /**
     *  @private
     *  Closes the itemEditorInstance if the focus is outside of the data grid.
     */
    private function editor_removedFromStageHandler(event:Event):void
	{
		if (itemEditorInstance || editedItemRenderer)
		{
			// If we can't save the data, say, because the data was invalid, 
			// then cancel the save.
			if (!dataGrid.endItemEditorSession())
			{
				dataGrid.endItemEditorSession(true);
			}
		}
	}
	
    /**
     *  @private
     *  Closes the itemEditorInstance if the focus is outside of the data grid.
     */
    private function editor_focusOutHandler(event:FocusEvent):void
    {
        //trace("editor_focusOutHandler " + event.relatedObject);
        
        // If the focus goes to a component that is owned by the editor, 
        // then don't end the editor session.
        if (event.relatedObject)
        {
            var component:IUIComponent = getIUIComponent(event.relatedObject);
            if (component && editorOwns(component))
                return;                
        }
        
        // ignore textfields losing focus on mousedowns
        if (!event.relatedObject)
            return;
        
        if (itemEditorInstance || editedItemRenderer)
        {
            // If we can't save the data, say, because the data was invalid, 
            // then cancel the save.
            if (!dataGrid.endItemEditorSession())
            {
                dataGrid.endItemEditorSession(true);
            }
        }        
    }
    
    /**
     *  @private
     *  Special case for TextArea control. See editor_keyDownHandler.
     *  ColorPicker also dispatches the "enter" event so keep the
     *  parameter of type Event, not FlexEvent.
     */
    private function editor_enterHandler(event:Event):void
    {
        //trace("FlexEvent" );
        if (event is FlexEvent)
            gotFlexEnterEvent = true;
    }
    
    /**
     *  @private
     * 
     *  Handle keys on the editor to stop the editing session.
     */
    private function editor_keyDownHandler(event:KeyboardEvent):void
    {
        //trace("keyboard event = " + event);
        if (event.isDefaultPrevented())
        {
            // Special case the ENTER key since TextArea cancels the ENTER when it 
            // doesn't use it but instead it dispatches an FlexEvent.ENTER.
            // The problem is the ENTER event does not have the control and 
            // shift key flags we need.
            if (!(event.charCode == Keyboard.ENTER && gotFlexEnterEvent))
            {
                gotFlexEnterEvent = false;
                return;
            }
        }
     
        gotFlexEnterEvent = false;
        
        // ESC just kills the editor, no new data
        if (event.keyCode == Keyboard.ESCAPE)
        {
            cancelEdit();
        }
        else if (event.ctrlKey && event.charCode == 46)
        {   // Check for Ctrl-.
            cancelEdit();
        }
        else if (event.charCode == Keyboard.ENTER && event.keyCode != 229)
        {
            if (!_editedItemPosition)
                return;
            
            // If the ctrl or ctrl and shift keys are down then set a flag to 
            // avoid changing the focusable children flag becaue 
            // need to be redone when starting up the editor again.
            if (event.ctrlKey || (event.ctrlKey && event.shiftKey))
                restoreFocusableChildren = false;
            
            // Enter closes the editor.
            // 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 (dataGrid.endItemEditorSession())
            {
                if (grid.focusManager)
                    grid.focusManager.defaultButtonEnabled = false;
                
                if (event.ctrlKey || (event.ctrlKey && event.shiftKey))
                {
                    var lastRow:int = lastEditedItemPosition ? lastEditedItemPosition.rowIndex : 0;
                    var lastColumn:int = lastEditedItemPosition ? lastEditedItemPosition.columnIndex : 0;
                    
                    if (event.shiftKey)
                        lastRow -= 1;
                    else
                        lastRow += 1;
                    
                    // If we have a valid next row, then start another editor.
                    if (lastRow >= 0 && lastRow < dataGrid.dataProvider.length)
                    {
                        if (!openEditorInNextEditableCell(lastRow, lastColumn - 1, false))
                        {
                            // We didn't start an editor so restore the data grid's
                            // focusable chidlren flags.
                            restoreFocusableChildren = true;
                            restoreFocusableChildrenFlags();
                        }
                    }                        
                }
            }
        }
        
        // Prevent the DataGrid from processing any keystrokes that were 
        // received by the editor. We don't cancel the keystokes here 
        // because on AIR that cancels text input into the text field.
    	// We need to let the copy/cut/past combinations pass through
    	// because they need to reach the NativeApplication in order to
    	// be correctly processed by the item editors.
        // Note on Mac OS ctrlKey covers ctrl and command keys
    	if (!event.ctrlKey) 
    	{
    		event.stopPropagation();
    	}
    }
    
    /**
     *  @private
     *  handle focus changes generated from keyboard keys.
     */
    private function editor_keyFocusChangeHandler(event:FocusEvent):void
    {
        // if we tabbed out of the edit then prevent the tab and
        // save the edit. Next start up a new edit session in the
        // next cell.
        //trace("editor_editor_keyFocusChangeHandler");
        lastEvent = event;
        
        if (itemEditorInstance || editedItemRenderer)
        {
            if (event.isDefaultPrevented())
                return;
            
            var nextObject:IFocusManagerComponent = grid.focusManager.getNextFocusManagerComponent(event.shiftKey);
            if (nextObject == itemEditorInstance ||
                (itemEditorInstance && !DisplayObjectContainer(itemEditorInstance).contains(DisplayObject(nextObject))) ||
                (!itemEditorInstance && 
                    (nextObject == editedItemRenderer ||
                    (editedItemRenderer && !DisplayObjectContainer(editedItemRenderer).contains(DisplayObject(nextObject))))))
            {
                event.preventDefault();
                
                restoreFocusableChildren = false;
                dataGrid.endItemEditorSession();
                
                if (!openEditorInNextEditableCell(lastEditedItemPosition.rowIndex,
                                                  lastEditedItemPosition.columnIndex,
                                                  event.shiftKey))
                {
                    // We didn't start an editor so restore the data grid's
                    // focusable chidlren flags.
                    restoreFocusableChildren = true;
                    restoreFocusableChildrenFlags();                    
                }
            }
        }
    }

    /**
     *  @private
     */
    private function editorAncestorResizeHandler(event:Event):void
    {
        // If we can't save the data, say, because the data was invalid, 
        // then cancel the save.
        if (!dataGrid.endItemEditorSession())
        {
            dataGrid.endItemEditorSession(true);
        }
    }
    
    /**
     *  @private
     */
    private function sandBoxRoot_mouseDownHandler(event:Event):void
    {
        if (editorOwnsClick(event))
        {
            return;
        }
        
        // If clicked on the scroll bars then keep the editor up
        if (dataGrid.scroller && 
            dataGrid.scroller.contains(DisplayObject(event.target)) &&
            !grid.contains(DisplayObject(event.target)))
        {
            return;
        }
        
        // If we can't save the data, say, because the data was invalid, 
        // then cancel the save.
        if (!dataGrid.endItemEditorSession())
        {
            dataGrid.endItemEditorSession(true);
        }
        
        // If the item editor was destroyed then set focus back to the grid 
        // so grid logic will deal if focus doesn't end up somewhere else. 
        if (!itemEditorInstance)
            dataGrid.setFocus();
    }
   
}
}
