Transferred from the Adobe Open Source Subversion Repository

Revision: 12850
Author:   jimurphy@adobe.com
Date:     2009-12-11T14:57:14.623098Z

Log Message:
-----------
add 6 new DMV projects to the SDK:
automation
automation_air
automation_dmv
automation_flashflexkit
automation_spark
datavisualization

These projects are setup to build in an ant main call.  There are currently several warnings in the datavisualization project that will be cleaned up.  No checkintests exist for these projects as of yet.

I also modified the exisitng projects build files for easier management of the localization targets, bundle and fat-swc. If the projects that I updated:airframework,airspark,framework,playerglobal,rpc,and spark.  All the new projects have been implemented this same way.

QE notes: DMV folks should run through their tests
Doc notes: probably
Bugs: nope
Reviewer:
Tests run: ran the following targets: compile,checkintests,other.locales and doc
Is noteworthy for integration: no

Modified Paths:
--------------
1404 paths were modified

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1252972 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/charts/src/mx/charts/chartClasses/ChartBase.as
+++ frameworks/projects/charts/src/mx/charts/chartClasses/ChartBase.as
@@ -0,0 +1,5544 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  ADOBE SYSTEMS INCORPORATED
+//  Copyright 2009 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.charts.chartClasses
+{
+
+import flash.display.DisplayObject;
+import flash.display.DisplayObjectContainer;
+import flash.display.Graphics;
+import flash.display.Shape;
+import flash.events.Event;
+import flash.events.IEventDispatcher;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.utils.*;
+
+import mx.charts.ChartItem;
+import mx.charts.HitData;
+import mx.charts.events.ChartEvent;
+import mx.charts.events.ChartItemEvent;
+import mx.charts.styles.HaloDefaults;
+import mx.collections.ArrayCollection;
+import mx.collections.ICollectionView;
+import mx.collections.IList;
+import mx.collections.ListCollectionView;
+import mx.collections.XMLListCollection;
+import mx.core.DragSource;
+import mx.core.EventPriority;
+import mx.core.FlexShape;
+import mx.core.IDataRenderer;
+import mx.core.IFlexDisplayObject;
+import mx.core.IUIComponent;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.effects.Parallel;
+import mx.effects.effectClasses.ParallelInstance;
+import mx.events.DragEvent;
+import mx.events.EffectEvent;
+import mx.graphics.IFill;
+import mx.graphics.IStroke;
+import mx.graphics.SolidColor;
+import mx.graphics.Stroke;
+import mx.managers.DragManager;
+import mx.managers.IFocusManagerComponent;
+import mx.managers.ILayoutManagerClient;
+import mx.styles.CSSStyleDeclaration;
+import mx.core.IFlexModuleFactory;
+
+use namespace mx_internal;
+
+//--------------------------------------
+//  Events
+//--------------------------------------
+
+/**
+ *  Dispatched when the selection changes in the chart.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.CHANGE
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="change", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  Dispatched when no data point is found under the mouse pointer
+ *  when mouse is clicked on chart.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartEvent.CHART_CLICK
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="chartClick", type="mx.charts.events.ChartEvent")]
+
+/**
+ *  Dispatched when no data point is found under the mouse pointer
+ *  when mouse is double-clicked on chart.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartEvent.CHART_DOUBLE_CLICK
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="chartDoubleClick", type="mx.charts.events.ChartEvent")]
+
+/**
+ *  Dispatched when a data point is found under the mouse pointer
+ *  when it is clicked.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.MOUSE_CLICK_DATA
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="itemClick", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  Dispatched when a data point is found under the mouse pointer
+ *  when it is double clicked.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.ITEM_DOUBLE_CLICK
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="itemDoubleClick", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  Dispatched when a data point is found under the mouse pointer
+ *  when it is pressed down.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.ITEM_MOUSE_DOWN
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="itemMouseDown", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  Dispatched when the mouse pointer moves while over a data point.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.ITEM_MOUSE_MOVE
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="itemMouseMove", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  Dispatched when a data point is found under the mouse pointer
+ *  when it is released.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.ITEM_MOUSE_UP
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="itemMouseUp", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  Dispatched when the closest data point under the mouse pointer changes.
+ *  Flex considers only data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.ITEM_ROLL_OUT
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="itemRollOut", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  Dispatched when a new data point is found under the mouse pointer.
+ *  Flex only considers data points within the radius determined by
+ *  the mouseSensitivity property.
+ *
+ *  @eventType mx.charts.events.ChartItemEvent.ITEM_ROLL_OVER
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Event(name="itemRollOver", type="mx.charts.events.ChartItemEvent")]
+
+/**
+ *  @private
+ *  Hidden from metadata, since it's not to exposed to end users
+ */
+/*
+[Event(name="legendDataChanged", type="flash.events.Event")]
+*/
+
+//--------------------------------------
+//  Styles
+//--------------------------------------
+
+include "../../styles/metadata/PaddingStyles.as"
+include "../styles/metadata/TextStyles.as"
+
+/**
+ *  Contains a list of Strings, each corresponding to a CSS type selector
+ *  to be used as the default CSS style for a series.
+ *  Each series in the chart draws a CSS type selector from the list
+ *  contained in the chartSeriesStyles style.
+ *  The first series uses the first selector, the second uses
+ *  the second, and so on.
+ *  Style properties in this type selector can be overridden
+ *  by specifying a styleName property for the series.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="chartSeriesStyles", type="Array", arrayType="String", inherit="no")]
+
+/**
+ *  The Stroke to use to render the callout line
+ *  from the data tip target to the tip.
+ *  If set to null, no Stroke is drawn
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="dataTipCalloutStroke", type="mx.graphics.IStroke", inherit="no")]
+
+/**
+ *  Specifies the class to use to render data tips.
+ *  This class must implement the IFlexDisplayObject
+ *  and IDataRenderer interfaces.
+ *  The chart assigns the custom data tip's data property
+ *  to be the HitData structure describing the data point being described.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="dataTipRenderer", type="Class", inherit="no")]
+
+/**
+ *  Specifies the fill style used for the chart background.
+ *  The fill can be either a simple color value
+ *  or an object that implements the mx.graphics.IFill interface.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="fill", type="mx.graphics.IFill", inherit="no")]
+
+/**
+ *  Color of disabled chartitem in the chart.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="itemDisabledColor", type="uint", format="Color", inherit="yes")]
+
+/**
+ *  Color of rolledOver chartitem in the chart.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="itemRollOverColor", type="uint", format="Color", inherit="yes")]
+
+/**
+ *  Color of selected chartitem in the chart.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="itemSelectionColor", type="uint", format="Color", inherit="yes")]
+
+/**
+ *  Specifies the maximum number of datatips a chart will show.
+ *  If more datapoints are in range of the chart than allowed by this style,
+ *  they will be prioritized by distance,
+ *  with the closest showing first.
+ *
+ *
The default value is NaN, which shows whatever datatips are within range.

+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="maximumDataTipCount", type="int", inherit="no")]
+
+/**
+ *  Specifies the number of pixels between the chart's bottom border
+ *  and its content area.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="paddingBottom", type="Number", format="Length", inherit="no")]
+
+/**
+ *  Specifies the number of pixels between the chart's top border
+ *  and its content area.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="paddingTop", type="Number", format="Length", inherit="no")]
+
+/**
+ *  Specifies whether to show targets over the datapoints
+ *  when showDataTips is set to true.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+[Style(name="showDataTipTargets", type="Boolean", inherit="no")]
+
+//--------------------------------------
+//  Other metadata
+//--------------------------------------
+
+[DefaultProperty("dataProvider")]
+
+/**
+ *  The ChartBase class is the link between the Flex component
+ *  architecture and the DualStyleObject architecture.
+ *  It extends the Flex UIComponent base class,
+ *  but contains DualStyleObject classes.
+ *
+ *
You typically do not use the ChartBase class directly.
+ *  Instead you use one of its subclasses, such as PlotChart or BubbleChart.
+ *  It acts as the base class for the common chart types
+ *  provided in the mx.charts package.

+ *
+ *
This class defines a number of CSS styles and properties
+ *  that provide easy access to the more common features of the framework.

+ *
+ *
A chart's minimum size is 20 x 20 pixels.
+ *  A chart's maximum size is unbounded.
+ *  A chart's preferred size is 400 x 400 pixels.

+ *
+ *
ChartBase objects, and its subclasses, augment the normal
+ *  mouse event objects with additional data that describes
+ *  the nearest chart data point under the mouse.
+ *  The event object for mouse events contains an additional property,
+ *  hitData, which contains a HitData object
+ *  that describes the nearest data point.
+ *  See mx.charts.HitData for more information on the contents
+ *  of the HitData object.

+ *
+ *
ChartBase objects consider data points only within a certain radius
+ *  of the mouse pointer.
+ *  You can set this radius using the mouseSensitivity
+ *  property.
+ *  If there is no data point within the mouseSensitivity
+ *  radius, event.hitData is null.

+ *
+ *  @mxml
+ *
+ *
Flex components inherit the following properties
+ *  from the ChartBase class:

+ *
+ *

+ *  <mx:tagname
+ *    Properties
+ *    allElements="Array; No default"
+ *    annotationElements="Array; No default"
+ *    backgroundElements="Array; No default"
+ *    chartState=""
+ *    clipContent="false|true"
+ *    dataProvider="No default"
+ *    dataRegion"No default"
+ *    dataTipFunction="No default"
+ *    dataTipLayerIndex"No default"
+ *    dataTipMode"No default"
+ *    description"No default"
+ *    dragEnabled="false|true"
+ *    dragMoveEnabled="false|true"
+ *    dropEnabled="false|true"
+ *    labelElements"No default"
+ *    legendData"No default"
+ *    mouseSensitivity="5"
+ *    selectedChartItem=ChartItem; No default"
+ *    selectedChartItems=Array; No default"
+ *    selectionMode="none|single|multiple"
+ *    series="No default"
+ *    seriesFilters"No default"
+ *    showAllDataTips="true|false"
+ *    showDataTips="true|false"
+ *    transforms="No default"
+ *
+ *    Styles
+ *    chartSeriesStyles="Style; No default"
+ *    dataTipCalloutStroke="Stroke; No default"
+ *    dataTipRenderer="Renderer; No default"
+ *    fill="IFill; No default"
+ *    fontFamily="Verdana"
+ *    fontSize="10"
+ *    itemDisabledColor="uint; No default"
+ *    itemRollOverColor="uint; No default"
+ *    itemSelectionColor="uint; No default"
+ *    maximumDataTipCount="NaN"
+ *    paddingBottom="No default"
+ *    paddingTop="No default"
+ *    paddingLeft="0"
+ *    paddingRight="0"
+ *    showDataTipTargets="true|false"
+ *
+ *   Events
+ *    change="Event; No default"
+ *    itemClick="Event; No default"
+ *    itemDoubleClick="Event; No default"
+ *    itemMouseDown="Event; No default"
+ *    itemMouseMove="Event; No default"
+ *    itemMouseUp="Event; No default"
+ *    itemRollOut="Event; No default"
+ *    itemRollOver="Event; No default"
+ *  >
+ *

+ *
+ *  @see mx.charts.HitData
+ *  @see mx.charts.CategoryAxis
+ *  @see mx.charts.LinearAxis
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class ChartBase extends UIComponent implements IFocusManagerComponent
+{
+    include "../../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class Initialization
+    //
+    //--------------------------------------------------------------------------
+
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private static const TOOLTIP_TARGET_INNER_RADIUS:Number = 1.5;
+
+    /**
+     *  @private
+     */
+    private static const TOOLTIP_TARGET_RADIUS:Number = 4.5;
+
+    /**
+     *  The value of this constant is passed to methods such as getNextItem() and getPrevItem().
+     *  These methods use this constant to determine which item or series to select when the user
+     *  presses a key such as the left arrow.
+     *
+     *  For example, if the left arrow or right arrow key was pressed, the direction is set to "horizontal"
+     *  (ChartBase.HORIZONTAL).
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static const HORIZONTAL:String = "horizontal";
+
+    /**
+     *  The value of this constant is passed to methods such as getNextItem() and getPrevItem().
+     *  These methods use this constant to determine which item or series to select when the user
+     *  presses a key such as the left arrow.
+     *
+     *  For example, if the up arrow or down arrow key was pressed, the direction is set to "vertical"
+     *  (ChartBase.VERTICAL).
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public static const VERTICAL:String = "vertical";
+
+    /**
+     *  @private
+     *  Mouse movement threshold for determining when to start a drag.
+     */
+    mx_internal static const DRAG_THRESHOLD:int = 4;
+
+
+    /**
+     *  @private
+     */
+    private static var ITEM_EVENTS:Object =
+    {
+        chartClick: true,
+        chartDoubleClick: true,
+        itemClick: true,
+        itemDoubleClick: true,
+        itemMouseDown: true,
+        itemMouseUp: true,
+        itemMouseMove: true,
+        itemRollOver: true,
+        itemRollOut: true
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function ChartBase()
+    {
+        super();
+		this.addEventListener(DragEvent.DRAG_START, dragStartHandler);
+
+        tabEnabled = false;
+
+        _seriesHolder = new UIComponent();
+        _seriesFilterer = new UIComponent();
+        _seriesHolder.addChild(_seriesFilterer);
+        addChild(_seriesHolder);
+
+        _backgroundElementHolder = new UIComponent();
+        addChild(_backgroundElementHolder);
+
+        _annotationElementHolder = new UIComponent();
+        addChild(_annotationElementHolder);
+
+        _dataTipOverlay = new FlexShape();
+        _dataTipOverlay.name = "dataTipOverlay";
+        addChild(_dataTipOverlay);
+
+        _allDataTipOverlay = new FlexShape();
+        _allDataTipOverlay.name = "allDataTipOverlay";
+        addChild(_allDataTipOverlay);
+
+        var g:Graphics;
+
+        _seriesMask = new FlexShape();
+        _seriesMask.name = "seriesMask";
+        g = _seriesMask.graphics;
+        g.clear();
+        g.beginFill(0, 100);
+        g.drawRect(0,0,10,10);
+        g.endFill();
+        _seriesMask.visible = false;
+
+        _backgroundElementMask = new FlexShape();
+        _backgroundElementMask.name = "backgroundElementMask";
+        g = _backgroundElementMask.graphics;
+        g.clear();
+        g.beginFill(0, 100);
+        g.drawRect(0,0,10,10);
+        g.endFill();
+        _backgroundElementMask.visible = false;
+
+        _annotationElementMask = new FlexShape();
+        _annotationElementMask.name = "annotationElementMask";
+        g = _annotationElementMask.graphics;
+        g.clear();
+        g.beginFill(0, 100);
+        g.drawRect(0,0,10,10);
+        g.endFill();
+        _annotationElementMask.visible = false;
+
+        _seriesHolder.addChild(_seriesMask);
+        _seriesHolder.mask = _seriesMask;
+
+        _backgroundElementHolder.addChild(_backgroundElementMask);
+        _backgroundElementHolder.mask = _backgroundElementMask;
+
+        _annotationElementHolder.addChild(_annotationElementMask);
+        _annotationElementHolder.mask = _annotationElementMask;
+
+        _currentHitSet = [];
+
+        invalidateChildOrder();
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+
+	/**
+	 *  @private
+	 */
+	private var _moduleFactoryInitialized:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _allTipCache:InstanceCache;
+
+    /**
+     *  @private
+     */
+    private var _tipCache:InstanceCache;
+
+    /**
+     *  @private
+     */
+    private var _dataTipOverlay:Shape;
+
+    /**
+     *  @private
+     */
+    private var _allDataTipOverlay:Shape;
+    /**
+     *  We need commitProperties() to be called before an update.
+     *  Since there are scenarios where that might not be guaranteed,
+     *  we'll enforce it ourselves.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private var _commitPropertiesCalled:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _seriesMask:Shape;
+
+    /**
+     *  @private
+     */
+    private var _backgroundElementMask:Shape;
+
+    /**
+     *  @private
+     */
+    private var _annotationElementMask:Shape;
+
+    /**
+     *  @private
+     */
+    private var _bSeriesDirty:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _bDataDirty:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _childOrderDirty:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _userSeries:Array /* of Series */ = [];
+
+    /**
+     *  @private
+     */
+    private var _backgroundElements:Array /* of ChartElement */ = [];
+
+    /**
+     *  @private
+     */
+    private var _annotationElements:Array /* of ChartElement */ = [];
+
+    /**
+     *  @private
+     */
+    private var _description:String = "";
+
+    /**
+     *  @private
+     */
+    private var _dataProvider:ICollectionView;
+
+    /**
+    * @private
+    */
+    protected var _seriesHolder:UIComponent;
+
+    /**
+    * @private
+    */
+    protected var _seriesFilterer:UIComponent;
+
+    /**
+    * @private
+    */
+    protected var _backgroundElementHolder:UIComponent;
+
+    /**
+    * @private
+    */
+    protected var _annotationElementHolder:UIComponent;
+
+    /**
+     *  The set of all chart elements displayed in the chart.
+     *  This set includes series, second series, background elements,
+     *  and annotation elements.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected var allElements:Array /* of ChartElement */ = [];
+
+    /**
+     *  The set of display objects that represent the labels
+     *  for the chart elements.
+     *  Some series, annotation, and background types include overlays
+     *  such elements and callouts.
+     *  Elements can pass a display object to the chart that contains
+     *  the overlays to be placed on top of all other chart elememnts.
+     *  Chart implementors can access these overlay objects
+     *  in the labelElements array.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected var labelElements:Array /* of UIComponent */ = [];
+
+    /**
+     *  @private
+     */
+    private var _clipContent:Boolean = true;
+
+    /**
+    * @private
+    */
+    protected var _transforms:Array /* of DataTransform */;
+
+    /**
+     *  @private
+     */
+    private var _showAllDataTips:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _showDataTips:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _dataTipMode:String = "multiple";
+
+    /**
+     *  @private
+     */
+    private var _currentHitSet:Array /* of HitData */;
+
+    /**
+     *  @private
+     */
+    private var _mouseEventsInitialzed:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _rangeEventsInitialzed:Boolean = false;
+
+    /**
+     *  @private
+     */
+    private var _transitionState:uint = 0;
+
+    /**
+     *  @private
+     */
+    private var _transitionEffect:ParallelInstance;
+
+    /**
+     *  @private
+     */
+    private var _seriesStylesDirty:Boolean = true;
+
+   /**
+     *  @private
+     */
+    protected var _selectedSeries:Series=null;
+
+   /**
+     *  @private
+     *  Storage for the selectionMode property.
+     */
+    private var _selectionMode:String="none";
+
+    /**
+     *  @private
+     */
+    private var _mouseDown:Boolean=false;
+
+    /**
+     *  @private
+     */
+    private var _mouseDownPoint:Point=null;
+
+    /**
+     *  @private
+     */
+    private var _mouseDownItem:ChartItem=null;
+
+    /**
+     *  @private
+     */
+    protected var _caretItem:ChartItem=null;
+
+    /**
+     *  @private
+     */
+    protected var _anchorItem:ChartItem=null;
+
+     /**
+     *  @private
+     */
+    private var dLeft:Number = 0;
+
+    /**
+     *  @private
+     */
+    private var dTop:Number = 0;
+
+    /**
+     *  @private
+     */
+    private var dRight:Number = 0;
+
+     /**
+     *  @private
+     */
+    private var dBottom:Number = 0;
+
+     /**
+     *  @private
+     */
+    private var tX:Number;
+
+    /**
+     *  @private
+     */
+    private var tY:Number;
+
+    /**
+     *  @private
+     */
+    private var rangeItemRenderer:RangeSelector = null;
+
+    /**
+     *  @private
+     */
+    private var dataRegionForRange:Rectangle = null;
+
+    /**
+     *  @private
+     */
+    public var dataTipItemsSet:Boolean = false;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  showInAutomationHierarchy
+    //----------------------------------
+
+    /**
+     *  @private
+     */
+    override public function set showInAutomationHierarchy(value:Boolean):void
+    {
+        //do not allow value changes
+    }
+
+
+    //-------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  annotationElements
+    //----------------------------------
+
+    [Inspectable(arrayType="mx.charts.chartClasses.ChartElement")]
+
+    /**
+     *  Sets an array of ChartElement objects that appears on top
+     *  of any data series rendered by the chart.
+     *  Each item in the array must extend the mx.charts.DualStyleObject
+     *  class and implement the IChartElement2 interface.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get annotationElements():Array /* of ChartElement */
+    {
+        return _annotationElements;
+    }
+
+    /**
+     *  @private
+     */
+    public function set annotationElements(value:Array /* of ChartElement */):void
+    {
+        _annotationElements = value;
+
+        invalidateSeries();
+    }
+
+    //----------------------------------
+    //  backgroundElements
+    //----------------------------------
+
+    [Inspectable(arrayType="mx.charts.chartClasses.ChartElement")]
+
+    /**
+     *  Sets an array of background ChartElement objects that appear below
+     *  any data series rendered by the chart.
+     *  Each item in the Array must extend the mx.charts.DualStyleObject
+     *  class and implement the IChartElement2 interface.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get backgroundElements():Array /* of ChartElement */
+    {
+        return _backgroundElements;
+    }
+
+    /**
+     *  @private
+     */
+    public function set backgroundElements(value:Array /* of ChartElement */):void
+    {
+        _backgroundElements = value;
+
+        invalidateSeries();
+    }
+
+    //----------------------------------
+    //  chartState
+    //----------------------------------
+
+    [Inspectable(environment="none")]
+
+    /**
+     *  The current transition state of the chart.
+     *  Use this property to determine whether the chart
+     *  is currently transitioning out its old data,
+     *  transitioning in its new data,
+     *  or has completed all transitions and is showing its current data set.
+     *  See the mx.charts.chartClasses.ChartState enumeration
+     *  for possible values.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get chartState():uint
+    {
+        return _transitionState;
+    }
+
+    /**
+    * @private
+    */
+    protected function setChartState(value:uint):void
+    {
+        if (_transitionState == value)
+            return;
+
+        var oldState:uint = _transitionState;
+        _transitionState = value;
+
+        var n:int = allElements.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var g:IChartElement = allElements[i] as IChartElement;
+            if (g)
+                g.chartStateChanged(oldState, value);
+        }
+
+        invalidateDisplayList();
+    }
+
+    //----------------------------------
+    //  clipContent
+    //----------------------------------
+
+    [Inspectable(defaultValue="true")]
+
+    /**
+     *  Determines whether Flex clips the chart to the area bounded by the axes.
+     *  Set to false to clip the chart.
+     *  Set to true to avoid clipping when the data is rendered.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get clipContent():Boolean
+    {
+        return _clipContent;
+    }
+
+    /**
+     *  @private
+     */
+    public function set clipContent(value:Boolean):void
+    {
+        if (_clipContent == value)
+            return;
+        _clipContent = value;
+
+        _seriesHolder.mask = _clipContent ?
+                             _seriesMask :
+                             null;
+
+        _backgroundElementHolder.mask = _clipContent ?
+                                        _backgroundElementMask :
+                                        null;
+
+        _annotationElementHolder.mask = _clipContent ?
+                                        _annotationElementMask :
+                                        null;
+    }
+
+    //----------------------------------
+    //  dataProvider
+    //----------------------------------
+
+    [Inspectable(category="Data", arrayType="Object")]
+
+    /**
+     *  Specifies the data provider for the chart.
+     *  Data series rendered by the chart are assigned this data provider.
+     *  To render disparate data series in the same chart,
+     *  use the dataProvider property on the individual series.
+     *
+     *
This property can accept an array
+     *  or any other object that implements the IList or ICollectionView interface.

+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get dataProvider():Object
+    {
+        return _dataProvider;
+    }
+
+    /**
+     *  @private
+     */
+    public function set dataProvider(value:Object):void
+    {
+        if (value is Array)
+        {
+            value = new ArrayCollection(value as Array);
+        }
+        else if (value is ICollectionView)
+        {
+        }
+        else if (value is IList)
+        {
+            value = new ListCollectionView(value as IList);
+        }
+        else if (value is XMLList)
+        {
+            value = new XMLListCollection(XMLList(value));
+        }
+        else if (value != null)
+        {
+            value = new ArrayCollection([ value ]);
+        }
+        else
+        {
+            value = new ArrayCollection();
+        }
+
+        _dataProvider = ICollectionView(value);
+
+        invalidateData();
+    }
+
+    //----------------------------------
+    //  dataRegion
+    //----------------------------------
+
+    /**
+     *  The area of the chart used to display data.
+     *  This rectangle excludes the area used for gutters, axis lines and labels, and padding.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function get dataRegion():Rectangle
+    {
+        return null;
+    }
+
+    //----------------------------------
+    //  dataTipFunction
+    //----------------------------------
+
+    [Inspectable(category="Data")]
+
+    /**
+     *  Specifies a callback method used to generate data tips from values.
+     *  This method should use the following signature:
+     *

+     *  function dataTipFunction(hitData:HitData):String
+     *

+     *
This method returns a string that is displayed for each data point.
+     *  The text can include HTML formatting.
+     *  The single parameter is a HitData object that describes the data point.

+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var dataTipFunction:Function;
+
+    //----------------------------------
+    //  dataTipLayerIndex
+    //----------------------------------
+
+    /**
+     *  The index of the child that is responsible for rendering data tips.
+     *  Derived classes that add visual elements to the chart
+     *  should add them below this layer.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function get dataTipLayerIndex():int
+    {
+        return getChildIndex(_dataTipOverlay);
+    }
+
+    //----------------------------------
+    //  dataTipMode
+    //----------------------------------
+
+    [Inspectable(category="Data", enumeration="single,multiple", defaultValue="single")]
+
+    /**
+     *  Specifies how Flex displays DataTip controls for the chart.
+     *  DataTip controls are similar to ToolTip controls, except that they display
+     *  an appropriate value that represents the nearest chart data point
+     *  under the mouse pointer.
+     *
+     *
Possible values of dataTipMode are:
+     *

+     *
"single" - Data tips are shown for the closest data point
+     *    to the mouse cursor.

+     *
+     *
"multiple" - Data tips are shown for any DataTip control
+     *    within range of the mouse cursor. You can control the sensitivity
+     *    with the mouseSensitivity property.

+     *

+     *

+     *
+     *
You can customize DataTip controls with the
+     *  dataTipFunction property.

+     *
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get dataTipMode():String
+    {
+        return _dataTipMode;
+    }
+
+    /**
+     *  @private
+     */
+    public function set dataTipMode(value:String):void
+    {
+        _dataTipMode = value;
+
+        updateDataTips();
+    }
+
+    //----------------------------------
+    //  description
+    //----------------------------------
+
+    [Inspectable(defaultValue="")]
+
+    /**
+     *  A short description of the data in the chart.
+     *  When accessibility is enabled, screen readers use this property to describe the chart.
+     *
This string defaults to the empty string, and must be
+     *  explicitly assigned by the developer to have meaning.

+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get description():String
+    {
+        return _description;
+    }
+
+    /**
+     *  @private
+     */
+    public function set description(value:String):void
+    {
+        setDescription(value);
+        tabEnabled = true;
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function setDescription(value:String):void
+    {
+        _description = value;
+    }
+
+    //----------------------------------
+    //  dragEnabled
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the dragEnabled property.
+     */
+    private var _dragEnabled:Boolean = false;
+
+    /**
+     *  Specifies whether you can drag items out of
+     *  this chart and drop them on other controls.
+     *  If true, dragging is enabled for the chart.
+     *  If the dropEnabled property is also true,
+     *  you can drag items and drop them in the chart
+     *  to reorder the items.
+     *
+     *  @default false
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get dragEnabled():Boolean
+    {
+        return _dragEnabled;
+    }
+
+    /**
+     *  @private
+     */
+    public function set dragEnabled(value:Boolean):void
+    {
+        if (_dragEnabled && !value)
+        {
+            removeEventListener(DragEvent.DRAG_COMPLETE,
+                                dragCompleteHandler, false);
+        }
+
+        _dragEnabled = value;
+
+        if (value)
+        {
+            addEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler,
+                             false, EventPriority.DEFAULT_HANDLER);
+        }
+    }
+
+    //----------------------------------
+    //  dragImage
+    //----------------------------------
+
+    /**
+     *  Gets an instance of a class that displays the visuals
+     *  during a drag-and-drop operation.
+     *
+     *  @default mx.controls.chartClasses.ChartItemDragProxy
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function get dragImage():IUIComponent
+    {
+        var image:ChartItemDragProxy = new ChartItemDragProxy();
+        image.owner = this;
+        return image;
+    }
+
+    //----------------------------------
+    //  dragMoveEnabled
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the dragMoveEnabled property.
+     */
+    private var _dragMoveEnabled:Boolean = false;
+
+    [Inspectable(defaultValue="false")]
+
+    /**
+     *  Indicates which display cursor to show as drag feedback.
+     *
+     *  If true, and the dragEnabled property
+     *  is true and the Control key is not held down,
+     *  moveCursor is shown as feedback.
+     *  If the Control key is held down, copyCursor is shown.
+     *
+     *  If false and the dragEnabled property
+     *  is true, then copyCursor is shown
+     *  whether the Control key is held down or not.
+     *
+     *  @default false
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get dragMoveEnabled():Boolean
+    {
+        return _dragMoveEnabled;
+    }
+
+    /**
+     *  @private
+     */
+    public function set dragMoveEnabled(value:Boolean):void
+    {
+        _dragMoveEnabled = value;
+    }
+
+
+    //----------------------------------
+    //  dropEnabled
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the dropEnabled property.
+     */
+    private var _dropEnabled:Boolean = false;
+
+    [Inspectable(defaultValue="false")]
+
+    /**
+     *  A flag that specifies whether dragged items can be dropped onto the
+     *  chart.
+     *
+     *
If you set this property to true,
+     *  the chart accepts all data formats, and assumes that
+     *  the dragged data matches the format of the data in the data provider.
+     *  To explicitly check the data format of the data
+     *  being dragged, you must handle one or more of the drag events,
+     *  such as dragOver, and call the
+     *  preventDefault() method of the DragEvent to customize
+     *  the way the list class accepts dropped data.

+     *
+     *
When dropEnabled is set to true,
+     *  Flex automatically calls the showDropFeedback()
+     *  and hideDropFeedback() methods to display the drop indicator.

+     *
+     *  @default false
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get dropEnabled():Boolean
+    {
+        return _dropEnabled;
+    }
+
+    /**
+     *  @private
+     */
+    public function set dropEnabled(value:Boolean):void
+    {
+        if (_dropEnabled && !value)
+        {
+            removeEventListener(DragEvent.DRAG_ENTER, dragEnterHandler, false);
+            removeEventListener(DragEvent.DRAG_EXIT, dragExitHandler, false);
+            removeEventListener(DragEvent.DRAG_OVER, dragOverHandler, false);
+            removeEventListener(DragEvent.DRAG_DROP, dragDropHandler, false);
+        }
+
+        _dropEnabled = value;
+
+        if (value)
+        {
+            addEventListener(DragEvent.DRAG_ENTER, dragEnterHandler, false,
+                             EventPriority.DEFAULT_HANDLER);
+            addEventListener(DragEvent.DRAG_EXIT, dragExitHandler, false,
+                             EventPriority.DEFAULT_HANDLER);
+            addEventListener(DragEvent.DRAG_OVER, dragOverHandler, false,
+                             EventPriority.DEFAULT_HANDLER);
+            addEventListener(DragEvent.DRAG_DROP, dragDropHandler, false,
+                             EventPriority.DEFAULT_HANDLER);
+        }
+    }
+
+    //----------------------------------
+    //  legendData
+    //----------------------------------
+
+    [Bindable("legendDataChanged")]
+    [Inspectable(environment="none")]
+
+    /**
+     *  An array of Legend items.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get legendData():Array /* of LegendData */
+    {
+        var keyItems:Array /* of LegendItem */ = [];
+
+        var n:int = allElements.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var s:Series = allElements[i] as Series;
+            if (s)
+                keyItems = keyItems.concat(s.legendData);
+        }
+
+        return keyItems;
+    }
+
+    //----------------------------------
+    //  mouseSensitivity
+    //----------------------------------
+
+    /**
+     *  Specifies the distance, in pixels, that Flex considers a data point
+     *  to be under the mouse pointer when the pointer moves around a chart.
+     *  Flex considers any data point less than mouseSensitivity
+     *  pixels away to be under the mouse pointer.
+     *  This value is also used by the findDataPoints method.
+     *
+     *  @default 5
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var mouseSensitivity:Number = 5;
+
+    //----------------------------------
+    //  selectedChartItem
+    //----------------------------------
+
+    [Inspectable(category="Data")]
+
+    /**
+     *  Specifies the selected ChartItem in the chart. If multiple items are selected,
+     *  this property specifies the most recently selected item.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get selectedChartItem():ChartItem
+    {
+        if (_selectedSeries)
+            return _selectedSeries.selectedItem;
+        return null;
+    }
+
+    //----------------------------------
+    //  selectedChartItems
+    //----------------------------------
+
+    [Inspectable(category="Data")]
+
+    /**
+     *  Specifies an array of all the selected ChartItem objects in the chart.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get selectedChartItems():Array /* of ChartItem */
+    {
+        var arr:Array /* of ChartItem */ = [];
+
+        var n:int = series.length;
+        for (var i:int = 0; i < n; i++)
+        {
+        	var m:int = series[i].selectedItems.length;
+            for (var j:int = 0; j < m; j++)
+            {
+                arr.push(series[i].selectedItems[j])
+            }
+        }
+
+        return arr;
+    }
+
+    //----------------------------------
+    //  selectionMode
+    //----------------------------------
+
+    [Inspectable(category="General", enumeration="none,single,multiple", defaultValue="none")]
+
+    /**
+     *  Specifies whether or not ChartItem objects can be selected. Possible
+     *  values are none, single, or multiple.
+     *  Set to none to prevent chart items from being selected.
+     *  Set to single to allow only one item to be selected at a time.
+     *  Set to multiple to allow one or more chart items to be selected at a time.
+     *
+     *
If you set this to single or multiple, you can override this on a
+     *  per-series basis by setting the value of the series' selectable property to false.
+     *  If you set the value of the selectionMode property to none, then chart items will not be selectable,
+     *  regardless of the value of the series' selectable property.

+     *
+     *  @default none
+     *
+     *  @see mx.charts.ChartItem
+     *  @see mx.charts.chartClasses.Series
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get selectionMode():String
+    {
+        return _selectionMode;
+    }
+
+    /**
+     *  @private
+     */
+    public function set selectionMode(value:String):void
+    {
+        if (_selectionMode == value)
+            return;
+
+        _selectionMode = value;
+
+        /*if (_selectionMode != "none")
+        {
+            if (_mouseEventsInitialzed == false)
+                setupMouseDispatching();
+        }*/
+
+        invalidateProperties();
+    }
+
+    //----------------------------------
+    //  series
+    //----------------------------------
+
+    [Inspectable(category="Data", arrayType="mx.charts.chartClasses.Series")]
+
+    /**
+     *  An array of Series objects that define the chart data.
+     *  Each chart defines the type of Series objects
+     *  that you use to populate this array.
+     *  For example, a ColumnChart control expects ColumnSeries objects
+     *  as part of this array.
+     *  Some charts accept any object of type IChartElement2
+     *  as part of the array, but in general each chart
+     *  expects a specific type.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get series():Array /* of Series */
+    {
+        return _userSeries;
+    }
+
+    /**
+     *  @private
+     */
+    public function set series(value:Array /* of Series */):void
+    {
+        value = value == null ? [] : value;
+        _userSeries = value;
+
+        var n:int = value.length;
+        for (var i:int = 0; i < n; ++i)
+        {
+            if (value[i] is Series)
+            {
+                (value[i] as Series).owner = this;
+            }
+        }
+
+        invalidateSeries();
+        invalidateData();
+        legendDataChanged();
+    }
+
+    //----------------------------------
+    //  seriesFilters
+    //----------------------------------
+
+    /**
+     *  An array of filters that are applied to all series in the chart.
+     *  Assign an array of bitmap filters to this property to apply them to all the series at once.
+     *  Set the seriesFilter property to an empty array to clear the default
+     *  filters on the chart's series.
+     *  Assigning filters to the seriesFilters property, which applies to all
+     *  series, is more efficient than assigning them to individual series.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get seriesFilters():Array
+    {
+        return _seriesFilterer.filters;
+    }
+
+    /**
+     *  @private
+     */
+    public function set seriesFilters(value:Array):void
+    {
+        _seriesFilterer.filters = value;
+    }
+
+    //----------------------------------
+    //  showAllDataTips
+    //----------------------------------
+
+    [Inspectable(category="Data", defaultValue="false")]
+
+    /**
+     *  Specifies whether Flex shows all DataTip controls for the chart.
+     *  DataTip controls are similar to tool tips,
+     *  except that they display an appropriate value
+     *  representing the chart data point.
+     *
+     *
Different chart elements might show different styles
+     *  of DataTip controls.
+     *  For example, a stacked chart element might show both the values
+     *  of the column and the percentage that it contributes to the whole.

+     *
+     *
You can customize DataTip controls with the
+     *  dataTipFunction property.

+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get showAllDataTips():Boolean
+    {
+        return _showAllDataTips;
+    }
+
+    /**
+     *  @private
+     */
+    public function set showAllDataTips(value:Boolean):void
+    {
+        if (_showAllDataTips == value)
+            return;
+
+        _showAllDataTips = value;
+
+        updateAllDataTips();
+    }
+
+    //----------------------------------
+    //  showDataTips
+    //----------------------------------
+
+    [Inspectable(category="Data", defaultValue="false")]
+
+    /**
+     *  Specifies whether Flex shows DataTip controls for the chart.
+     *  DataTip controls are similar to tool tips,
+     *  except that they display an appropriate value
+     *  that represents the nearest chart data point under the mouse pointer.
+     *
+     *
Different chart elements might show different styles
+     *  of DataTip controls.
+     *  For example, a stacked chart element might show both the values
+     *  of the column and the percentage that it contributes to the whole.

+     *
+     *
You can customize DataTip controls with the
+     *  dataTipFunction property.

+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get showDataTips():Boolean
+    {
+        return _showDataTips;
+    }
+
+    /**
+     *  @private
+     */
+    public function set showDataTips(value:Boolean):void
+    {
+        if (_showDataTips == value)
+            return;
+
+        _showDataTips = value;
+
+        if (_showDataTips)
+        {
+            if (_mouseEventsInitialzed == false)
+                setupMouseDispatching();
+        }
+
+        updateDataTips();
+    }
+
+    //----------------------------------
+    //  transforms
+    //----------------------------------
+
+    /**
+     *  The DataTransform objects that are managed by this chart.
+     *  Each chart contains one or more data transforms
+     *  that represent a set of axes used to map from tuples
+     *  from data space to screen space and vice-versa.
+     *  Most charts have only a single DataTransform object,
+     *  but CartesianChart controls that support second axes
+     *  can manage a second DataTransform as needed.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    [Deprecated(replacement="IChartElement2.dataTransform")]
+
+    protected function get transforms():Array /* of DataTransform */
+    {
+        return _transforms;
+    }
+
+    /**
+     *  @private
+     */
+    protected function set transforms(value:Array /* of DataTransform */):void
+    {
+        _transforms = value;
+
+        invalidateProperties();
+        invalidateSeries();
+        invalidateData();
+
+        legendDataChanged();
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    //  Diagnostics
+    //
+    //--------------------------------------------------------------------------
+
+    mx_internal function get allElementsArray():Array /* of ChartElement */
+    {
+        return allElements;
+    }
+
+    mx_internal function get labelElementsArray():Array /* of UIComponent */
+    {
+        return labelElements;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: EventDispatcher
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    override public function addEventListener(
+                                    type:String, listener:Function,
+                                    useCapture:Boolean = false,
+                                    priority:int = 0,
+                                    useWeakReference:Boolean = false):void
+    {
+        if (_mouseEventsInitialzed == false &&
+            ITEM_EVENTS[type] == true)
+        {
+            setupMouseDispatching();
+        }
+
+        super.addEventListener(type, listener, useCapture,
+                               priority, useWeakReference);
+    }
+
+	/**
+	 *  @private
+	 */
+	private function initStyles():Boolean
+	{
+		HaloDefaults.init(styleManager);
+
+		var chartBaseFill:IFill = IFill(new SolidColor(0xFFFFFF, 0));
+
+		var selector:CSSStyleDeclaration =
+			HaloDefaults.createSelector("mx.charts.chartClasses.ChartBase", styleManager);
+
+		selector.defaultFactory = function():void
+		{
+			this.chartSeriesStyles = HaloDefaults.chartBaseChartSeriesStyles;
+			this.fill = chartBaseFill;
+			this.calloutStroke = new Stroke(0x888888,2);
+			this.dataTipRenderer = DataTip;
+			this.fontSize = 10;
+		}
+
+		return true;
+	}
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: UIComponent
+    //
+    //--------------------------------------------------------------------------
+
+	/**
+	 *  @inheritDoc
+	 *
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	override public function set moduleFactory(factory:IFlexModuleFactory):void
+	{
+		super.moduleFactory = factory;
+
+		if (_moduleFactoryInitialized)
+			return;
+
+		_moduleFactoryInitialized = true;
+
+
+		// our style settings
+		initStyles();
+	}
+
+    /**
+     *  @private
+     */
+    override public function invalidateSize():void
+    {
+        cancelEffect();
+
+        super.invalidateSize();
+    }
+
+    /**
+     *  @private
+     */
+    override protected function commitProperties():void
+    {
+        _commitPropertiesCalled = true;
+
+        super.commitProperties();
+
+        if (_bSeriesDirty)
+        {
+            updateSeries();
+            _selectedSeries = null;
+            _bSeriesDirty = false;
+        }
+
+        updateSeriesStyles();
+
+        if (_bDataDirty)
+        {
+            updateData();
+            _bDataDirty = false;
+        }
+
+        if (_childOrderDirty)
+        {
+            updateChildOrder();
+            _childOrderDirty = false;
+        }
+
+        if (_selectionMode != "none")
+        {
+            if (_mouseEventsInitialzed == false)
+                setupMouseDispatching();
+            if (_rangeEventsInitialzed == false)
+                setupRangeDispatching()
+            tabEnabled = true;
+        }
+        else
+        {
+            tabEnabled = false;
+            dragEnabled = false;
+        }
+    }
+
+    /**
+     *  @private
+     */
+    override protected function measure():void
+    {
+        super.measure();
+
+        measuredWidth = 400;
+        measuredHeight = 400;
+    }
+
+    /**
+     *  @private
+     */
+    override protected function updateDisplayList(unscaledWidth:Number,
+                                                  unscaledHeight:Number):void
+    {
+        super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+        // Since there are some scenarios where we might get
+        // an updateDisplayList() before a commitProperties(),
+        //  we need to guarantee it.
+        if (_commitPropertiesCalled == false)
+            commitProperties();
+
+        graphics.clear();
+        graphics.lineStyle(0, 0, 0);
+
+        var fill:IFill = GraphicsUtilities.fillFromStyle(getStyle("fill"));
+
+        GraphicsUtilities.fillRect(graphics, 0, 0,
+            unscaledWidth, unscaledHeight, fill);
+    }
+
+    /**
+     *  @inheritDoc
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function setActualSize(w:Number, h:Number):void
+    {
+        if (w != this.width || h != this.height)
+            cancelEffect();
+
+        super.setActualSize(w, h);
+    }
+
+    /**
+     *  @private
+     */
+    override public function styleChanged(styleProp:String):void
+    {
+        if (styleProp == null || styleProp == "chartSeriesStyles")
+            invalidateSeries();
+
+        super.styleChanged(styleProp);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    [Deprecated(replacement="Series.getAxis()")]
+    /**
+     *  Retrieves the Axis instance for a particular dimension of the chart.
+     *  This is a low level accessor.
+     *  You typically retrieve the Axis instance directly through a named property,
+     *  such as horizontalAxis, verticalAxis,
+     *  or radiusAxis.
+     *
+     *  @param dimension The dimension that you want to get the axis for.
+     *
+     *  @return The Axis instance.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getAxis(dimension:String):IAxis
+    {
+        return transforms[0].getAxis(dimension);
+    }
+
+    [Deprecated(replacement="Series.setAxis()")]
+    /**
+     *  Assigns an Axis instance to a particular dimension of the chart.
+     *  This is a low-level accessor.
+     *  You typically set the Axis instance directly through a named property,
+     *  such as horizontalAxis, verticalAxis,
+     *  or radiusAxis.
+     *
+     *  @param dimension The dimension whose axis is responsible
+     *  for transforming the data.
+     *
+     *  @param value The Axis instance.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function setAxis(dimension:String, value:IAxis):void
+    {
+        transforms[0].setAxis(dimension, value);
+    }
+
+    [Deprecated(replacement="IChartElement2.dataToLocal()")]
+    /**
+     *  Converts a tuple of data values to an x-y coordinate on screen.
+     *  Call this method to transform data on to the screen
+     *  by using the same transform that the individual elements use.
+     *  For example, to create a custom highlight for a data region of a chart,
+     *  you might use this method to determine the on-screen coordinates
+     *  of the range of interest.
+     *
+     *
For Cartesian charts, you typically pass two values.
+     *  The first value maps to the horizontal axis,
+     *  and the second value maps to the vertical axis.

+     *
+     *
For polar charts, the first value maps to the angular axis,
+     *  and the second maps to the radial axis.

+     *
+     *  @param ...dataValues The data values to convert.
+     *
+     *  @return Coordinates that are relative to the chart.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function dataToLocal(... dataValues):Point
+    {
+        return null;
+    }
+
+    [Deprecated(replacement="IChartElement2.localToData()")]
+    /**
+     *  Converts a coordinate on screen to a tuple of data values.
+     *  Call this function to determine what data values
+     *  a particular point on screen represents.
+     *
Individual chart types determine how this transformation occurs.
+     *  The point is relative to the chart's coordinate space.

+     *
+     *  @param pt The Point object to convert.
+     *
+     *  @return The tuple of data values.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function localToData(pt:Point):Array /* of Object */
+    {
+        return null;
+    }
+
+    /**
+     *  Returns an array of HitData objects that describe
+     *  the nearest data point to the coordinates passed to the method.
+     *  The x and y arguments should be values
+     *  in the coordinate system of the ChartBase object.
+     *
This method adheres to the limits specified by the
+     *  mouseSensitivity property of the ChartBase object
+     *  when looking for nearby data points.

+     *
+     *  @param x The x coordinate relative to the ChartBase object.
+     *  @param y The y coordinate relative to the ChartBase object.
+     *
+     *  @return An array of HitData objects.
+     *
+     *  @see mx.charts.HitData
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function findDataPoints(x:Number, y:Number):Array /* of HitData */
+    {
+        var result:Array /* of HitData */ = [];
+
+        if (dataRegion.contains(x, y) == false)
+            return result;
+
+        var n:int;
+        var i:int;
+
+        n = allElements.length;
+        for (i = n-1; i >= 0; i--)
+        {
+            var g:IChartElement = allElements[i] as IChartElement;
+
+            if (!g || g.visible == false)
+                continue;
+
+            var hds:Array /* of HitData */ = g.findDataPoints(x - _seriesHolder.x,
+                                             y - _seriesHolder.y,
+                                             mouseSensitivity);
+
+            if (hds.length == 0)
+                continue;
+
+            result = result.concat(hds);
+        }
+
+		n = result.length;
+        for (i = 0; i < n; i++)
+        {
+            result[i].x += _seriesHolder.x;
+            result[i].y += _seriesHolder.y;
+        }
+
+        return result;
+    }
+
+    /**
+     *  Returns an array of HitData objects representing the chart items
+     *  in the underlying objects that implement the IChartElement2 interface.
+     *
+     *  @return An array of HitData objects that represent the data points.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getAllDataPoints():Array /* of HitData */
+    {
+        var result:Array /* of HitData */ = [];
+        var n:int;
+        var i:int;
+
+        n = allElements.length;
+        for (i = n-1; i >= 0; i--)
+        {
+            var g:IChartElement2 = allElements[i] as IChartElement2;
+
+            if (!g || g.visible == false)
+                continue;
+
+            var hds:Array /* of HitData */ = g.getAllDataPoints();
+
+            if (hds.length == 0)
+                continue;
+
+            result = result.concat(hds);
+        }
+
+		n = result.length;
+        for (i = 0; i < n; i++)
+        {
+            result[i].x += _seriesHolder.x;
+            result[i].y += _seriesHolder.y;
+        }
+
+        return result;
+    }
+
+    /**
+     *  Gets all the chart items that are within the defined rectangular region.
+     *  You call this method to determine what chart items are under
+     *  a particular rectangular region.
+     *
Individual chart types determine whether their chart item is under the region.
+     *  The point should be in the global coordinate space.

+     *
+     *  @param value The rectangular region.
+     *
+     *  @return An array of ChartItem objects.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+
+    public function getItemsInRegion(value:Rectangle):Array /* of ChartItem */
+    {
+        var arrAllItems:Array /* of ChartItem */ = [];
+
+        if (_transforms)
+        {
+        	var n:int  = _transforms.length;
+            for (var i:int = 0; i < n; i++)
+            {
+                arrAllItems = arrAllItems.concat(findItemsInRegionFromElements(_transforms[i],value));
+            }
+        }
+        return arrAllItems;
+    }
+
+    /**
+     *  Gets the chart item next to the currently focused item in the chart,
+     * with respect to the axes. If no chart items are currently selected,
+     * then this method returns the first item in the first series.
+     *
+     *  @param direction The direction in which the next item should be returned. Possible values
+     *                   are ChartBase.NAVIGATE_HORIZONTAL and ChartBase.NAVIGATE_VERTICAL.
+     *  @return The corresponding ChartItem object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+
+    public function getNextItem(direction:String):ChartItem
+    {
+        return null;
+    }
+
+    /**
+     *  Gets the chart item that is before the currently focused item in the chart,
+     *  with respect to the axes. If no chart items are currently selected,
+     *  then this method returns the first item in the first series.
+     *
+     *  @param direction The direction in which the previous item should be returned. Possible values
+     *                   are ChartBase.NAVIGATE_HORIZONTAL and ChartBase.NAVIGATE_VERTICAL.
+     *  @return The corresponding ChartItem object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+
+    public function getPreviousItem(direction:String):ChartItem
+    {
+        return null;
+    }
+
+    /**
+     *  Gets the first item in the chart, with respect to the axes.
+     *
+     *  @param direction The direction in which the first item should be returned. Possible values
+     *                   are ChartBase.NAVIGATE_HORIZONTAL and ChartBase.NAVIGATE_VERTICAL.
+     *  @return The corresponding ChartItem object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+
+    public function getFirstItem(direction:String):ChartItem
+    {
+        return null;
+    }
+
+    /**
+     *  Gets the last chart item in the chart, with respect to the axes.
+     *
+     *  @param direction The direction in which the last item should be returned. Possible values
+     *                   are ChartBase.NAVIGATE_HORIZONTAL and ChartBase.NAVIGATE_VERTICAL.
+     *  @return The corresponding ChartItem object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+
+    public function getLastItem(direction:String):ChartItem
+    {
+        return null;
+    }
+
+
+    /**
+     *  Dispatches a new LegendDataChanged event.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function legendDataChanged():void
+    {
+        dispatchEvent(new Event("legendDataChanged"));
+    }
+
+    /**
+     *  Informs the chart that the underlying data displayed in the chart
+     *  has been changed.
+     *  Chart series and elements call this function when their rendering has
+     *  changed in order to trigger a coordinated execution of show and hide data effects.
+     *  You typically do not call this method on the chart directly.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function hideData():void
+    {
+        if (_transitionEffect)
+        {
+            setChartState(ChartState.NONE);
+            _transitionEffect.end();
+            _transitionEffect = null;
+        }
+
+        setChartState(ChartState.PREPARING_TO_HIDE_DATA);
+    }
+
+    /**
+     *  Triggers a redraw of the chart.
+     *  Call this method when you change the style properties
+     *  of the chart's series.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function invalidateSeriesStyles():void
+    {
+        if (!_seriesStylesDirty)
+        {
+            _seriesStylesDirty = true;
+
+            invalidateProperties();
+        }
+    }
+
+    /**
+     *  Informs the chart that its series array was modified and
+     *  should be reprocessed. Derived chart classes can call this method to trigger a
+     *  call to the chart's internal updateSeries() method on the next commitProperties() cycle.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function invalidateSeries():void
+    {
+        if (_bSeriesDirty == false)
+        {
+            _bSeriesDirty = true;
+
+            invalidateProperties();
+            invalidateDisplayList();
+        }
+    }
+
+    /**
+     *  Informs the chart that its child list was modified and should be reordererd.
+     *  Derived chart classes can call this method to trigger a call to the chart's internal
+     *  updateChildOrder() method on the next commitProperties() cycle.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function invalidateChildOrder():void
+    {
+        if (_childOrderDirty == false)
+        {
+            _childOrderDirty = true;
+
+            invalidateProperties();
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function cancelEffect():void
+    {
+        if (_transitionEffect)
+        {
+            _transitionEffect.end();
+            _transitionEffect = null;
+        }
+
+        setChartState(ChartState.NONE);
+    }
+
+    /**
+     *  @private
+     */
+    protected function advanceEffectState():void
+    {
+        var p:Parallel;
+        var transitionChildren:Array;
+        var i:int;
+        var n:int;
+
+        if (_transitionState == ChartState.PREPARING_TO_HIDE_DATA)
+        {
+            transitionChildren = collectTransitions();
+
+            if (transitionChildren.length == 0)
+            {
+                setChartState(ChartState.PREPARING_TO_SHOW_DATA);
+            }
+            else
+            {
+                setChartState(ChartState.HIDING_DATA);
+
+                p = new Parallel();
+
+                _transitionEffect = ParallelInstance(p.createInstance());
+
+				n = transitionChildren.length;
+                for (i = 0; i < n; i++)
+                {
+                    _transitionEffect.addChildSet([transitionChildren[i]]);
+                }
+
+                _transitionEffect.addEventListener(EffectEvent.EFFECT_END,
+                                                   dataEffectEndHandler);
+
+                _transitionEffect.play();
+            }
+        }
+
+        if (_transitionState == ChartState.PREPARING_TO_SHOW_DATA)
+        {
+            transitionChildren = collectTransitions();
+
+            if (transitionChildren.length == 0)
+            {
+                setChartState(ChartState.NONE);
+            }
+            else
+            {
+                setChartState(ChartState.SHOWING_DATA);
+
+                p = new Parallel();
+
+                _transitionEffect = ParallelInstance(p.createInstance());
+
+				n = transitionChildren.length;
+                for (i = 0; i < n; i++)
+                {
+                    _transitionEffect.addChildSet([transitionChildren[i]]);
+                }
+
+                _transitionEffect.addEventListener(EffectEvent.EFFECT_END,
+                                                   dataEffectEndHandler);
+
+                _transitionEffect.play();
+
+            }
+        }
+        invalidateDisplayList();
+    }
+
+    /**
+     *  @private
+     */
+    private function setupMouseDispatching():void
+    {
+        _mouseEventsInitialzed = true;
+
+        super.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
+        super.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
+        super.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
+        super.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
+        super.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
+        super.addEventListener(MouseEvent.CLICK, mouseClickHandler);
+        super.addEventListener(MouseEvent.DOUBLE_CLICK, mouseDoubleClickHandler);
+    }
+
+   /**
+     *  @private
+     */
+    private function setupRangeDispatching():void
+    {
+        _rangeEventsInitialzed = true;
+        addEventListener(RangeEvent.REGION_CHANGE, regionChangeHandler);
+    }
+
+    /**
+     *  @private
+     */
+    private function processRollEvents(hitSet:Array /* of HitData */, event:MouseEvent):void
+    {
+        var removedSet:Array /* of HitData */ = [];
+        var addedSet:Array /* of HitData */ = [];
+        var unchangedSet:Array /* of HitData */ = [];
+        var newLen:int = hitSet.length;
+        var oldLen:int = _currentHitSet.length;
+        var oldIndex:int = 0;
+        var newIndex:int = 0;
+
+        var pt:Point = null;
+
+        if (hitSet.length == 0 && _currentHitSet.length == 0)
+        {
+            if (_selectionMode == "single" && event.type == flash.events.MouseEvent.MOUSE_DOWN)
+            {
+                clearSelection();
+                return;
+            }
+            else if (_selectionMode == "multiple" && event.type == flash.events.MouseEvent.MOUSE_DOWN)
+            {
+                startTracking(event);
+                return;
+            }
+            return;
+        }
+
+        var sortingSet:Array /* of HitData */ = hitSet.concat();
+        if (newLen > 1)
+            sortingSet.sortOn("id", Array.NUMERIC);
+
+        while (oldIndex < oldLen || newIndex < newLen)
+        {
+            if (newIndex == newLen ||
+                (oldIndex < oldLen &&
+                 _currentHitSet[oldIndex].id < sortingSet[newIndex].id))
+            {
+                removedSet.push(_currentHitSet[oldIndex]);
+                oldIndex++;
+            }
+            else if (oldIndex == oldLen ||
+                     (newIndex < newLen &&
+                      _currentHitSet[oldIndex].id > sortingSet[newIndex].id))
+            {
+                addedSet.push(sortingSet[newIndex]);
+                newIndex++;
+            }
+            else
+            {
+                unchangedSet.push(sortingSet[newIndex]);
+                newIndex++;
+                oldIndex++;
+            }
+        }
+
+        if (removedSet.length > 0)
+        {
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.ITEM_ROLL_OUT,
+                                             removedSet, event, this));
+        }
+
+        if (addedSet.length > 0)
+        {
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.ITEM_ROLL_OVER,
+                                             addedSet, event, this));
+        }
+
+        if (unchangedSet.length > 0)
+        {
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.ITEM_MOUSE_MOVE,
+                                             unchangedSet, event, this));
+        }
+
+        if (event.type == flash.events.MouseEvent.MOUSE_DOWN)
+        {
+            if (_dragEnabled && !DragManager.isDragging)
+            {
+                _mouseDown = true;
+                pt = new Point(event.localX, event.localY);
+                pt = DisplayObject(event.target).localToGlobal(pt);
+                _mouseDownPoint = globalToLocal(pt);
+                _mouseDownItem = hitSet[0].chartItem;
+            }
+            else if (hitSet.length > 0) // If dragEnabled is true, selection change happens on mouseup as items will get deselected.
+                selectItem(hitSet[0].chartItem,event);
+        }
+
+        if (event.type == flash.events.MouseEvent.MOUSE_UP)
+        {
+            if (_dragEnabled && _mouseDown && !DragManager.isDragging)
+                selectItem(_mouseDownItem,event);
+
+            _mouseDown = false;
+            _mouseDownPoint = null;
+            _mouseDownItem = null;
+        }
+
+        if (event.type != flash.events.MouseEvent.MOUSE_DOWN && event.type != flash.events.MouseEvent.MOUSE_UP)
+        {
+            if (!(DragManager.isDragging))
+                rollOverItem(hitSet,removedSet);
+        }
+
+        if (event.type == flash.events.MouseEvent.MOUSE_MOVE)
+        {
+            pt = new Point(event.localX, event.localY);
+            pt = DisplayObject(event.target).localToGlobal(pt);
+            pt = globalToLocal(pt);
+
+            if (_dragEnabled && _mouseDown && !DragManager.isDragging && (Math.abs(_mouseDownPoint.x - pt.x) > DRAG_THRESHOLD || Math.abs(_mouseDownPoint.y - pt.y) > DRAG_THRESHOLD))
+            {
+                // check whether the mousedown item is selected or not.
+                var seriesObject:Series = Series(_mouseDownItem.element);
+                if (seriesObject.selectedItems.indexOf(_mouseDownItem) == -1)
+                    selectItem(_mouseDownItem,event);
+
+                if (_selectedSeries) // if atleast one item is selected, then only drag
+                {
+                    var mousePt:Point = localToGlobal(_mouseDownPoint);
+                    mousePt = _selectedSeries.globalToLocal(mousePt);
+                    var dragEvent:DragEvent = new DragEvent(DragEvent.DRAG_START);
+                    dragEvent.dragInitiator = this;
+                    dragEvent.localX = mousePt.x;
+                    dragEvent.localY = mousePt.y;
+                    dragEvent.buttonDown = true;
+                    _selectedSeries.dispatchEvent(dragEvent);
+                }
+            }
+        }
+
+        _currentHitSet = hitSet;
+
+        // Do not show datatips when drag is happening as drag image will not be having datatip
+        if (_dragEnabled && _mouseDown && DragManager.isDragging)
+            updateDataTipToMatchHitSet([]);
+        else
+            updateDataTipToMatchHitSet(_currentHitSet);
+    }
+
+   /**
+    *  @private
+    */
+   mx_internal function rollOverItem(hitSet:Array /* of HitData */,removedSet:Array /* of HitData */):void
+   {
+        var data:HitData = null;
+        var seriesObject:Series = null;
+        var index:int = 0;
+
+        // Set the first item in the hitset to roll over - as per datatip logic.
+        if (hitSet.length > 0)
+        {
+            data = hitSet[0];
+            if (_selectionMode != "none" && Series(data.chartItem.element).selectable)
+                data.chartItem.currentState = ChartItem.ROLLOVER;
+        }
+
+        // removedset also can be set when hitset is set
+        if (removedSet.length > 0)
+        {
+        	var n: int = removedSet.length;
+            // we do not know which item has rollover hence loop through all removed set
+            for (var i:int = 0; i < n; i++)
+            {
+                data = removedSet[i];
+                seriesObject = Series(data.chartItem.element);
+                if (seriesObject.selectable) // handle for those series, which are selectable
+                {
+                    index = seriesObject.selectedItems.indexOf(data.chartItem);
+                    if (index == -1) // item not selected in the series
+                    {
+                        if (!_selectedSeries)
+                            data.chartItem.currentState = ChartItem.NONE;
+                        else
+                            data.chartItem.currentState = ChartItem.DISABLED;
+                    }
+                    else // item is selected in the series
+                    {
+                        data.chartItem.currentState = ChartItem.SELECTED;
+                    }
+                }
+            }
+        }
+    }
+
+   /**
+    *  @private
+    */
+
+   mx_internal function selectItem(item:ChartItem, event:MouseEvent):void
+   {
+        var seriesObject:Series = null;
+        var bSelectionChanged:Boolean = false;
+        var bAddToSelection:Boolean = false;
+        var index:int = -1;
+
+        seriesObject = Series(item.element);
+
+        if (event.shiftKey && _anchorItem)
+        {
+            handleShift(item);
+            bSelectionChanged = true;
+            // now make data.chartItem as the last item in that series to get selected.
+            // if that is selectable otherwise take the selected series
+            if (seriesObject.selectedItems.length > 1)
+            {
+                var id:int = seriesObject.selectedItems.indexOf(item);
+                seriesObject.selectedItems.splice(id,1);
+                seriesObject.selectedItems.push(item);
+                _selectedSeries = seriesObject;
+            }
+        }
+        else
+        if (_selectionMode != "none" && seriesObject.selectable)
+        {
+            // If the item is selected
+            if (seriesObject.selectedItems.indexOf(item) == -1)
+                bAddToSelection = true;
+
+            if (bAddToSelection)
+            {
+                if (!_selectedSeries)
+                    setChartItemsToDisabled();
+                else
+                {
+                    if (_selectionMode == "single")
+                    {
+                        // if multiple selection was enabled earlier and now its single check that.
+                        if (selectedChartItems.length > 1)
+                        {
+                            clearSelection();
+                            setChartItemsToDisabled();
+                        }
+                        else
+                            _selectedSeries.removeItemfromSelection(_selectedSeries.selectedItem);
+                    }
+                    else if (!event.ctrlKey)
+                    {
+                        clearSelection();
+                        setChartItemsToDisabled();
+                    }
+                }
+                seriesObject.addItemtoSelection(item);
+                _selectedSeries = seriesObject;
+
+                bSelectionChanged = true;
+            }
+            else
+            {
+                if (_selectionMode == "multiple")
+                {
+                    if (event.ctrlKey) // remove this item from selection
+                    {
+                        seriesObject.removeItemfromSelection(item);
+                        if (_selectedSeries.selectedItems.length == 0)
+                        {
+                            var nextSeries:Series = seriesObject;
+                            nextSeries = getSelectedSeries(seriesObject);
+
+                            if (!nextSeries) // This was the only item selected
+                                clearSelection();
+                            else
+                                _selectedSeries = nextSeries;
+                        }
+                        bSelectionChanged = true;
+                    }
+                    else // clear all others except this
+                    {
+                        // if this is the same item as the only selected item - do nothing.
+                        if (seriesObject == _selectedSeries && !(getSelectedSeries(seriesObject)) && _selectedSeries.selectedItems.length == 1)
+                            bSelectionChanged = false;
+                        else
+                        {
+                            clearSelection();
+                            setChartItemsToDisabled();
+
+                            seriesObject.addItemtoSelection(item);
+                            _selectedSeries = seriesObject;
+                            bSelectionChanged = true;
+                        }
+                    }
+                    // As the mouse is over that item, but the item is selected
+                    item.currentState = ChartItem.ROLLOVER;
+                }
+                else // If the selection mode is single, just change the selected series
+                {
+                    if (selectedChartItems.length > 1)
+                    {
+                        clearSelection();
+                        seriesObject.addItemtoSelection(item);
+                    }
+                    _selectedSeries = seriesObject;
+                }
+            }
+        }
+
+       if (bSelectionChanged)
+       {
+            if (_selectedSeries)
+            {
+                if (_caretItem) // caret item could have been selected as part of keyboard, clear that.
+                {
+                    if (Series(_caretItem.element).selectedItems.indexOf(_caretItem) != -1)
+                        _caretItem.currentState = ChartItem.SELECTED;
+                    else
+                        _caretItem.currentState = ChartItem.DISABLED;
+                }
+
+                _caretItem = _selectedSeries.selectedItem;
+                _caretItem.currentState = ChartItem.FOCUSEDSELECTED;
+                if (!_anchorItem || !event.shiftKey)
+                    _anchorItem = _caretItem;
+            }
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.CHANGE,null,event,this));
+       }
+   }
+
+  /**
+    *  @private
+    */
+
+   mx_internal function getSelectedSeries(seriesObject:Series):Series
+   {
+   		var n:int  = _transforms.length;
+        for (var i:int = 0; i < n; i++)
+        {
+        	var m:int = _transforms[i].elements.length;
+            for (var j:int = 0; j < m; j++)
+            {
+                if (_transforms[i].elements[j] is Series && _transforms[i].elements[j] != seriesObject && _transforms[i].elements[j].selectedItems.length != 0)
+                    return _transforms[i].elements[j];
+            }
+        }
+
+        return null;
+    }
+
+  /**
+    *  @private
+    */
+
+   mx_internal function setChartItemsToDisabled():void
+   {
+   		var n:int = _transforms.length;
+        for (var i:int = 0; i < n; i++)
+        {
+        	var m:int = _transforms[i].elements.length;
+            for (var j:int = 0; j < m; j++)
+            {
+                if (_transforms[i].elements[j] is Series)
+                    _transforms[i].elements[j].clearSeriesItemsState(false,ChartItem.DISABLED);
+            }
+        }
+    }
+
+   /**
+     *  Deselects all selected chart items in the chart control. Sets the currentState property of all chart items in the
+     *  chart to none.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+
+   public function clearSelection():void
+   {
+        if (_selectedSeries)
+        {
+        	var n:int  = _transforms.length;
+            for (var i:int = 0; i < n; i++)
+            {
+            	var m:int = _transforms[i].elements.length;
+                for (var j:int = 0; j < m; j++)
+                {
+                    if (_transforms[i].elements[j] is Series)
+                        _transforms[i].elements[j].clearSeriesItemsState(true);
+                }
+            }
+
+            _selectedSeries = null;
+            _caretItem = null;
+            _anchorItem = null;
+        }
+   }
+
+    /**
+     *  @private
+     */
+
+    mx_internal function selectSpecificChartItems(arrItems:Array /* of ChartItem */):void
+    {
+        var seriesObject:Series = null;
+        var item:ChartItem = null;
+        var index:int = -1;
+        var bDisabled:Boolean = false;
+
+        // clear all
+        clearSelection();
+
+        var n:int = arrItems.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            seriesObject = Series(arrItems[i].element);
+            if (seriesObject.selectable)
+            {
+                if (!bDisabled) // set items to disabled, only if there are items to be selected
+                {
+                    bDisabled = true;
+                    setChartItemsToDisabled();
+                }
+                // if an item is already selected - deselect that and selct this item
+                if (_selectionMode == "single" && _selectedSeries)
+                    _selectedSeries.removeItemfromSelection(_selectedSeries.selectedItem);
+
+                if (seriesObject.selectedItems.indexOf(arrItems[i]) == -1)
+                    seriesObject.addItemtoSelection(arrItems[i]);
+                _selectedSeries = seriesObject;
+            }
+        }
+
+        if (_selectedSeries)
+        {
+            _caretItem = _selectedSeries.selectedItem;
+            _caretItem.currentState = ChartItem.FOCUSEDSELECTED;
+            _anchorItem = _caretItem;
+        }
+    }
+
+     /**
+     *  @private
+     */
+
+    mx_internal function seriesSelectionChanged(seriesObject:Series,arrItems:Array /* of ChartItem */):void
+    {
+        var nextSeries:Series = null;
+
+        if (_selectionMode == "none")
+            return;
+
+        // if nothing is selected, disable all.
+        if (!_selectedSeries)
+            setChartItemsToDisabled();
+        else
+            seriesObject.clearSeriesItemsState(true,ChartItem.DISABLED);
+
+        if (arrItems.length == 0)
+        {
+            // Is any other series selected
+            nextSeries = getSelectedSeries(seriesObject);
+            if (!nextSeries)
+                clearSelection();
+            else
+                _selectedSeries = nextSeries;
+        }
+        else
+        {
+            if (_selectionMode == "single")
+            {
+                if (_selectedSeries && _selectedSeries != seriesObject)
+                    _selectedSeries.removeItemfromSelection(_selectedSeries.selectedItem);
+                seriesObject.addItemtoSelection(arrItems[arrItems.length - 1]);
+            }
+            else
+            {
+            	var n:int = arrItems.length;
+                for (var i:int = 0; i < n; i++)
+                {
+                    seriesObject.addItemtoSelection(arrItems[i]);
+                }
+            }
+
+            _selectedSeries = seriesObject;
+        }
+
+        if (_selectedSeries)
+        {
+            _caretItem = _selectedSeries.selectedItem;
+            _caretItem.currentState = ChartItem.FOCUSEDSELECTED;
+            _anchorItem = _caretItem;
+        }
+    }
+
+    /**
+     *  @private
+     */
+     mx_internal function handleSpace(event:KeyboardEvent):void
+     {
+        // select or deselect the caret item depending upon the ctrl key
+        if (!_caretItem)
+            return;
+
+        var caretSeries:Series;
+        var bSelectionChanged:Boolean = false;
+        var bControl:Boolean = false;
+        var bShift:Boolean = false;
+
+        if (event.ctrlKey)
+            bControl = true;
+
+        if (event.shiftKey) // Shift takes precedence over control. But Shift will behave same as normal case.
+        {
+            bShift = true;
+            bControl = false;
+        }
+
+        caretSeries = Series(_caretItem.element);
+
+        if (caretSeries.selectable)
+        {
+            if (caretSeries.selectedItems.indexOf(_caretItem) != -1) // already selected
+            {
+                if (bControl) // now deselect that
+                {
+                    caretSeries.removeItemfromSelection(_caretItem);
+                    _caretItem.currentState = ChartItem.FOCUSED;
+
+                    if (selectionMode == "single")
+                        clearSelection();
+                    else if (_selectedSeries.selectedItems.length == 0) // more items from other series are there
+                    {
+                        var nextSeries:Series = caretSeries;
+                        nextSeries = getSelectedSeries(caretSeries);
+                        if (!nextSeries) // This was the only item selected
+                            clearSelection();
+                        else
+                            _selectedSeries = nextSeries;
+                    }
+                    bSelectionChanged = true;
+                }
+            }
+            else // not selected, select that
+            {
+                if (_selectionMode == "single" || (_selectionMode == "multiple" && !bControl))
+                {
+                    var item:ChartItem = _caretItem;
+                    clearSelection();
+                    _caretItem = item;
+                    _anchorItem = item;
+                }
+
+                if (!_selectedSeries) // nothing is selected
+                    setChartItemsToDisabled();
+
+                _selectedSeries = caretSeries;
+                _selectedSeries.addItemtoSelection(_caretItem);
+                _caretItem.currentState = ChartItem.FOCUSEDSELECTED;
+                bSelectionChanged = true;
+            }
+        }
+
+        if (bSelectionChanged)
+        {
+            if (_selectedSeries && (!bShift || !_anchorItem))
+                _anchorItem = _selectedSeries.selectedItem;
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.CHANGE,null,null,this));
+        }
+     }
+
+    /**
+     *  @private
+     */
+    mx_internal function handleNavigation(item:ChartItem,event:KeyboardEvent):void
+    {
+        var seriesObject:Series;
+        var caretSeriesObject:Series;
+        var bSelectionChanged:Boolean = false;
+        var bControl:Boolean = false;
+        var bShift:Boolean = false;
+
+        seriesObject = Series(item.element);
+
+        if (event.ctrlKey)
+            bControl = true;
+
+        if (event.shiftKey) // Shift takes precedence over control.
+        {
+            bShift = true;
+            bControl = false;
+        }
+
+        if (bControl) // Do not change the selection but change the highlight
+        {
+            if (_caretItem)
+            {
+                var caretSeries:Series;
+                caretSeries = Series(_caretItem.element);
+                if (caretSeries.selectable)
+                {
+                    if (caretSeries.selectedItems.indexOf(_caretItem) != -1)
+                        _caretItem.currentState = ChartItem.SELECTED
+                    else if (_selectedSeries)
+                            _caretItem.currentState = ChartItem.DISABLED;
+                        else
+                            _caretItem.currentState = ChartItem.NONE;
+                }
+            }
+            item.currentState = ChartItem.FOCUSED;
+        }
+        else // Change the selection
+        {
+            if (!bShift || !_anchorItem)
+            {
+                if (!_selectedSeries)
+                    setChartItemsToDisabled();
+                else
+                    if (selectionMode == "single")
+                        _selectedSeries.removeItemfromSelection(_selectedSeries.selectedItem);
+                    else
+                    {
+                        clearSelection();
+                        setChartItemsToDisabled();
+                    }
+
+                seriesObject.addItemtoSelection(item);
+                _selectedSeries = seriesObject;
+                item.currentState = ChartItem.FOCUSEDSELECTED;
+            }
+            else // select the item under shift, _selectedSeries should not be null.
+            {
+                if (selectionMode == "single")
+                {
+                    _selectedSeries.removeItemfromSelection(_selectedSeries.selectedItem);
+                    seriesObject.addItemtoSelection(item);
+                }
+                else // clear all except the anchor item and select range from anchor to item.
+                {
+                    var tempItem:ChartItem = _anchorItem;
+                    var index1:int = Series(_anchorItem.element).items.indexOf(_anchorItem);
+                    var index2:int = seriesObject.items.indexOf(item);
+                    var temp:int;
+
+                    clearSelection();
+                    setChartItemsToDisabled();
+                    _anchorItem = tempItem;
+
+                    // With current behavior anchor and item should be from the same series for range selection.
+                    if (Series(_anchorItem.element) == seriesObject)
+                    {
+                        if (index1 > index2)
+                        {
+                            temp = index1;
+                            index1 = index2;
+                            index2 = temp;
+                        }
+                        for (temp = index1; temp <= index2; temp++)
+                        {
+                            seriesObject.addItemtoSelection(seriesObject.items[temp]);
+                        }
+                    }
+                    else
+                    {
+                        Series(_anchorItem.element).addItemtoSelection(_anchorItem);
+                        seriesObject.addItemtoSelection(item);
+                    }
+                }
+                _selectedSeries = seriesObject;
+                item.currentState = ChartItem.FOCUSEDSELECTED;
+            }
+            bSelectionChanged = true;
+        }
+
+        _caretItem = item;
+
+        if (bSelectionChanged && _selectedSeries)
+        {
+            if (!bShift || (_selectedSeries && !_anchorItem)) // This can happen when nothing is selected and shift is pressed
+                _anchorItem = _selectedSeries.selectedItem;
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.CHANGE,null,null,this));
+        }
+    }
+
+    /**
+     *  @private
+     */
+     mx_internal function handleShift(item:ChartItem):void
+     {
+        // is called only when anchor item is not null
+        // leverage the region selection algo for handling shift - but it resets the anchor and caret items.
+        var tempItem:ChartItem = _anchorItem;
+        var tempCaretItem:ChartItem = _caretItem;
+
+        if (!(_anchorItem.itemRenderer) || !(item.itemRenderer))
+            return;
+
+        var rc:Rectangle = new Rectangle;
+        var pt1:Point = new Point(_anchorItem.itemRenderer.x ,_anchorItem.itemRenderer.y);
+        var pt2:Point = new Point(item.itemRenderer.x ,item.itemRenderer.y);
+        var arrItems:Array /* of ChartItem */;
+        var pt:Point;
+
+        pt1 = Series(_anchorItem.element).localToGlobal(pt1);
+        pt2 = Series(item.element).localToGlobal(pt2);
+
+
+        rc.left = Math.min(pt1.x, pt2.x,pt1.x + _anchorItem.itemRenderer.width, pt2.x + item.itemRenderer.width);
+        rc.top = Math.min(pt1.y, pt2.y,pt1.y + _anchorItem.itemRenderer.height, pt2.y + item.itemRenderer.height);
+
+        rc.right = Math.max(pt1.x, pt2.x,pt1.x + _anchorItem.itemRenderer.width, pt2.x + item.itemRenderer.width);
+        rc.bottom = Math.max(pt1.y, pt2.y,pt1.y + _anchorItem.itemRenderer.height, pt2.y + item.itemRenderer.height);
+
+        // Make sure we relax the bounds a little bit, otherwise neighbors can get selected
+        rc.left = rc.left + 2;
+        rc.top  = rc.top + 2;
+        rc.right = rc.right - 2;
+        rc.bottom = rc.bottom - 2;
+
+        selectRectangleRegion(rc);
+
+        // restore anchor item and caret item
+        _anchorItem = tempItem;
+        _caretItem = tempCaretItem;
+     }
+
+    /**
+     *  @private
+     */
+     private function selectRectangleRegion(r:Rectangle, bPreserveSelection:Boolean = false):void
+     {
+        var arrItems:Array /* of ChartItem */ = getItemsInRegion(r);
+
+        if (bPreserveSelection)
+            arrItems = arrItems.concat(selectedChartItems);
+
+        selectSpecificChartItems(arrItems);
+     }
+
+    /**
+     *  @private
+     */
+
+    mx_internal function getSeriesTransformState(seriesObject:Object):Boolean
+    {
+        return seriesObject.getTransformState();
+    }
+
+    /**
+     *  @private
+     */
+    private function findItemsInRegionFromElements(transform:DataTransform,value:Rectangle):Array /* of ChartItem */
+    {
+        var elements:Array /* of ChartElement */ = transform.elements;
+        var arrItems:Array /* of ChartItem */ = [];
+        var n:int = elements.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            if (elements[i] is Series && elements[i].selectable && elements[i].visible)
+                arrItems = arrItems.concat(elements[i].getItemsInRegion(value));
+        }
+        return arrItems;
+    }
+
+    /**
+     *  @private
+     */
+    private function updateDataTips():void
+    {
+        var hitPoints:Array /* of HitData */ = findDataPoints(mouseX, mouseY);
+        _currentHitSet = hitPoints;
+
+        updateDataTipToMatchHitSet(_currentHitSet);
+    }
+
+    /**
+     *  Displays all noninteractive data tips
+     *  if showAllDataTips is set.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function updateAllDataTips():void
+    {
+        var hitSet:Array /* of HitData */;
+
+        if (!showAllDataTips && !dataTipItemsSet)
+            hitSet = [];
+        else
+            hitSet = getAllDataPoints();
+
+        var tipCount:Number = hitSet.length;
+
+        if (tipCount == 0)
+        {
+            if (_allTipCache)
+                _allTipCache.count = 0;
+        }
+        else
+        {
+            if (!_allTipCache)
+            {
+                var tipClass:* = getStyle("dataTipRenderer");
+                _allTipCache = new InstanceCache(tipClass, this);
+                _allTipCache.discard = true;
+                _allTipCache.remove = true;
+
+            }
+            _allTipCache.count = tipCount;
+
+            for (var i:int = 0; i < tipCount; i++)
+            {
+                var currentHitData:HitData = hitSet[i];
+
+                var tipInstance:IFlexDisplayObject  = _allTipCache.instances[i];
+
+                if (dataTipFunction != null)
+                    currentHitData.dataTipFunction = invokeDTFunction;
+
+                if (tipInstance is IDataRenderer)
+                    (tipInstance as IDataRenderer).data = currentHitData;
+            }
+        }
+
+        positionAllDataTips(hitSet);
+    }
+
+    /**
+     *  @private
+     */
+    private function updateDataTipToMatchHitSet(hitSet:Array /* of HitData */):void
+    {
+        var tipCount:Number;
+
+        if (_showDataTips == false)
+        {
+            tipCount = 0;
+        }
+        else if (_dataTipMode == "multiple")
+        {
+            tipCount= getStyle("maximumDataTipCount");
+            if (isNaN(tipCount))
+                tipCount = hitSet.length;
+            else
+                tipCount = Math.min(tipCount, hitSet.length);
+        }
+        else // "single"
+        {
+            tipCount = Math.min(hitSet.length, 1);
+        }
+
+        if (tipCount == 0)
+        {
+            if (_tipCache)
+                _tipCache.count = 0;
+        }
+        else
+        {
+            if (!_tipCache)
+            {
+                var tipClass:* = getStyle("dataTipRenderer");
+                _tipCache = new InstanceCache(tipClass,
+                                              systemManager.toolTipChildren);
+                _tipCache.discard = true;
+                _tipCache.remove = true;
+                _tipCache.creationCallback = tipCreated;
+
+            }
+            _tipCache.count = tipCount;
+
+            for (var i:int = 0; i < tipCount; i++)
+            {
+                var currentHitData:HitData = hitSet[i];
+
+                var tipInstance:IFlexDisplayObject  = _tipCache.instances[i];
+
+                if (dataTipFunction != null)
+                    currentHitData.dataTipFunction = invokeDTFunction;
+
+                if (tipInstance is IDataRenderer)
+                    (tipInstance as IDataRenderer).data = currentHitData;
+            }
+        }
+
+        positionDataTips();
+    }
+
+    /**
+     *  @private
+     */
+    private function tipCreated(tip:IEventDispatcher, cache:InstanceCache):void
+    {
+        tip.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
+        tip.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
+        tip.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
+    }
+
+    /**
+     *  @private
+     */
+    private function invokeDTFunction(hd:HitData):String
+    {
+        return dataTipFunction(hd);
+    }
+
+    /**
+     *  Defines the locations of DataTip objects on the chart when the
+     *  showAllDataTips property is set to true.
+     *  This method ensures that DataTips do not overlap each other
+     *  (if multiple DataTips are visible) or overlap their target data items.
+     *
+     *  @param hitSet An Array of HitData objects.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function positionAllDataTips(hitSet:Array /* of HitData */):void
+    {
+        var tipCount:int = _allTipCache ? _allTipCache.count:0;
+        var rc:Rectangle = dataRegion;
+        var g:Graphics = _allDataTipOverlay.graphics;
+        var pData:Array /* of TipPositionData */;
+        var pLeft:Array /* of TipPositionData */ = [];
+        var pRight:Array /* of TipPositionData */ = [];
+        var sortList:Array /* of TipPositionData */ = [];
+        var i:int;
+        var data:TipPositionData;
+        var minX:Number;
+        var maxX:Number;
+        var len:int;
+        var stacks:Array /* of TipStack */;
+        var currentStack:TipStack;
+        var calloutStroke:IStroke = getStyle("calloutStroke");
+        var dataTipHOffset:Number = getStyle("horizontalDataTipOffset");
+        var dataTipVOffset:Number = getStyle("horizontalDataTipOffset");
+
+        if (isNaN(dataTipHOffset))
+            dataTipHOffset = 6;
+        if (isNaN(dataTipVOffset))
+            dataTipVOffset = 6;
+
+        g.clear();
+
+        if (tipCount == 0)
+            return;
+
+        var showTargetValue:Object = getStyle("showDataTipTargets");
+        var showTarget:Boolean = showTargetValue != false &&
+                                 showTargetValue != "false";
+
+        pData = _allTipCache.instances.slice(0, tipCount);
+        var localPts:Point = new Point();
+
+        for (i = 0; i < tipCount; i++)
+        {
+            var hitData:HitData = hitSet[i];
+            var tipInstance:IFlexDisplayObject = pData[i];
+
+            localPts.x = Math.max(rc.left, Math.min(hitData.x, rc.right));
+            localPts.y = Math.max(rc.top, Math.min(hitData.y, rc.bottom));
+            var pts:Point = localToGlobal(localPts);
+
+            var xpos:Number;
+            var ypos:Number;
+
+            if (tipInstance is ILayoutManagerClient)
+                ILayoutManagerClient (tipInstance).validateSize();
+
+            data = new TipPositionData(tipInstance, hitData,
+                                       localPts.x, localPts.y, pts.x, pts.y);
+
+            if (data.gy - dataTipVOffset - tipInstance.measuredHeight > 0)
+                data.py = data.gy - dataTipVOffset - tipInstance.measuredHeight;
+            else
+                data.py = data.gy + dataTipVOffset;
+
+            sortList.push(data);
+            pData[i] = data;
+        }
+
+        if (sortList.length > 0)
+        {
+            sortList.sortOn("gx", Array.NUMERIC);
+
+            minX = sortList[0].gx;
+            maxX = sortList[sortList.length - 1].gx;
+
+            var screenTL:Point = new Point(4, 4);
+            var screenBR:Point = new Point(screen.width - 4, screen.height - 4);
+
+            i = 0;
+
+            // This code pre-examines the datatips for tips that would
+            // stick out off screen, and forces them to flip to the other side.
+            // While this gets datatips that don't stick off screen and don't
+            // overlap the points, it makes for some fantastically unattractive
+            // datatip layouts.
+            // So for now I'm opting for the prettier but occasionally slightly
+            // annoying behavior of sliding tips over until they don't stick
+            // off screen, potentially overlapping the points.
+            /*
+            while (i < sortList.length)
+            {
+                data = sortList[i];
+                if (maxX + dataTipHOffset + tipInstance.measuredWidth >
+                    screenBR.x)
+                {
+                    pLeft.push(data);
+                    sortList.splice(i, 1);
+                }
+                else if (minX - dataTipHOffset - tipInstance.measuredWidth <
+                         screenTL.x)
+                {
+                    pRight.push(data);
+                    sortList.splice(i ,1);
+                }
+                else
+                {
+                    i++;
+                }
+            }
+            */
+
+            var splitPoint:int = Math.floor(sortList.length / 2);
+
+            // As a first approximation, we just divide these in half.
+            // But our goal is to end up with an even set of left/right stacks.
+            // So if we already have items in those stacks,
+            // let's adjust our split.
+            if (pLeft.length > pRight.length)
+            {
+                splitPoint = Math.max(0, splitPoint -
+                                      (pLeft.length - pRight.length));
+            }
+            else if (pRight.length > pLeft.length)
+            {
+                splitPoint = Math.min(sortList.length,
+                                      splitPoint +
+                                      (pRight.length - pLeft.length));
+            }
+
+            pLeft = pLeft.concat(sortList.slice(0, splitPoint));
+            pRight = pRight.concat(sortList.slice(splitPoint, sortList.length));
+        }
+
+        pRight.sortOn("gy");
+        len = pRight.length;
+        stacks = [];
+        currentStack = null;
+
+        for (i = 0; i < len; i++)
+        {
+            data = pRight[i];
+            data.isRight = true;
+            data.px = data.gx + dataTipHOffset;
+            if (currentStack)
+            {
+                if (data.py < currentStack.gy + currentStack.height)
+                {
+                    currentStack.addTip(data, screen.height);
+                }
+                else
+                {
+                    reduceStacks(stacks, currentStack);
+                    currentStack = new TipStack();
+                    currentStack.addTip(data, screen.height);
+                }
+            }
+            else
+            {
+                currentStack = new TipStack();
+                currentStack.addTip(data, screen.height);
+            }
+        }
+
+        if (currentStack)
+            reduceStacks(stacks, currentStack);
+
+        // Now make sure none of the tips block any targets.
+        var startTarget:Number = 0;
+        var endTarget:Number = 0;
+
+        len = stacks.length;
+        for (i = 0; i < len; i++)
+        {
+            stacks[i].positionY();
+        }
+
+        pLeft.sortOn("gy");
+        len = pLeft.length;
+        stacks = [];
+        currentStack = null;
+        for (i = 0; i < len; i++)
+        {
+            data = pLeft[i];
+            data.isRight = false;
+            data.px = data.gx - data.width - dataTipHOffset;
+
+            if (currentStack)
+            {
+                if (data.py < currentStack.gy + currentStack.height)
+                {
+                    currentStack.addTip(data, screen.height);
+                }
+                else
+                {
+                    reduceStacks(stacks, currentStack);
+                    currentStack = new TipStack();
+                    currentStack.addTip(data, screen.height);
+                }
+            }
+            else
+            {
+                currentStack = new TipStack();
+                currentStack.addTip(data, screen.height);
+            }
+        }
+
+        if (currentStack)
+            reduceStacks(stacks, currentStack);
+
+        len = stacks.length;
+        for (i = 0; i < len; i++)
+        {
+            stacks[i].positionY();
+        }
+
+        pData.sortOn("py");
+        len = pData.length;
+        maxX = -Infinity;
+        minX = Infinity;
+
+        var minForRightTips:Number = -Infinity;
+        var maxForLeftTips:Number = Infinity;
+        var repeatLayout:Boolean = true;
+
+        // We should never have to go through this loop more than twice.
+        var repeatCount:Number = 0;
+        while (repeatLayout && repeatCount <= 2)
+        {
+            repeatLayout = false;
+            repeatCount++;
+            for (i = 0; i < len; i++)
+            {
+                var tipData:TipPositionData = pData[i];
+
+                var bResetMaxX:Boolean = false;
+                var bResetMinX:Boolean = false;
+
+                while (startTarget < pData.length &&
+                       pData[startTarget].gy + TOOLTIP_TARGET_RADIUS <
+                       tipData.py)
+                {
+                    if (pData[startTarget].gx >= maxX)
+                        bResetMaxX = true;
+                    if (pData[startTarget].gx <= minX)
+                        bResetMinX = true;
+
+                    startTarget++;
+                }
+
+                endTarget = Math.max(endTarget, startTarget);
+
+                while (endTarget < pData.length &&
+                       pData[endTarget].gy - TOOLTIP_TARGET_RADIUS <
+                       tipData.py + tipData.height)
+                {
+                    if (pData[endTarget].gx >= maxX)
+                    {
+                        bResetMaxX = false;
+                        maxX = pData[endTarget].gx;
+                    }
+
+                    if (pData[endTarget].gx <= minX)
+                    {
+                        bResetMinX = false;
+                        minX = pData[endTarget].gx;
+                    }
+
+                    endTarget++;
+                }
+
+                if (bResetMaxX || bResetMinX)
+                {
+                    maxX = -Infinity;
+                    minX = Infinity;
+
+                    for (var j:int = startTarget; j < endTarget; j++)
+                    {
+                        maxX = Math.max(maxX, pData[j].gx);
+                        minX = Math.min(minX, pData[j].gx);
+                    }
+                }
+
+                if (tipData.isRight)
+                {
+                    tipData.px = Math.max(tipData.px,
+                                          maxX + TOOLTIP_TARGET_RADIUS);
+                    tipData.px = Math.max(minForRightTips, tipData.px);
+
+                    if (tipData.px > screenBR.x - tipData.width)
+                    {
+                        tipData.px = screenBR.x - tipData.width;
+                        if (maxForLeftTips > tipData.px)
+                        {
+                            maxForLeftTips = tipData.px;
+                            repeatLayout = true;
+                        }
+                    }
+                }
+                else
+                {
+                    tipData.px = Math.min(tipData.px,
+                                          minX - TOOLTIP_TARGET_RADIUS -
+                                          tipData.width);
+                    tipData.px = Math.min(maxForLeftTips - tipData.width,
+                                          tipData.px);
+
+                    if (tipData.px < screenTL.x)
+                    {
+                        tipData.px = screenTL.x;
+                        if (tipData.px + tipData.width > minForRightTips)
+                        {
+                            minForRightTips = tipData.px + tipData.width;
+                            repeatLayout = true;
+                        }
+                    }
+                }
+
+                pts.x = tipData.px;
+                pts.y = tipData.py;
+                localPts = globalToLocal(pts);
+                tipData.tip.move(localPts.x, localPts.y);
+
+                if (showTarget)
+                {
+                    if (len > 1)
+                    {
+                        if (calloutStroke)
+                        {
+                            calloutStroke.apply(g,null,null);
+
+                            if (tipData.isRight)
+                            {
+                                g.moveTo(localPts.x,
+                                         localPts.y + tipData.height /  2);
+                                g.lineTo(tipData.x,
+                                         localPts.y + tipData.height / 2);
+                                g.lineTo(tipData.x, tipData.y);
+                            }
+                            else
+                            {
+                                g.moveTo(localPts.x + tipData.width,
+                                         localPts.y + tipData.height / 2);
+                                g.lineTo(tipData.x,
+                                         localPts.y + tipData.height / 2);
+                                g.lineTo(tipData.x, tipData.y);
+                            }
+                        }
+                    }
+
+                    var tipColor:uint = tipData.hd.contextColor;
+                    g.lineStyle(1, tipColor, 100);
+                    g.moveTo(tipData.x, tipData.y);
+                    g.beginFill(0xFFFFFF, 1);
+                    g.drawCircle(tipData.x, tipData.y, TOOLTIP_TARGET_RADIUS);
+                    g.endFill();
+
+                    g.beginFill(tipColor, 1);
+                    g.drawCircle(tipData.x, tipData.y,
+                                 TOOLTIP_TARGET_INNER_RADIUS);
+                    g.endFill();
+                }
+            }
+        }
+    }
+
+    /**
+     *  Defines the locations of DataTip objects on the chart.
+     *  This method ensures that DataTip objects do not overlap each other
+     *  (if multiple DataTip objects are visible) or overlap their target data items.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function positionDataTips():void
+    {
+        var tipCount:int = _tipCache ? _tipCache.count:0;
+        var rc:Rectangle = dataRegion;
+        var g:Graphics = _dataTipOverlay.graphics;
+        var pData:Array /* of TipPositionData */;
+        var pLeft:Array /* of TipPositionData */ = [];
+        var pRight:Array /* of TipPositionData */  = [];
+        var sortList:Array /* of TipPositionData */ = [];
+        var i:int;
+        var data:TipPositionData;
+        var minX:Number;
+        var maxX:Number;
+        var len:int;
+        var stacks:Array /* of TipStack */;
+        var currentStack:TipStack;
+        var calloutStroke:IStroke = getStyle("calloutStroke");
+        var dataTipHOffset:Number = getStyle("horizontalDataTipOffset");
+        var dataTipVOffset:Number = getStyle("horizontalDataTipOffset");
+
+        if (isNaN(dataTipHOffset))
+            dataTipHOffset = 6;
+        if (isNaN(dataTipVOffset))
+            dataTipVOffset = 6;
+
+        g.clear();
+
+        if (tipCount == 0)
+            return;
+
+        var showTargetValue:Object = getStyle("showDataTipTargets");
+        var showTarget:Boolean = showTargetValue != false &&
+                                 showTargetValue != "false";
+
+        pData = _tipCache.instances.slice(0, tipCount);
+        var localPts:Point = new Point();
+
+        for (i = 0; i < tipCount; i++)
+        {
+            var hitData:HitData = _currentHitSet[i];
+            var tipInstance:IFlexDisplayObject = pData[i];
+
+            localPts.x = Math.max(rc.left, Math.min(hitData.x, rc.right));
+            localPts.y = Math.max(rc.top, Math.min(hitData.y, rc.bottom));
+			var pts:Point = localToGlobal(localPts);
+
+            var xpos:Number;
+            var ypos:Number;
+
+            if (tipInstance is ILayoutManagerClient)
+                ILayoutManagerClient (tipInstance).validateSize();
+
+            data = new TipPositionData(tipInstance, hitData,
+                                       localPts.x, localPts.y, pts.x, pts.y);
+
+            if (data.gy - dataTipVOffset - tipInstance.measuredHeight > 0)
+                data.py = data.gy - dataTipVOffset - tipInstance.measuredHeight;
+            else
+                data.py = data.gy + dataTipVOffset;
+
+            sortList.push(data);
+            pData[i] = data;
+        }
+
+        if (sortList.length > 0)
+        {
+            sortList.sortOn("gx", Array.NUMERIC);
+
+            minX = sortList[0].gx;
+            maxX = sortList[sortList.length - 1].gx;
+
+            var screenTL:Point = new Point(4, 4);
+            var screenBR:Point = new Point(screen.width - 4, screen.height - 4);
+
+            i = 0;
+
+            // This code pre-examines the datatips for tips that would
+            // stick out off screen, and forces them to flip to the other side.
+            // While this gets datatips that don't stick off screen and don't
+            // overlap the points, it makes for some fantastically unattractive
+            // datatip layouts.
+            // So for now I'm opting for the prettier but occasionally slightly
+            // annoying behavior of sliding tips over until they don't stick
+            // off screen, potentially overlapping the points.
+            /*
+            while (i < sortList.length)
+            {
+                data = sortList[i];
+                if (maxX + dataTipHOffset + tipInstance.measuredWidth >
+                    screenBR.x)
+                {
+                    pLeft.push(data);
+                    sortList.splice(i, 1);
+                }
+                else if (minX - dataTipHOffset - tipInstance.measuredWidth <
+                         screenTL.x)
+                {
+                    pRight.push(data);
+                    sortList.splice(i ,1);
+                }
+                else
+                {
+                    i++;
+                }
+            }
+            */
+
+            var splitPoint:int = Math.floor(sortList.length / 2);
+
+            // As a first approximation, we just divide these in half.
+            // But our goal is to end up with an even set of left/right stacks.
+            // So if we already have items in those stacks,
+            // let's adjust our split.
+            if (pLeft.length > pRight.length)
+            {
+                splitPoint = Math.max(0, splitPoint -
+                                      (pLeft.length - pRight.length));
+            }
+            else if (pRight.length > pLeft.length)
+            {
+                splitPoint = Math.min(sortList.length,
+                                      splitPoint +
+                                      (pRight.length - pLeft.length));
+            }
+
+            pLeft = pLeft.concat(sortList.slice(0, splitPoint));
+            pRight = pRight.concat(sortList.slice(splitPoint, sortList.length));
+        }
+
+        pRight.sortOn("gy");
+        len = pRight.length;
+        stacks = [];
+        currentStack = null;
+
+        for (i = 0; i < len; i++)
+        {
+            data = pRight[i];
+            data.isRight = true;
+            data.px = data.gx + dataTipHOffset;
+            if (currentStack)
+            {
+                if (data.py < currentStack.gy + currentStack.height)
+                {
+                    currentStack.addTip(data, screen.height);
+                }
+                else
+                {
+                    reduceStacks(stacks, currentStack);
+                    currentStack = new TipStack();
+                    currentStack.addTip(data, screen.height);
+                }
+            }
+            else
+            {
+                currentStack = new TipStack();
+                currentStack.addTip(data, screen.height);
+            }
+        }
+
+        if (currentStack)
+            reduceStacks(stacks, currentStack);
+
+        // Now make sure none of the tips block any targets.
+        var startTarget:Number = 0;
+        var endTarget:Number = 0;
+
+        len = stacks.length;
+        for (i = 0; i < len; i++)
+        {
+            stacks[i].positionY();
+        }
+
+        pLeft.sortOn("gy");
+        len = pLeft.length;
+        stacks = [];
+        currentStack = null;
+        for (i = 0; i < len; i++)
+        {
+            data = pLeft[i];
+            data.isRight = false;
+            data.px = data.gx - data.width - dataTipHOffset;
+
+            if (currentStack)
+            {
+                if (data.py < currentStack.gy + currentStack.height)
+                {
+                    currentStack.addTip(data, screen.height);
+                }
+                else
+                {
+                    reduceStacks(stacks, currentStack);
+                    currentStack = new TipStack();
+                    currentStack.addTip(data, screen.height);
+                }
+            }
+            else
+            {
+                currentStack = new TipStack();
+                currentStack.addTip(data, screen.height);
+            }
+        }
+
+        if (currentStack)
+            reduceStacks(stacks, currentStack);
+
+        len = stacks.length;
+        for (i = 0; i < len; i++)
+        {
+            stacks[i].positionY();
+        }
+
+        pData.sortOn("py");
+        len = pData.length;
+        maxX = -Infinity;
+        minX = Infinity;
+
+        var minForRightTips:Number = -Infinity;
+        var maxForLeftTips:Number = Infinity;
+        var repeatLayout:Boolean = true;
+
+        // We should never have to go through this loop more than twice.
+        var repeatCount:Number = 0;
+        while (repeatLayout && repeatCount <= 2)
+        {
+            repeatLayout = false;
+            repeatCount++;
+            for (i = 0; i < len; i++)
+            {
+                var tipData:TipPositionData = pData[i];
+
+                var bResetMaxX:Boolean = false;
+                var bResetMinX:Boolean = false;
+
+                while (startTarget < pData.length &&
+                       pData[startTarget].gy + TOOLTIP_TARGET_RADIUS <
+                       tipData.py)
+                {
+                    if (pData[startTarget].gx >= maxX)
+                        bResetMaxX = true;
+                    if (pData[startTarget].gx <= minX)
+                        bResetMinX = true;
+
+                    startTarget++;
+                }
+
+                endTarget = Math.max(endTarget, startTarget);
+
+                while (endTarget < pData.length &&
+                       pData[endTarget].gy - TOOLTIP_TARGET_RADIUS <
+                       tipData.py + tipData.height)
+                {
+                    if (pData[endTarget].gx >= maxX)
+                    {
+                        bResetMaxX = false;
+                        maxX = pData[endTarget].gx;
+                    }
+
+                    if (pData[endTarget].gx <= minX)
+                    {
+                        bResetMinX = false;
+                        minX = pData[endTarget].gx;
+                    }
+
+                    endTarget++;
+                }
+
+                if (bResetMaxX || bResetMinX)
+                {
+                    maxX = -Infinity;
+                    minX = Infinity;
+
+                    for (var j:int = startTarget; j < endTarget; j++)
+                    {
+                        maxX = Math.max(maxX, pData[j].gx);
+                        minX = Math.min(minX, pData[j].gx);
+                    }
+                }
+
+                if (tipData.isRight)
+                {
+                    tipData.px = Math.max(tipData.px,
+                                          maxX + TOOLTIP_TARGET_RADIUS);
+                    tipData.px = Math.max(minForRightTips, tipData.px);
+
+                    if (tipData.px > screenBR.x - tipData.width)
+                    {
+                        tipData.px = screenBR.x - tipData.width;
+                        if (maxForLeftTips > tipData.px)
+                        {
+                            maxForLeftTips = tipData.px;
+                            repeatLayout = true;
+                        }
+                    }
+                }
+                else
+                {
+                    tipData.px = Math.min(tipData.px,
+                                          minX - TOOLTIP_TARGET_RADIUS -
+                                          tipData.width);
+                    tipData.px = Math.min(maxForLeftTips - tipData.width,
+                                          tipData.px);
+
+                    if (tipData.px < screenTL.x)
+                    {
+                        tipData.px = screenTL.x;
+                        if (tipData.px + tipData.width > minForRightTips)
+                        {
+                            minForRightTips = tipData.px + tipData.width;
+                            repeatLayout = true;
+                        }
+                    }
+                }
+                pts.x = tipData.px;
+                pts.y = tipData.py;
+
+
+                localPts = this.parentApplication.systemManager.getSandboxRoot().globalToLocal(pts);
+
+				var chartLocalPts:Point = globalToLocal(pts);
+
+				tipData.tip.move(localPts.x, localPts.y);
+				if (showTarget)
+                {
+                    if (len > 1)
+                    {
+                        if (calloutStroke)
+                        {
+                            calloutStroke.apply(g,null,null);
+
+                            if (tipData.isRight)
+                            {
+                                g.moveTo(chartLocalPts.x,
+                                         chartLocalPts.y + tipData.height /  2);
+                                g.lineTo(tipData.x,
+                                         chartLocalPts.y + tipData.height / 2);
+                                g.lineTo(tipData.x, tipData.y);
+                            }
+                            else
+                            {
+                                g.moveTo(chartLocalPts.x + tipData.width,
+                                         chartLocalPts.y + tipData.height / 2);
+                                g.lineTo(tipData.x,
+                                         chartLocalPts.y + tipData.height / 2);
+                                g.lineTo(tipData.x, tipData.y);
+                            }
+                        }
+                    }
+
+                    var tipColor:uint = tipData.hd.contextColor;
+                    g.lineStyle(1, tipColor, 100);
+                    g.moveTo(tipData.x, tipData.y);
+                    g.beginFill(0xFFFFFF, 1);
+                    g.drawCircle(tipData.x, tipData.y, TOOLTIP_TARGET_RADIUS);
+                    g.endFill();
+
+                    g.beginFill(tipColor, 1);
+                    g.drawCircle(tipData.x, tipData.y,
+                                 TOOLTIP_TARGET_INNER_RADIUS);
+                    g.endFill();
+                }
+            }
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function reduceStacks(stacks:Array /* of TipStack */, currentStack:TipStack):void
+    {
+        while (stacks.length > 0)
+        {
+            var prevStack:TipStack = stacks[stacks.length - 1];
+            if (prevStack.gy + prevStack.height < currentStack.gy)
+                break;
+
+            prevStack.merge(currentStack, screen.height);
+
+            currentStack = stacks.pop();
+        }
+
+        stacks.push(currentStack);
+    }
+
+    /**
+     *  Applies per-series customization and formatting to the series of the chart.
+     *  This method is called once for each series when the series
+     *  has been changed by a call to the invalidateSeries() method.
+     *
+     *  @param seriesGlyph The series to customize.
+     *  @param i The series' index in the series array.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function customizeSeries(seriesGlyph:Series, i:uint):void
+    {
+    }
+
+    /**
+     *  Triggers a redraw of the chart.
+     *  Call this method when you add or change
+     *  the chart's series or data providers.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function invalidateData():void
+    {
+        _bDataDirty=true;
+        invalidateProperties();
+    }
+
+    /**
+     *  Preprocesses the series and transform for display. You typically do not call
+     *  this method directly. Instead, this method is called automatically during the
+     *  chart control's commitProperties() cycle when the series has
+     *  been invalidated by a call to the invalidateSeries() method.
+     *
By default, this method calls the customizeSeries() method once for each series in the set.
+     *  Chart subclasses can override this method to add customization logic that is global to the whole series set.

+     *
+     *  @param seriesSet An array of series to preprocess.
+     *  @param transform The transform used by the series.
+     *
+     *  @return An array of series with the series set applied.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function applySeriesSet(seriesSet:Array /* of Series */,
+                                      transform:DataTransform):Array /* of Series */
+    {
+    	var n:int = seriesSet.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var newSeries:IChartElement = seriesSet[i];
+            if (newSeries is Series)
+                customizeSeries(Series(seriesSet[i]), i);
+        }
+
+        return seriesSet;
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function updateChildOrder():void
+    {
+        var nextindex:int = 0;
+        setChildIndex(_backgroundElementHolder, nextindex++);
+        nextindex = updateAxisOrder(nextindex);
+        setChildIndex(_seriesHolder, nextindex++);
+        setChildIndex(_annotationElementHolder, nextindex++);
+        setChildIndex(_allDataTipOverlay, nextindex++);
+        setChildIndex(_dataTipOverlay, nextindex++);
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function updateAxisOrder(nextindex:int):int
+    {
+        return nextindex;
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function updateSeries():void
+    {
+        var displayedSeries:Array /* of Series */ = applySeriesSet(_userSeries, _transforms[0]);
+
+        var len:int = displayedSeries ? displayedSeries.length : 0;
+        var c:DisplayObject;
+        var g:IChartElement;
+        var labelLayer:UIComponent;
+
+        len = labelElements.numChildren;
+
+        removeElements(_backgroundElementHolder, true);
+        removeElements(_seriesFilterer, false);
+        removeElements(_annotationElementHolder, true);
+
+        addElements(_backgroundElements, _transforms[0],
+                    _backgroundElementHolder);
+
+        allElements = _backgroundElements.concat();
+
+        addElements(displayedSeries, _transforms[0], _seriesFilterer);
+
+        allElements = allElements.concat(displayedSeries);
+
+        labelElements = [];
+        var n:int  = displayedSeries.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            g = displayedSeries[i] as IChartElement;
+            if (!g)
+                continue;
+
+            Series(g).invalidateProperties();
+
+            labelLayer = UIComponent(g.labelContainer);
+            if (labelLayer)
+                labelElements.push(labelLayer);
+        }
+
+        addElements(labelElements, _transforms[0],_annotationElementHolder);
+
+        allElements = allElements.concat(labelElements);
+
+        addElements(_annotationElements,
+                    _transforms[0],_annotationElementHolder);
+
+        allElements = allElements.concat(_annotationElements);
+
+        _transforms[0].elements = _annotationElements.concat(displayedSeries).
+                                  concat(_backgroundElements);
+
+        _bDataDirty = true;
+        invalidateSeriesStyles();
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function addElements(elements:Array /* of ChartElement */, transform:DataTransform,
+                                   elementParent:UIComponent):void
+    {
+        var c:DisplayObject;
+        var g:IChartElement;
+
+        var n:int = elements.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            c = elements[i];
+            g = c as IChartElement;
+            if (g && !(g is Series) && !(g is IDataCanvas))
+                g.dataTransform = transform;
+
+            elementParent.addChild(c);
+        }
+    }
+
+    /**
+     * @private
+     */
+    mx_internal function removeElements(parent:UIComponent,hasMask:Boolean):void
+    {
+        var n:int = parent.numChildren;
+        var stopIndex:int = hasMask ? 1 : 0;
+        for (var i:int = n - 1;
+             i >= stopIndex; // intentional -- leave the mask in place
+             i--)
+        {
+            var c:DisplayObject = parent.removeChildAt(i);
+            var g:IChartElement = (c as IChartElement);
+            if (g)
+                g.dataTransform = null;
+        }
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function updateSeriesStyles():void
+    {
+        if (_seriesStylesDirty)
+        {
+            _seriesStylesDirty = false;
+
+            var nextAvailableStyle:uint = 0;
+
+            var styles:Array /* of Object */ = getStyle("chartSeriesStyles");
+            if (styles)
+            {
+                var n:int = allElements.length;
+                for (var i:int = 0; i < n; i++)
+                {
+                    var g:IChartElement = allElements[i] as IChartElement;
+                    if (g)
+                    {
+                        nextAvailableStyle =
+                            g.claimStyles(styles, nextAvailableStyle);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function applyDataProvider(dp:ICollectionView,
+                                         transform:DataTransform):void
+    {
+        var axes:Object = transform.axes;
+        for (var p:String in axes)
+        {
+            axes[p].chartDataProvider = dp;
+        }
+
+        var elements:Array /* of ChartElement */ = transform.elements;
+        var n:int = elements.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            if (elements[i] is Series)
+                elements[i].chartDataProvider = dp;
+        }
+        clearSelection();
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function updateData():void
+    {
+        if (_dataProvider != null)
+            applyDataProvider(_dataProvider,_transforms[0]);
+
+        var n:uint = series.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            applyDataProvider(ICollectionView(dataProvider),series[i].dataTransform);
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function collectTransitions():Array /* of IEffectInstance */
+    {
+        var a:Array /* of IEffectInstance */ = [];
+
+        var n:int = allElements.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var g:IChartElement = allElements[i] as IChartElement;
+            if (g)
+                g.collectTransitions(_transitionState, a);
+        }
+
+        return a;
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function updateKeyboardCache():void
+    {
+        return;
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function getNextSeries(seriesArray:Array /* of Series */):ChartItem
+    {
+        var itemFound:Boolean = false;
+        var index:int;
+
+        // We are not cycling through the items if we reach the end as per some customers suggestion
+        if (!_caretItem)
+            index = -1;
+        else
+            index = seriesArray.indexOf(Series(_caretItem.element));
+
+        while (!itemFound && index < seriesArray.length - 1)
+        {
+            ++index;
+            if (seriesArray[index].selectable && seriesArray[index].visible && seriesArray[index].items.length > 0)
+                itemFound = true;
+        }
+
+        if (itemFound)
+            return seriesArray[index].items[0];
+        return null;
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function getPreviousSeries(seriesArray:Array /* of Series */ ):ChartItem
+    {
+        var itemFound:Boolean = false;
+        var index:int;
+
+        // We are not cycling through the items if we reach the end as per some customers suggestion
+        if (!_caretItem)
+            index = seriesArray.length;
+        else
+            index = seriesArray.indexOf(Series(_caretItem.element));
+        while (!itemFound && index > 0)
+        {
+            --index;
+            if (seriesArray[index].selectable && seriesArray[index].visible && seriesArray[index].items.length > 0)
+                itemFound = true;
+        }
+
+        if (itemFound)
+            return seriesArray[index].items[0];
+        return null;
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function getNextSeriesItem(seriesArray:Array /* of Series */ ):ChartItem
+    {
+        var index:int = 0;
+        var caretSeries:Series;
+
+        if (!_caretItem)
+            return getNextSeries(seriesArray);
+
+        caretSeries = Series(_caretItem.element);
+        index = caretSeries.items.indexOf(_caretItem);
+        if (index == caretSeries.items.length - 1)
+            return null;
+        return caretSeries.items[++index];
+    }
+
+    /**
+     *  @private
+     */
+    mx_internal function getPreviousSeriesItem(seriesArray:Array /* of Series */):ChartItem
+    {
+        var index:int = 0;
+        var caretSeries:Series;
+
+        if (!_caretItem)
+            return getPreviousSeries(seriesArray);
+
+        caretSeries = Series(_caretItem.element);
+        index = caretSeries.items.indexOf(_caretItem);
+        if (index == 0)
+            return null;
+        return caretSeries.items[--index];
+    }
+
+    /**
+     *  Adds the selected items to the DragSource object as part of a
+     *  drag and drop operation.
+     *  You can override this method to add other data to the drag source.
+     *
+     * @param ds The DragSource object to which the data is added.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function addDragData(ds:Object):void // actually a DragSource
+    {
+        ds.addData(selectedChartItems, "chartitems");
+    }
+
+    /**
+     *  Displays a drop indicator under the mouse pointer to indicate that a
+     *  drag-and-drop operation is allowed. The drop indicator also indicates where the items will
+     *  be dropped.
+     *
+     *  @param event A DragEvent object that contains information about where
+     *  the mouse pointer is.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function showDropFeedback(event:DragEvent):void
+    {
+        drawFocus(true);
+    }
+
+    /**
+     *  Hides the drop indicator that indicates that a
+     *  drag-and-drop operation is allowed.
+     *
+     *  @param event A DragEvent object that contains information about the
+     *  mouse location.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function hideDropFeedback(event:DragEvent):void
+    {
+        drawFocus(false);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Region Selection
+    //
+    //--------------------------------------------------------------------------
+
+    private function startTracking(event:MouseEvent) :void
+    {
+       /* the user clicked the mouse down. First, we need to add listeners for the mouse dragging */
+       if (dataRegion.contains(mouseX,mouseY) == false)
+           return;
+
+       if (rangeItemRenderer)
+       {
+           rangeItemRenderer.clear();
+           removeChild(rangeItemRenderer);
+       }
+
+       rangeItemRenderer = new RangeSelector();
+       addChild(rangeItemRenderer);
+
+       dataRegionForRange = dataRegion;
+
+       systemManager.getSandboxRoot().addEventListener("mouseUp",endTracking,true);
+       systemManager.getSandboxRoot().addEventListener("mouseMove",track,true);
+
+       var mouseVals:Array /* of Number */;
+
+       tX = mouseX;
+       tY = mouseY;
+       mouseVals = [tX,tY];
+
+       updateTrackBounds(mouseVals);
+    }
+
+    private function track(event:MouseEvent):void
+    {
+        if (event.buttonDown == false)
+        {
+            endTracking(event);
+            return;
+        }
+        updateTrackBounds([mouseX,mouseY]);
+        dispatchRegionChange(event);
+        event.stopPropagation();
+    }
+
+    private function dispatchRegionChange(event:MouseEvent):void
+    {
+        var leftTop:Point = new Point(dLeft,dTop);
+        var rightBottom:Point = new Point(dRight,dBottom);
+        leftTop = localToGlobal(leftTop);
+        rightBottom = localToGlobal(rightBottom);
+        var r:Rectangle = new Rectangle(leftTop.x, leftTop.y, rightBottom.x - leftTop.x, rightBottom.y - leftTop.y);
+
+        dispatchEvent(new RangeEvent(RangeEvent.REGION_CHANGE,r,event));
+    }
+
+    private function endTracking(event:MouseEvent):void
+    {
+        systemManager.getSandboxRoot().removeEventListener("mouseUp",endTracking,true);
+        systemManager.getSandboxRoot().removeEventListener("mouseMove",track,true);
+
+        rangeItemRenderer.clear();
+        removeChild(rangeItemRenderer);
+        rangeItemRenderer = null;
+
+        dispatchRegionChange(event);
+     }
+
+    private function updateTrackBounds(mouseVals:Array /* of Number */):void
+    {
+        /* store the bounding rectangle of the selection, in a normalized mouse coordinates -based rectangle */
+
+        dRight = Math.max(tX,mouseVals[0]);
+        dLeft = Math.min(tX,mouseVals[0]);
+        dTop = Math.min(tY,mouseVals[1]);
+        dBottom = Math.max(tY,mouseVals[1]);
+
+        dLeft = Math.max(dLeft,dataRegionForRange.left);
+        dTop = Math.max(dTop,dataRegionForRange.y);
+        dRight = Math.min(dRight,dataRegionForRange.x + dataRegionForRange.width);
+        dBottom = Math.min(dBottom, dataRegionForRange.y + dataRegionForRange.height);
+
+        rangeItemRenderer.move(dLeft,dTop);
+        rangeItemRenderer.setActualSize(dRight - dLeft,dBottom - dTop);
+    }
+
+
+    //--------------------------------------------------------------------------
+    //
+    //  Event handlers
+    //
+    //--------------------------------------------------------------------------
+
+
+    /**
+     *  @private
+     */
+    private function mouseOverHandler(event:MouseEvent):void
+    {
+        if (_tipCache)
+        {
+            var n:int = _tipCache.count;
+            for (var i:int = 0; i < n; i++)
+            {
+                var ti:IFlexDisplayObject = _tipCache.instances[i];
+
+                if (event.target == ti ||
+                    ((ti is DisplayObjectContainer) &&
+                     (ti as DisplayObjectContainer).contains(
+                        event.target as DisplayObject)))
+                {
+                    return;
+                }
+
+                if (event.relatedObject&&
+                    (ti == event.relatedObject ||
+                     ((ti is DisplayObjectContainer) &&
+                      (ti as DisplayObjectContainer).contains(
+                        event.relatedObject))))
+                {
+                    return;
+                }
+            }
+        }
+
+        if (!(event.relatedObject) ||
+            (event.relatedObject != this &&
+             !contains(event.relatedObject)))
+        {
+            var p:Point = new Point(event.localX, event.localY);
+            p = globalToLocal(DisplayObject(event.target).localToGlobal(p));
+
+            var hitPoints:Array /* of HitData */ = findDataPoints(p.x, p.y);
+
+            processRollEvents(hitPoints, event);
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function mouseOutHandler(event:MouseEvent):void
+    {
+
+        if (_tipCache)
+        {
+            var n:int = _tipCache.count;
+            for (var i:int = 0; i < n; i++)
+            {
+                var ti:IFlexDisplayObject = _tipCache.instances[i];
+
+                if (event.target == ti ||
+                    ((ti is DisplayObjectContainer) &&
+                     (ti as DisplayObjectContainer).contains(
+                        event.target as DisplayObject)))
+                {
+                    return;
+                }
+
+                if (event.relatedObject &&
+                    (ti == event.relatedObject ||
+                     ((ti is DisplayObjectContainer) &&
+                      (ti as DisplayObjectContainer).contains(
+                            event.relatedObject))))
+                {
+                    return;
+                }
+            }
+        }
+
+        if (!(event.relatedObject) ||
+            (event.relatedObject != this &&
+             !contains(event.relatedObject)))
+        {
+            processRollEvents([], event);
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function mouseDownHandler(event:MouseEvent):void
+    {
+        var p:Point = new Point(event.localX, event.localY);
+        p = globalToLocal(DisplayObject(event.target).localToGlobal(p));
+
+        var hitPoints:Array /* of HitData */ = findDataPoints(p.x, p.y);
+		setFocus();
+        processRollEvents(hitPoints, event);
+
+        if (_currentHitSet)
+        {
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.ITEM_MOUSE_DOWN,
+                                             _currentHitSet, event, this));
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function mouseMoveHandler(event:MouseEvent):void
+    {
+        if (_tipCache)
+        {
+            var n:int = _tipCache.count;
+            for (var i:int = 0; i < n; i++)
+            {
+                var ti:IFlexDisplayObject = _tipCache.instances[i];
+
+                if (event.target == ti ||
+                    ((ti is DisplayObjectContainer) &&
+                    (ti as DisplayObjectContainer).contains(
+                        event.target as DisplayObject)))
+                {
+                    return;
+                }
+            }
+        }
+
+        var p:Point = new Point(event.localX, event.localY);
+        p = globalToLocal(DisplayObject(event.target).localToGlobal(p));
+
+        var hitPoints:Array /* of HitData */ = findDataPoints(p.x, p.y);
+
+        processRollEvents(hitPoints, event);
+    }
+
+    /**
+     *  @private
+     */
+    private function mouseUpHandler(event:MouseEvent):void
+    {
+        var p:Point = new Point(event.localX, event.localY);
+        p = globalToLocal(DisplayObject(event.target).localToGlobal(p));
+
+        var hitPoints:Array /* of HitData */  = findDataPoints(p.x, p.y);
+
+        processRollEvents(hitPoints, event);
+
+        if (_currentHitSet)
+        {
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.ITEM_MOUSE_UP,
+                                             _currentHitSet, event, this));
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function mouseClickHandler(event:MouseEvent):void
+    {
+        var p:Point = new Point(event.localX, event.localY);
+        p = globalToLocal(DisplayObject(event.target).localToGlobal(p));
+
+        var hitPoints:Array /* of HitData */ = findDataPoints(p.x, p.y);
+
+        processRollEvents(hitPoints, event);
+
+        if (_currentHitSet && _currentHitSet.length > 0)
+        {
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.ITEM_CLICK,
+                                             _currentHitSet, event, this));
+        }
+        else
+        {
+        	dispatchEvent(new ChartEvent(ChartEvent.CHART_CLICK, event, this));
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function mouseDoubleClickHandler(event:MouseEvent):void
+    {
+        var p:Point = new Point(event.localX, event.localY);
+        p = globalToLocal(DisplayObject(event.target).localToGlobal(p));
+
+        var hitPoints:Array /* of HitData */ = findDataPoints(p.x, p.y);
+
+        processRollEvents(hitPoints, event);
+
+        if (_currentHitSet && _currentHitSet.length > 0)
+        {
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.ITEM_DOUBLE_CLICK,
+                                             _currentHitSet, event, this));
+        }
+        else
+        {
+            dispatchEvent(new ChartEvent(ChartEvent.CHART_DOUBLE_CLICK, event, this));
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function dataEffectEndHandler(event:EffectEvent):void
+    {
+        event.target.removeEventListener(EffectEvent.EFFECT_END,
+                                         dataEffectEndHandler);
+
+        if (chartState == ChartState.HIDING_DATA)
+            setChartState(ChartState.PREPARING_TO_SHOW_DATA);
+        else
+            setChartState(ChartState.NONE);
+
+        _transitionEffect = null;
+
+        invalidateDisplayList();
+    }
+
+    /**
+     *  @private
+     */
+    private function regionChangeHandler(event:RangeEvent):void
+    {
+        var bSelected:Boolean = true;
+        if (!_selectedSeries)
+            bSelected = false;
+        selectRectangleRegion(event.regionSelected,event.mouseEvent.ctrlKey || event.mouseEvent.shiftKey);
+        if ((bSelected || _selectedSeries) && !event.mouseEvent.buttonDown) // Fire the event only if the earlier or current selection is non-empty and if mouse is up
+            dispatchEvent(new ChartItemEvent(ChartItemEvent.CHANGE,null,event.mouseEvent,this));
+    }
+
+    /**
+     *  The default handler for the dragStart event.
+     *
+     *  @param event The DragEvent object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function dragStartHandler(event:DragEvent):void
+    {
+        if (event.isDefaultPrevented())
+            return;
+
+        var dragSource:DragSource = new DragSource();
+
+        addDragData(dragSource);
+
+        var proxyOrigin:Point = event.target.localToGlobal(
+						new Point(event.localX, event.localY));
+		proxyOrigin = globalToLocal(proxyOrigin);
+		var xOffset:Number = - (proxyOrigin.x - event.localX);
+		var yOffset:Number = - (proxyOrigin.y - event.localY);
+		DragManager.doDrag(this, dragSource, event, dragImage,
+                           xOffset, yOffset, 0.5, dragMoveEnabled);
+    }
+
+    /**
+     *  Handles events of type DragEvent.DRAG_ENTER. This method
+     *  determines if the DragSource object contains valid elements and uses
+     *  the showDropFeedback() method to set up the UI feedback.
+     *
+     *  @param event The DragEvent object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function dragEnterHandler(event:DragEvent):void
+    {
+        if (event.isDefaultPrevented())
+            return;
+
+        if (event.dragSource.hasFormat("chartitems"))
+        {
+            DragManager.acceptDragDrop(this);
+            DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE);
+            showDropFeedback(event);
+            return;
+        }
+
+        hideDropFeedback(event);
+
+        DragManager.showFeedback(DragManager.NONE);
+    }
+
+    /**
+     *  Handles events of type DragEvent.DRAG_OVER. This method
+     *  determines whether the DragSource object contains valid elements and uses
+     *  the showDropFeedback() method to set up the UI feeback.
+     *
+     *  @param event The DragEvent object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function dragOverHandler(event:DragEvent):void
+    {
+        if (event.isDefaultPrevented())
+            return;
+
+        if (event.dragSource.hasFormat("chartitems"))
+        {
+            DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE);
+            showDropFeedback(event);
+            return;
+        }
+
+        hideDropFeedback(event);
+
+        DragManager.showFeedback(DragManager.NONE);
+    }
+
+    /**
+     *  Handles events of type DragEvent.DRAG_EXIT. This method hides
+     *  the UI feeback by calling the hideDropFeedback() method.
+     *
+     *  @param event The DragEvent object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function dragExitHandler(event:DragEvent):void
+    {
+        if (event.isDefaultPrevented())
+            return;
+
+        hideDropFeedback(event);
+
+        DragManager.showFeedback(DragManager.NONE);
+    }
+
+    /**
+     *  Handles events of type DragEvent.DRAG_DROP. This method hides
+     *  the UI feeback by calling the hideDropFeedback() method.
+     *
+     *  @param event The DragEvent object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function dragDropHandler(event:DragEvent):void
+    {
+        if (event.isDefaultPrevented())
+            return;
+
+        hideDropFeedback(event);
+    }
+
+    /**
+     *  Handles events of type DragEvent.DRAG_COMPLETE. This method
+     *  removes the item from the data provider.
+     *
+     *  @param event The DragEvent object.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    protected function dragCompleteHandler(event:DragEvent):void
+    {
+       _mouseDown = false;
+       _mouseDownItem = null;
+       _mouseDownPoint = null;
+
+       if (event.isDefaultPrevented())
+            return;
+
+    }
+}
+
+}
+
+import mx.charts.HitData;
+import mx.core.IFlexDisplayObject;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Helper class: TipStack
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  @private
+ */
+class TipStack
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function TipStack()
+    {
+        super();
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    public var tips:Array /* of TipSPositionData */ = [];
+
+    /**
+     *  @private
+     */
+    public var height:Number;
+
+    /**
+     *  @private
+     */
+    public var gy:Number;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    public function merge(ts:TipStack, screenHeight:Number):void
+    {
+        tips = tips.concat(ts.tips);
+
+        var newHeight:Number = ts.gy + ts.height - gy;
+        gy = Math.max(0, gy - (gy + height - ts.gy) / 2);
+        if (gy + newHeight > screenHeight)
+            gy = Math.max(0, screenHeight - newHeight);
+        height = newHeight;
+    }
+
+    /**
+     *  @private
+     */
+    public function addTip(tip:TipPositionData, screenHeight:Number):void
+    {
+        tips.push(tip);
+
+        if (tips.length == 1)
+        {
+            gy = tip.py;
+            height = tip.height;
+        }
+        else if (tips.length == 2)
+        {
+            height += tip.height;
+            gy = Math.min(screenHeight - height,
+                 Math.max(0, (tips[0].gy + tips[1].gy) / 2) - height / 2);
+        }
+        else
+        {
+            height += tip.height;
+            gy = Math.min(screenHeight - height,
+                 Math.max(0, ((gy + height / 2) *
+                 (tips.length - 1) + tip.gy) / tips.length - height / 2));
+        }
+    }
+
+    /**
+     *  @private
+     */
+    public function positionY():void
+    {
+        var gy:Number = this.gy;
+        var n:int = tips.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var tipData:TipPositionData = tips[i];
+            tipData.py = gy;
+            gy += tipData.height;
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Helper class: TipPositionData
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  @private
+ */
+class TipPositionData
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function TipPositionData(tipInstance:IFlexDisplayObject,
+                                    hitData:HitData,
+                                    x:Number, y:Number,
+                                    gx:Number, gy:Number)
+    {
+        super();
+
+        tip = tipInstance;
+        hd = hitData;
+        this.x = x;
+        this.y = y;
+        this.gx = gx;
+        this.gy = gy;
+        this.width = tipInstance.measuredWidth;
+        this.height = tipInstance.measuredHeight+4;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    public var tip:IFlexDisplayObject;
+
+    /**
+     *  @private
+     */
+    public var hd:HitData;
+
+    /**
+     *  @private
+     */
+    public var x:Number;
+
+    /**
+     *  @private
+     */
+    public var y:Number;
+
+    /**
+     *  @private
+     */
+    public var gx:Number;
+
+    /**
+     *  @private
+     */
+    public var gy:Number;
+
+    /**
+     *  @private
+     */
+    public var px:Number;
+
+    /**
+     *  @private
+     */
+    public var py:Number;
+
+    /**
+     *  @private
+     */
+    public var width:Number;
+
+    /**
+     *  @private
+     */
+    public var height:Number;
+
+    /**
+     *  @private
+     */
+    public var isRight:Boolean;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Helper class: RangeEvent
+//
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * The RangeEvent class represents events that are specific
+ * to the Range Selection.
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+
+import flash.events.Event;
+import flash.events.MouseEvent;
+import mx.charts.HitData;
+import mx.charts.chartClasses.ChartBase;
+import flash.display.InteractiveObject;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+
+/**
+ *  @private
+*/
+
+class RangeEvent extends Event
+{
+    include "../../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+
+
+    /**
+     *  Event type constant; indicates that the rectangular selection region has changed
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+
+    public static const REGION_CHANGE:String = "regionChange"
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @param type The type of the event.
+     *
+     *  @param the rectangular region of selection
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function RangeEvent(type:String, rect:Rectangle, event:MouseEvent)
+    {
+        super(type);
+        this.regionSelected = rect;
+        this.mouseEvent = event;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  regionSelected
+    //----------------------------------
+
+    [Inspectable(environment="none")]
+
+    /**
+     *  A rectangular region that was drawn to select items.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var regionSelected:Rectangle;
+
+    //----------------------------------
+    //  mouseEvent
+    //----------------------------------
+    /**
+     *  Indicates whether ctrl key has been pressed or not.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public var mouseEvent:MouseEvent;
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: Event
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    override public function clone():Event
+    {
+        return new RangeEvent(type, regionSelected,mouseEvent);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Helper class: RangeSelector
+//
+////////////////////////////////////////////////////////////////////////////////
+import flash.display.*;
+import flash.geom.*;
+import mx.skins.ProgrammaticSkin
+
+/**
+ *  @private
+ */
+
+class RangeSelector extends ProgrammaticSkin
+{
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function RangeSelector()
+    {
+        super();
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods
+    //
+    //--------------------------------------------------------------------------
+
+    public function clear():void
+    {
+        var g:Graphics = graphics;
+        g.clear();
+    }
+
+    /**
+     *  @private
+     */
+    override protected function updateDisplayList(unscaledWidth:Number,
+                                                  unscaledHeight:Number):void
+    {
+        super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+
+        var g:Graphics = graphics;
+        g.clear();
+
+        g.moveTo(0,0);
+        g.beginFill(0xDAF1FF,0.5);
+        g.lineStyle(1,0x009DFF);
+        g.drawRect(0,0,width,height);
+        g.endFill();
+    }
+}