////////////////////////////////////////////////////////////////////////////////
//
//  ADOBE SYSTEMS INCORPORATED
//  Copyright 2007 Adobe Systems Incorporated
//  All Rights Reserved.
//
//  NOTICE: Adobe permits you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////

package mx.controls.dataGridClasses
{

import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;

import mx.controls.DataGrid;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.EdgeMetrics;
import mx.core.FlexSprite;
import mx.core.IFlexDisplayObject;
import mx.core.IUIComponent;
import mx.core.LayoutDirection;
import mx.core.UIComponent;
import mx.core.UIComponentGlobals;
import mx.core.mx_internal;
import mx.effects.easing.Back;
import mx.events.DataGridEvent;
import mx.events.SandboxMouseEvent;
import mx.managers.CursorManager;
import mx.managers.CursorManagerPriority;
import mx.skins.halo.DataGridColumnDropIndicator;
import mx.styles.ISimpleStyleClient;
import mx.styles.StyleManager;

use namespace mx_internal;

/** 
 *  The DataGridHeader class defines the default header
 *  renderer for a DataGrid control.  
 *  By default, the header renderer
 *  draws the text associated with each header in the list, and an optional
 *  sort arrow (if sorted by that column).
 *
 *  @see mx.controls.DataGrid
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class DataGridHeader extends DataGridHeaderBase
{

    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function DataGridHeader()
    {
        super();
        addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
        addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
    }

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

    /**
     *  a function to clear selections
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override mx_internal function clearSelectionLayer():void
    {
        while (selectionLayer.numChildren > 0)
        {
            selectionLayer.removeChildAt(0);
        }
    }

    /**
     *  The DataGrid control associated with this renderer.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var dataGrid:DataGrid;

    /**
     *  An Array of header renderer instances.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var headerItems:Array = [];

    /**
     *  The cached header height, in pixels.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var cachedHeaderHeight:Number = 0;

    /**
     *  The cached padding for the bottom of the renderer, in pixels.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected var cachedPaddingBottom:Number = 0;

	/**
	 *  The cached padding for the top of the renderer, in pixels.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	protected var cachedPaddingTop:Number = 0;
	
	/**
	 *  Whether we need the separator on the far right
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public var needRightSeparator:Boolean = false;
	
	/**
	 *  Whether we need the separator events on the far right
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public var needRightSeparatorEvents:Boolean = false;

    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override protected function createChildren():void
    {
        dataGrid = parent as DataGrid;

        // this is the layer where we draw selection indicators
        selectionLayer = new UIComponent();
        addChild(selectionLayer);
    }

    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override protected function measure():void
    {
        super.measure();
        var calculatedHeight:Number = dataGrid.calculateHeaderHeight();
        cachedHeaderHeight = dataGrid._explicitHeaderHeight ? dataGrid.headerHeight : calculatedHeight;
        cachedPaddingBottom = getStyle("paddingBottom");
        cachedPaddingTop = getStyle("paddingTop");
        measuredHeight = cachedHeaderHeight;

        var ww:Number = 0;
        var n:int = visibleColumns ? visibleColumns.length : 0;
        for (var i:int = 0; i < n; i++)
            ww += visibleColumns[i].preferredWidth;
        measuredWidth = ww;
    }

    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override protected function updateDisplayList(w:Number, h:Number):void
    {
        allowItemSizeChangeNotification = false;

        // make new ones
        var cols:Array = visibleColumns;

        if (headerItemsChanged && (cols && cols.length > 0 || dataGrid.headerVisible))
        {
            headerItemsChanged = false;

            var xx:Number = 0;
            var yy:Number = 0;
            var hh:Number = 0;
            var ww:Number = 0;
            var rh:Number;
            var colNum:int = 0; // visible columns compensate for firstCol offset

            var rowData:DataGridListData;
            var item:IListItemRenderer;
            var extraItem:IListItemRenderer;
            var data:Object;
            var uid:String;
            var c:DataGridColumn;

            var maxHeaderHeight:Number = 0;
            // copy current list of renderers
            var oldHeaderItems:Array = headerItems.slice();

            while (cols && colNum < cols.length)
            {
                c = cols[colNum];
                item = c.cachedHeaderRenderer;
                if (!item)
                {
                    item = dataGrid.createColumnItemRenderer(c, true, c);
                    item.styleName = c;
                    c.cachedHeaderRenderer = item;
                }
                rowData = new DataGridListData((c.headerText != null) ? c.headerText : c.dataField, 
                                                                c.dataField, colNum, uid, dataGrid, 0);
                if (item is IDropInListItemRenderer)
                    IDropInListItemRenderer(item).listData = rowData;
                item.data = c;
                item.visible = true;
                // if it isn't parented by us, add it (could be in lockedColumns header)
                if (item.parent != this)
                    addChild(DisplayObject(item));
                headerItems[colNum] = item;
                // set prefW so we can compute prefH
                item.explicitWidth = ww = c.width;
                UIComponentGlobals.layoutManager.validateClient(item, true);
                // but size it regardless of what prefW is
                rh = item.getExplicitOrMeasuredHeight();
                item.setActualSize(ww, dataGrid._explicitHeaderHeight ?
                    cachedHeaderHeight - cachedPaddingTop - cachedPaddingBottom : rh);
                item.move(xx, yy + cachedPaddingTop);
                xx += ww;
                colNum++;
                hh = Math.ceil(Math.max(hh, dataGrid._explicitHeaderHeight ?
                    cachedHeaderHeight : rh + cachedPaddingBottom + cachedPaddingTop));
                maxHeaderHeight = Math.max(maxHeaderHeight, dataGrid._explicitHeaderHeight ?
                    cachedHeaderHeight - cachedPaddingTop - cachedPaddingBottom : rh);
            }

            // expand all headers to be of maximum height
            for (var i:int = 0; i < headerItems.length; i++)
                headerItems[i].setActualSize(headerItems[i].width, maxHeaderHeight);
            
            for (i = 0; i < oldHeaderItems.length; i++)
            {
                item = oldHeaderItems[i];
                if (item && headerItems.indexOf(item) == -1)
                {
                    // if it is parented by us, remove it (could be in lockedColumns header)
                    if (item.parent == this)
                        removeChild(DisplayObject(item));
                }
            }
            while (headerItems.length > colNum)
            {
                // remove extra columns
                extraItem = headerItems.pop();
                // if it is parented by us, remove it (could be in lockedColumns header)
                if (extraItem.parent == this)
                {
                    // make sure it isn't already in there elsewhere
                    if (headerItems.indexOf(extraItem) == -1)
                        removeChild(DisplayObject(extraItem));
                }
            }
        }
        var headerBG:UIComponent =
            UIComponent(getChildByName("headerBG"));
        
        if (headerBGSkinChanged)
        {
            headerBGSkinChanged = false;
            if (headerBG)
                removeChild(headerBG);
            headerBG = null;
        }

        if (!headerBG)
        {
            headerBG = new UIComponent();
            headerBG.name = "headerBG";
            addChildAt(DisplayObject(headerBG), 0);
                        
            var headerBGSkinClass:Class = getStyle("headerBackgroundSkin");
            var headerBGSkin:IFlexDisplayObject = new headerBGSkinClass();
       
            if (headerBGSkin is ISimpleStyleClient)
                ISimpleStyleClient(headerBGSkin).styleName = this;
            headerBG.addChild(DisplayObject(headerBGSkin));
        }
        if (dataGrid.headerVisible)
        {
            headerBG.visible = true;
            drawHeaderBackgroundSkin(IFlexDisplayObject(headerBG.getChildAt(0)));
            dataGrid._drawSeparators();
        }
        else
        {
            headerBG.visible = false;
            dataGrid._clearSeparators();
        }

        dataGrid._placeSortArrow();

        allowItemSizeChangeNotification = true;
    }

    mx_internal function _drawHeaderBackground(headerBG:UIComponent):void
    {
        drawHeaderBackground(headerBG);
    }

    /**
     *  Draws the background of the headers into the given 
     *  UIComponent. The graphics drawn may 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 = width;

        var hh:Number = cachedHeaderHeight;

        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
    {
        headerBGSkin.setActualSize(unscaledWidth, Math.ceil(cachedHeaderHeight));  
    }

    mx_internal function _clearSeparators():void
    {
        clearSeparators();
    }

    /**
     *  Removes column header separators that the user normally uses
     *  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(getChildByName("lines"));
        while (lines.numChildren)
        {
            lines.removeChildAt(lines.numChildren - 1);
            separators.pop();
        }
    }

    mx_internal function _drawSeparators():void
    {
        drawSeparators();
    }

    /**
     *  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 and 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
    {
        if (!separators)
            separators = [];

        var lines:UIComponent = UIComponent(getChildByName("lines"));
        
        if (!lines)
        {
            lines = new UIComponent();
            lines.name = "lines";
            addChild(lines); 
        }
        else
            setChildIndex(lines, numChildren - 1);

        // required to deal with some 2.x clipping behavior
        lines.scrollRect = new Rectangle(0, 0, unscaledWidth, unscaledHeight + 1);

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

        var n:int = visibleColumns ? visibleColumns.length : 0;
        
        if (!needRightSeparator && n > 0)
        	n--;
        
        for (var i:int = 0; i < n; i++)
        {
            var sep:UIComponent;
            var sepSkin:IFlexDisplayObject;
            
            if (i < lines.numChildren)
            {
                sep = UIComponent(lines.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));
                lines.addChild(sep);
                UIComponentGlobals.layoutManager.validateClient(sep, true);
                
                separators.push(sep);
            }
            // if not separator
            if ( !(i == visibleColumns.length-1 && !needRightSeparatorEvents) )
            {
	            DisplayObject(sep).addEventListener(
	                MouseEvent.MOUSE_OVER, columnResizeMouseOverHandler);
	            DisplayObject(sep).addEventListener(
	                MouseEvent.MOUSE_OUT, columnResizeMouseOutHandler);
	            DisplayObject(sep).addEventListener(
	                MouseEvent.MOUSE_DOWN, columnResizeMouseDownHandler);
	        }
			else
			{
                // if not separator
                if ( (i == visibleColumns.length-1 && !needRightSeparatorEvents) )
                {
	                DisplayObject(sep).removeEventListener(
	                    MouseEvent.MOUSE_OVER, columnResizeMouseOverHandler);
	                DisplayObject(sep).removeEventListener(
	                    MouseEvent.MOUSE_OUT, columnResizeMouseOutHandler);
	                DisplayObject(sep).removeEventListener(
	                    MouseEvent.MOUSE_DOWN, columnResizeMouseDownHandler);
	            }
			}

            var cols:Array = visibleColumns;
            if (!(cols && cols.length > 0 || dataGrid.headerVisible))
            {
                sep.visible = false;
                continue;
            }

            // Spark skins don't measure if the width is specified.
            var skinWidth:Number;
            if (sepSkin is IUIComponent)
                skinWidth = IUIComponent(sepSkin).getExplicitOrMeasuredWidth();
            else
                skinWidth = sepSkin.measuredWidth;
            
            sep.visible = true;
            sep.x = headerItems[i].x +
                    visibleColumns[i].width - Math.round(skinWidth / 2);
            if (i > 0)
            {
                sep.x = Math.max(sep.x,
                                 separators[i - 1].x + Math.round(skinWidth / 2));
            }
            sep.y = 0;
            sepSkin.setActualSize(skinWidth, Math.ceil(cachedHeaderHeight));

                        // Draw invisible background for separator affordance
            sep.graphics.clear();
            sep.graphics.beginFill(0xFFFFFF, 0);
            sep.graphics.drawRect(-separatorAffordance, 0,
								  sepSkin.measuredWidth + separatorAffordance,
								  cachedHeaderHeight);
            sep.graphics.endFill();
			sep.mouseEnabled = true;
        }

        while (lines.numChildren > n)
        {
            lines.removeChildAt(lines.numChildren - 1);
            separators.pop();
        }
        UIComponentGlobals.layoutManager.validateClient(lines, true);
    }
    
     /**
     *  Draws the highlight indicator into the given Sprite
     *  at the position, width and height specified using the
     *  color specified.
     * 
     *  @param indicator A Sprite that should contain the graphics
     *  that make a renderer look highlighted.
     *
     *  @param x The suggested x position for the indicator.
     *
     *  @param y The suggested y position for the indicator.
     *
     *  @param width The suggested width for the indicator.
     *
     *  @param height The suggested height for the indicator.
     *
     *  @param color The suggested color for the indicator.
     *
     *  @param itemRenderer The item renderer that is being highlighted.
     *
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawHeaderIndicator(indicator:Sprite, x:Number, y:Number, width:Number, height:Number, color:uint, itemRenderer:IListItemRenderer):void
    {
        var g:Graphics = indicator.graphics;
        g.clear();
        g.beginFill(color);
        g.drawRect(0, 0, width, height);
        g.endFill(); 
        indicator.x = x;
        indicator.y = y;
    }
    
     /**
     *  Draws the selection indicator into the given Sprite
     *  at the position, width and height specified using the
     *  color specified.
     * 
     *  @param indicator A Sprite that should contain the graphics
     *  that make a renderer look selected.
     *
     *  @param x The suggested x position for the indicator.
     *
     *  @param y The suggested y position for the indicator.
     *
     *  @param width The suggested width for the indicator.
     *
     *  @param height The suggested height for the indicator.
     *
     *  @param color The suggested color for the indicator.
     *
     *  @param itemRenderer The item renderer that is being selected.
     *
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawSelectionIndicator(indicator:Sprite, x:Number, y:Number, width:Number, height:Number, color:uint, itemRenderer:IListItemRenderer):void
    {
        var g:Graphics = indicator.graphics;
        g.clear();
        g.beginFill(color);
        g.drawRect(0, 0, width, height);
        g.endFill(); 
        indicator.x = x;
        indicator.y = y;
    }
    
     /**
     *  Draws the overlay on the dragged column into the given Sprite
     *  at the position, width and height specified using the
     *  color specified.
     * 
     *  @param indicator A Sprite that should contain the graphics
     *  that indicate that a column is being dragged.
     *
     *  @param x The suggested x position for the indicator.
     *
     *  @param y The suggested y position for the indicator.
     *
     *  @param width The suggested width for the indicator.
     *
     *  @param height The suggested height for the indicator.
     *
     *  @param color The suggested color for the indicator.
     *
     *  @param itemRenderer The item renderer that is being dragged.
     *
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawColumnDragOverlay(indicator:Sprite, x:Number, y:Number, width:Number, height:Number, color:uint, itemRenderer:IListItemRenderer):void
    {
        var g:Graphics = indicator.graphics;
        g.clear();
        g.beginFill(color);
        g.drawRect(0, 0, width, height);
        g.endFill(); 
        indicator.x = x;
        indicator.y = y;
    }   

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------
    /**
     *  @private
     */
    private function columnResizeMouseOverHandler(event:MouseEvent):void
    {
        if (!enabled || !dataGrid.resizableColumns)
            return;

        var target:DisplayObject = DisplayObject(event.target);
        var index:int = target.parent.getChildIndex(target);
        if (!visibleColumns[index].resizable)
            return;

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

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

        var target:DisplayObject = DisplayObject(event.target);
        var index:int = target.parent.getChildIndex(target);
        if (!visibleColumns[index].resizable)
            return;

        cursorManager.removeCursor(resizeCursorID);
    }

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

        var target:DisplayObject = DisplayObject(event.target);
        var index:int = target.parent.getChildIndex(target);
        if (!visibleColumns[index].resizable)
            return;

        startX = DisplayObject(event.target).x + x;
        lastPt = new Point(event.stageX, event.stageY);
        lastPt = dataGrid.globalToLocal(lastPt);
        var n:int = separators.length;
		var colIndex:int = 0;
        for (var i:int = 0; i < n; i++)
        {
            if (separators[i] == event.target)
            {
                resizingColumn = visibleColumns[i];
				colIndex = i;
            }
			else
				separators[i].mouseEnabled = false;
        }
        if (!resizingColumn)
            return;

        minX = headerItems[colIndex].x + x + resizingColumn.minWidth;

        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();
		if (resizeGraphic is Sprite)
			Sprite(resizeGraphic).mouseEnabled = false;

        dataGrid.addChild(DisplayObject(resizeGraphic));
        resizeGraphic.move(DisplayObject(event.target).x + x, 0);
        resizeGraphic.setActualSize(resizeGraphic.measuredWidth,
                                    dataGrid.height / dataGrid.scaleY);
    }

    /**
     *  @private
     */
    private function columnResizingHandler(event:MouseEvent):void
    {
        if (!MouseEvent(event).buttonDown)
        {
            columnResizeMouseUpHandler(event);
            return;
        }
        
        var vsw:int = dataGrid.vScrollBar ? dataGrid.vScrollBar.width : 0;

        var pt:Point = new Point(event.stageX, event.stageY);
        pt = dataGrid.globalToLocal(pt);
        lastPt = pt;
        resizeGraphic.move(Math.min(Math.max(minX, pt.x),
                           (dataGrid.width / dataGrid.scaleX) - separators[0].width - vsw), 0);
    }

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

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

        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);

        dataGrid.removeChild(DisplayObject(resizeGraphic));
        resizeGraphic = null;

        cursorManager.removeCursor(resizeCursorID);

        var c:DataGridColumn = resizingColumn;
        resizingColumn = null;

        var vsw:int = dataGrid.vScrollBar ? dataGrid.vScrollBar.width : 0;

        var mouseEvent:MouseEvent = event as MouseEvent;
        var pt:Point;
        
        if (mouseEvent)
        {
            pt = new Point(mouseEvent.stageX, mouseEvent.stageY);
            pt = dataGrid.globalToLocal(pt);
        }
        else
            pt = lastPt;
            
        // resize the column
        var widthChange:Number = Math.min(Math.max(minX, pt.x),
            (dataGrid.width / dataGrid.scaleX) - separators[0].width - vsw) - startX;
        dataGrid.resizeColumn(c.colNum, Math.floor(c.width + widthChange));

        invalidateDisplayList();    // force redraw of columns

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

    /**
     *  @private
     */
    private function columnDraggingMouseMoveHandler(event:MouseEvent):void
    {
        if (!event.buttonDown)
        {
            columnDraggingMouseUpHandler(event);
            return;
        }

        var item:IListItemRenderer;
        var c:DataGridColumn = dataGrid.movingColumn;
        var s:Sprite;
        var i:int = 0;
        var n:int = headerItems.length;
        var dgSelectionLayer:Sprite;

        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;

            var vm:EdgeMetrics = dataGrid.viewMetrics;

            // Create, position and draw selection layer over both headers.
            dgSelectionLayer = new UIComponent();
            dgSelectionLayer.name = "columnDragSelectionLayer";
            dgSelectionLayer.alpha = 0.6;
            dataGrid.addChild(dgSelectionLayer);
            dgSelectionLayer.x = vm.left;
            dgSelectionLayer.y = vm.top;

            // Create and position proxy.
            var proxy:IListItemRenderer = dataGrid.createColumnItemRenderer(c, true, c);
            proxy.name = "headerDragProxy";

            var rowData:DataGridListData = new DataGridListData((c.headerText != null) ? c.headerText : c.dataField, 
                                                                c.dataField, c.colNum, uid, dataGrid, 0);
            if (proxy is IDropInListItemRenderer)
                IDropInListItemRenderer(proxy).listData = rowData;

            dgSelectionLayer.addChild(DisplayObject(proxy));

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

            for (i = 0; i < n; i++)
            {
                item = headerItems[i];
                if (item.data == dataGrid.movingColumn)
                    break;
            }
            proxy.move(item.x + x, item.y);

            // Create, position and draw column overlay.
            s = new FlexSprite();
            s.name = "columnDragOverlay";
            s.alpha = 0.6;
            dataGrid.addChild(s);

            if (c.width > 0)
            {
                drawColumnDragOverlay(s, item.x + x, 0, c.width, 
                                        dataGrid.height / dataGrid.scaleY - vm.bottom - s.y, 
                                        getStyle("disabledColor"), item);
            }

            s = Sprite(selectionLayer.getChildByName("headerSelection"));
            if (s)
            {
                s.width = dataGrid.movingColumn.width;
                dgSelectionLayer.addChild(s);
                s.x += x;
            }


            // Clip the contents so the header drag proxy doesn't show
            // outside the list.
            dgSelectionLayer.scrollRect = new Rectangle(0, 0,
                    dataGrid.width / dataGrid.scaleX,
                    unscaledHeight);

            return;
        }

        // Global coordinates.
        var deltaX:Number = event.stageX - startX;
        dgSelectionLayer = Sprite(dataGrid.getChildByName("columnDragSelectionLayer"));

        // 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(dgSelectionLayer.getChildByName("headerSelection"));
        if (s)
            s.x += deltaXInLocalCoordinates;
        
         // Move header proxy.
        item = IListItemRenderer(dgSelectionLayer.getChildByName("headerDragProxy"));
        if (item)
            item.move(item.x + deltaXInLocalCoordinates, item.y);
        
        // Global coordinates.
        startX += deltaX;
        
        var allVisibleColumns:Array = dataGrid.getAllVisibleColumns();
        var pt:Point = new Point(event.stageX, event.stageY);
        pt = dataGrid.globalToLocal(pt);
        lastPt = pt;
        n = allVisibleColumns.length;
        var xx:Number = dataGrid.viewMetrics.left;
        var ww:Number;
        for (i = 0; i < n; i++)
        {
            ww = allVisibleColumns[i].width;

            if (pt.x < xx + ww)
            {
                // 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 > xx + ww / 2)
                {
                    i++;
                    xx += ww;
                }

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

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

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

                        dataGrid.addChild(
                            DisplayObject(columnDropIndicator));
                        var m:Shape = new Shape();
                        m.graphics.beginFill(0xffffff);
                        m.graphics.drawRect(0, 0, 10, 10);
                        m.graphics.endFill();
                        dataGrid.addChild(m);
                        columnDropIndicator.mask = m;
                    }

                    dataGrid.setChildIndex(
                        DisplayObject(columnDropIndicator),
                        dataGrid.numChildren - 1);
                    columnDropIndicator.visible = true;
                    m = columnDropIndicator.mask as Shape;
                    m.x = dataGrid.viewMetrics.left;
                    m.y = dataGrid.viewMetrics.top;
                    m.width = dataGrid.width / dataGrid.scaleX - m.x - dataGrid.viewMetrics.right;
                    m.height = dataGrid.height / dataGrid.scaleY - m.x - dataGrid.viewMetrics.bottom;

                    columnDropIndicator.setActualSize(3, dataGrid.height / dataGrid.scaleY);
                    columnDropIndicator.x = xx - columnDropIndicator.width + (layoutDirection == LayoutDirection.LTR ? 0 : 1);
                    columnDropIndicator.y = 0;  
                }
                break;
            }
            xx += ww;
        }
    }

    /**
     *  @private
     * 
     *  @param event MouseEvent or SandboxMouseEvent.
     */
    private function columnDraggingMouseUpHandler(event:Event):void
    {
        if (!dataGrid.movingColumn)
            return;

        var origIndex:int = dataGrid.movingColumn.colNum;
        var allVisibleColumns:Array = dataGrid.getAllVisibleColumns();

        if (dropColumnIndex >= 0)
        {
            if (dropColumnIndex >= allVisibleColumns.length)
            {
                dropColumnIndex = allVisibleColumns.length - 1;
            }
            else
            {
                if (origIndex < allVisibleColumns[dropColumnIndex].colNum)
                    dropColumnIndex--;
            }
     
            // dropColumnIndex is actually the index into the headerItems
            // array.  Get the corresponding index into the _columns array.
            dropColumnIndex = allVisibleColumns[dropColumnIndex].colNum;
        }

        // Shift columns.
        dataGrid.shiftColumns(origIndex, dropColumnIndex, event as MouseEvent);

        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 dgSelectionLayer:Sprite = Sprite(dataGrid.getChildByName("columnDragSelectionLayer"));
        if (!dgSelectionLayer)
        {
            startX = NaN;
            dataGrid.movingColumn = null;
            dropColumnIndex = -1;
            return;
        }

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

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

        if (columnDropIndicator)
            columnDropIndicator.visible = false;

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

        dataGrid.removeChild(dgSelectionLayer);

        startX = NaN;
        dataGrid.movingColumn = null;
        dropColumnIndex = -1;

        invalidateDisplayList(); // force redraw
    }

    /**
     *  @private
     */
    protected function mouseOverHandler(event:MouseEvent):void
    {
        var r:IListItemRenderer;
        var i:int;

        if (resizingColumn || dataGrid.movingColumn)
            return;

        if (dataGrid.enabled && dataGrid.sortableColumns && dataGrid.headerVisible)
        {
            // find out if we hit the sort arrow
            s = Sprite(getChildByName("sortArrowHitArea"));

            if (event.target == s)
            {
                var n:int = visibleColumns.length;
                for (i = 0; i < n; i++)
                {
                    if (visibleColumns[i].colNum == dataGrid.sortIndex)
                    {
                        r = headerItems[i];
                        break;
                    }
                }
            }
            else
            {
                for (i = 0; i < separators.length; i++)
                {
                    if (event.target == separators[i] && visibleColumns[i].resizable)
                        return;
                }
                var pt:Point = new Point(event.stageX, event.stageY);
                pt = globalToLocal(pt);
                for (i = 0; i < headerItems.length; i++)
                {
                    if (headerItems[i].x + headerItems[i].width >= pt.x)
                    {
                        r = headerItems[i];
                        break;
                    }
                }
                if (i >= headerItems.length)
                    return;
            }

            s = Sprite(getChildByName("sortArrowHitArea"));
            if (visibleColumns[i].sortable)
            {
                var s:Sprite = Sprite(
                    selectionLayer.getChildByName("headerSelection"));
                if (!s)
                {
                    s = new FlexSprite();
                    s.name = "headerSelection";
                    s.mouseEnabled = false;
                    selectionLayer.addChild(s);
                }      

                drawHeaderIndicator(s, r.x, 0, visibleColumns[i].width, cachedHeaderHeight - 0.5, getStyle("rollOverColor"), r);
                
            }
        }

        if (event.buttonDown)
            lastItemDown = r;
        else
            lastItemDown = null;
    }
    
    /**
     *  @private
     */
    protected function mouseOutHandler(event:MouseEvent):void
    {
        var r:IListItemRenderer;
        var i:int;

        if (resizeGraphic || dataGrid.movingColumn)
            return;

        if (dataGrid.enabled && dataGrid.sortableColumns && dataGrid.headerVisible)
        {
            // find out if we hit the sort arrow
            s = Sprite(getChildByName("sortArrowHitArea"));

            if (event.target == s)
            {
                var n:int = visibleColumns.length;
                for (i = 0; i < n; i++)
                {
                    if (visibleColumns[i].colNum == dataGrid.sortIndex)
                    {
                        r = headerItems[i];
                        break;
                    }
                }
                if (i >= visibleColumns.length)
                    return;
            }
            else
            {
                for (i = 0; i < separators.length; i++)
                {
                    if (event.target == separators[i] && visibleColumns[i].resizable)
                        return;
                }
                var pt:Point = new Point(event.stageX, event.stageY);
                pt = globalToLocal(pt);
                for (i = 0; i < headerItems.length; i++)
                {
                    if (headerItems[i].x + headerItems[i].width >= pt.x)
                    {
                        r = headerItems[i];
                        break;
                    }
                }
                if (i >= headerItems.length)
                    i = headerItems.length - 1;
            }

            if (visibleColumns.length > 0 && visibleColumns[i].sortable)
            {
                var s:Sprite = Sprite(
                    selectionLayer.getChildByName("headerSelection"));
                if (s)
                    selectionLayer.removeChild(s);
            }
        }

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

    }

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

        systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true, 0, true);
        systemManager.getSandboxRoot().addEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, mouseLeaveHandler, false, 0, true);

        // find out if we hit the sort arrow
        s = Sprite(getChildByName("sortArrowHitArea"));

        if (event.target == s)
        {
            var n:int = visibleColumns.length;
            for (i = 0; i < n; i++)
            {
                if (visibleColumns[i].colNum == dataGrid.sortIndex)
                {
                    r = headerItems[i];
                    break;
                }
            }
        }
        else
        {
            for (i = 0; i < separators.length; i++)
            {
                if (event.target == separators[i] && visibleColumns[i].resizable)
                    return;
            }
            var pt:Point = new Point(event.stageX, event.stageY);
            pt = globalToLocal(pt);
            for (i = 0; i < headerItems.length; i++)
            {
                if (headerItems[i].x + headerItems[i].width >= pt.x)
                {
                    r = headerItems[i];
                    break;
                }
            }
            if (i >= headerItems.length)
                return;
        }

        // if headers are visible and clickable for sorting
        if (dataGrid.enabled && (dataGrid.sortableColumns || dataGrid.draggableColumns)
                && dataGrid.headerVisible)
        {

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

                drawSelectionIndicator(s, r.x, 0, visibleColumns[i].width, cachedHeaderHeight - 0.5, getStyle("selectionColor"), r);
            }

            // begin column dragging
            if (dataGrid.draggableColumns && visibleColumns[i].draggable)
            {
                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);
                dataGrid.movingColumn = visibleColumns[i];
            }
        }
    }

     /**
     *  @private
     */
    protected function mouseUpHandler(event:MouseEvent):void
    {
        var dataGridEvent:DataGridEvent;
        var r:IListItemRenderer;
        var s:Sprite;
        var n:int;
        var i:int;

        systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
        systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, mouseLeaveHandler);

        // find out if we hit the sort arrow
        s = Sprite(getChildByName("sortArrowHitArea"));

        if (event.target == s)
        {
            n = visibleColumns.length;
            for (i = 0; i < n; i++)
            {
                if (visibleColumns[i].colNum == dataGrid.sortIndex)
                {
                    r = headerItems[i];
                    break;
                }
            }
        }
        else
        {
            for (i = 0; i < separators.length; i++)
            {
                if (event.target == separators[i] && visibleColumns[i].resizable)
                    return;
            }
            var pt:Point = new Point(event.stageX, event.stageY);
            pt = globalToLocal(pt);
            for (i = 0; i < headerItems.length; i++)
            {
                if (headerItems[i].x + headerItems[i].width >= pt.x)
                {
                    r = headerItems[i];
                    break;
                }
            }
            if (i >= headerItems.length)
                return;
        }

        if (dataGrid.enabled && (dataGrid.sortableColumns || dataGrid.draggableColumns)
                && dataGrid.dataProvider && dataGrid.headerVisible)
        {
            if (r == lastItemDown)
            {
                if (dataGrid.sortableColumns && visibleColumns[i].sortable)
                {
                    lastItemDown = null;
                    dataGridEvent = new DataGridEvent(DataGridEvent.HEADER_RELEASE, false, true);
                    // HEADER_RELEASE event is cancelable
                    dataGridEvent.columnIndex = visibleColumns[i].colNum;
                    dataGridEvent.dataField = visibleColumns[i].dataField;
                    dataGridEvent.itemRenderer = r;
                    dataGrid.dispatchEvent(dataGridEvent);
                }
            }
        }
    }

    private function mouseLeaveHandler(event:Event):void
    {
        systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
        systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, mouseLeaveHandler);
    }

    mx_internal function _placeSortArrow():void
    {
        placeSortArrow();
    }

    /**
     *  Draws the sort arrow graphic on the column that is the current sort key.
     *  This implementation creates or reuses an instance of the skin specified
     *  by <code>sortArrowSkin</code> style property and places 
     *  it in the appropriate column header.  It
     *  also shrinks the size of the column header if the text in the header
     *  would be obscured by the sort arrow.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function placeSortArrow():void
    {

        var sortArrowHitArea:Sprite =
            Sprite(getChildByName("sortArrowHitArea"));

        if (dataGrid.sortIndex == -1 && dataGrid.lastSortIndex == -1)
        {
            if (sortArrow)
                sortArrow.visible = false;
            if (sortArrowHitArea)
                sortArrowHitArea.visible = false;
            return;
        }

        if (!dataGrid.headerVisible)
        {
            if (sortArrow)
                sortArrow.visible = false;
            if (sortArrowHitArea)
                sortArrowHitArea.visible = false;
            return;
        }

        if (!sortArrow)
        {
            var sortArrowClass:Class = getStyle("sortArrowSkin");
            sortArrow = new sortArrowClass();
            DisplayObject(sortArrow).name = enabled ? "sortArrow" : "sortArrowDisabled";
            if (sortArrow is ISimpleStyleClient)
                ISimpleStyleClient(sortArrow).styleName = this;
            
            addChild(DisplayObject(sortArrow));
        }
        var xx:Number;
        var n:int;
        var i:int;
        var found:Boolean = false;
        if (headerItems && headerItems.length)
        {
            n = headerItems.length;
            for (i = 0; i < n; i++)
            {
                if (visibleColumns[i].colNum == dataGrid.sortIndex)
                {
                    xx = headerItems[i].x + visibleColumns[i].width;
                    headerItems[i].setActualSize(visibleColumns[i].width - sortArrow.measuredWidth - 8, headerItems[i].height);

                    if (!isNaN(headerItems[i].explicitWidth))
                        headerItems[i].explicitWidth = headerItems[i].width;

                    UIComponentGlobals.layoutManager.validateClient(headerItems[i], true);

                    // Create hit area to capture mouse clicks behind arrow.
                    if (!sortArrowHitArea)
                    {
                        sortArrowHitArea = new FlexSprite();
                        sortArrowHitArea.name = "sortArrowHitArea";
                        addChild(sortArrowHitArea);
                    }
                    else
                        sortArrowHitArea.visible = true;

                    sortArrowHitArea.x = headerItems[i].x + headerItems[i].width;
                    sortArrowHitArea.y = headerItems[i].y;

                    var g:Graphics = sortArrowHitArea.graphics;
                    g.clear();
                    g.beginFill(0, 0);
                    g.drawRect(0, 0, sortArrow.measuredWidth + 8,
                            headerItems[i].height);
                    g.endFill();
                    found = true;
                    break;
                }
            }
        }
        if (isNaN(xx))
            sortArrow.visible = false;
        else
            sortArrow.visible = true;

        if (visibleColumns.length && dataGrid.lastSortIndex >= 0 && dataGrid.lastSortIndex != dataGrid.sortIndex)
            if (visibleColumns[0].colNum <= dataGrid.lastSortIndex && 
                dataGrid.lastSortIndex <= visibleColumns[visibleColumns.length - 1].colNum)
            {
                n = headerItems.length;
                for (var j:int = 0; j < n; j++)
                {
                    if (visibleColumns[j].colNum == dataGrid.lastSortIndex)
                    {
                        headerItems[j].setActualSize(visibleColumns[j].width, headerItems[j].height);
                        UIComponentGlobals.layoutManager.validateClient(headerItems[j], true);
                        break;
                    }
                }
            }

        var d:Boolean = (dataGrid.sortDirection == "ASC");
        sortArrow.width = sortArrow.measuredWidth;
        sortArrow.height = sortArrow.measuredHeight;
        DisplayObject(sortArrow).scaleY = (d) ? -1.0 : 1.0;
        sortArrow.x = xx - sortArrow.measuredWidth - 8;
        var hh:Number = cachedHeaderHeight;
        sortArrow.y = (hh - sortArrow.measuredHeight) / 2 + ((d) ? sortArrow.measuredHeight: 0);

        if (found && sortArrow.x < headerItems[i].x)
            sortArrow.visible = false;

        if (!sortArrow.visible && sortArrowHitArea)
            sortArrowHitArea.visible = false;

    }


    //--------------------------------------------------------------------------
    //
    //  Overridden methods: UIComponent
    //
    //--------------------------------------------------------------------------

   /**
     *  @private
     */
    override public function invalidateSize():void
    {
        if (allowItemSizeChangeNotification)
            super.invalidateSize();
    }


    /**
     *  @copy mx.core.IUIComponent#enabled
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override public function set enabled(value:Boolean):void
    {
        super.enabled = value;
        if (sortArrow)
        {
			removeChild(DisplayObject(sortArrow));
            sortArrow = null;
            placeSortArrow();
        }
            
    }
    
    
    /**
     *  @private
     */
    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged(styleProp);
        if (styleProp == "headerBackgroundSkin")
        {
            headerBGSkinChanged = true;
        }
        else if (styleProp == "headerSeparatorSkin")
        {
            headerSepSkinChanged = true;
        }
    }

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

    /**
     *  @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
     */
    mx_internal function getSeparators():Array
    {
        return separators;
    }

    /**
     *  @private
     *  The column that is being resized.
     */
    private function get resizingColumn():DataGridColumn
	{
		return dataGrid.resizingColumn;
	}
    /**
     *  @private
     *  The column that is being resized.
     */
    private function set resizingColumn(value:DataGridColumn):void
	{
		dataGrid.resizingColumn = value;
	}

    /**
     *  Specifies a graphic that shows the proposed column width as the user stretches it.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    private var resizeGraphic:IFlexDisplayObject; //

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

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

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

    /**
     *  The small arrow graphic used to show sortable columns and direction.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var sortArrow:IFlexDisplayObject;

    /** 
     *  diagnostics
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal function get rendererArray():Array 
    {
        return headerItems;
    }

    /**
     *  The offset, in pixels, from the left side of the content of the renderer.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var leftOffset:Number = 0;

    /**
     *  The offset, in pixels, from the top of the content of the renderer.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var topOffset:Number = 0;

    /**
     *  The offset, in pixels, from the right side of the content of the renderer.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var rightOffset:Number = 0;

    /**
     *  The offset, in pixels, from the bottom of the content of the renderer.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public var bottomOffset:Number = 0;

    /**
     *  @private
     */
    private var allowItemSizeChangeNotification:Boolean = true;

    private var headerBGSkinChanged:Boolean = false;

    private var headerSepSkinChanged:Boolean = false;
}

}
