/src/charts/as/com/yahoo/astra/fl/charts/Chart.as
ActionScript | 890 lines | 478 code | 95 blank | 317 comment | 62 complexity | bd4f8bc5a48774046a00bb8d135d33b3 MD5 | raw file
- package com.yahoo.astra.fl.charts
- {
- import com.yahoo.astra.fl.charts.events.ChartEvent;
- import com.yahoo.astra.fl.charts.legend.ILegend;
- import com.yahoo.astra.fl.charts.legend.LegendItemData;
- import com.yahoo.astra.fl.charts.series.ICategorySeries;
- import com.yahoo.astra.fl.charts.series.ILegendItemSeries;
- import com.yahoo.astra.fl.charts.series.ISeries;
- import com.yahoo.astra.fl.charts.series.ISeriesItemRenderer;
- import com.yahoo.astra.fl.utils.UIComponentUtil;
-
- import fl.core.InvalidationType;
- import fl.core.UIComponent;
-
- import flash.accessibility.AccessibilityProperties;
- import flash.display.DisplayObject;
- import flash.display.Sprite;
- import flash.events.Event;
- import flash.events.MouseEvent;
- import flash.geom.Point;
- import flash.text.TextFormat;
- import flash.text.TextFormatAlign;
- import flash.utils.getDefinitionByName;
- import flash.events.ErrorEvent;
-
- //--------------------------------------
- // Styles
- //--------------------------------------
-
- /**
- * The padding that separates the border of the component from its contents,
- * in pixels.
- *
- * @default 10
- */
- [Style(name="contentPadding", type="Number")]
-
- /**
- * Name of the class to use as the skin for the background and border of the
- * component.
- *
- * @default ChartBackgroundSkin
- */
- [Style(name="backgroundSkin", type="Class")]
-
- /**
- * The default colors for each series. These colors are used for markers,
- * in most cases, but they may apply to lines, fills, or other graphical
- * items.
- *
- * <p>An Array of values that correspond to series indices in the data
- * provider. If the number of values in the Array is less than the number
- * of series, then the next series will restart at index zero in the style
- * Array. If the value of this style is an empty Array, then each individual series
- * will use the default or modified value set on the series itself.</p>
- *
- * <p>Example: If the seriesColors style is equal to [0xffffff, 0x000000] and there
- * are three series in the chart's data provider, then the series at index 0
- * will have a color of 0xffffff, index 1 will have a color of 0x000000, and
- * index 2 will have a color of 0xffffff (starting over from the beginning).</p>
- *
- * @default [0x00b8bf, 0x8dd5e7, 0xedff9f, 0xffa928, 0xc0fff6, 0xd00050, 0xc6c6c6, 0xc3eafb, 0xfcffad, 0xcfff83, 0x444444, 0x4d95dd, 0xb8ebff, 0x60558f, 0x737d7e, 0xa64d9a, 0x8e9a9b, 0x803e77]
- */
- [Style(name="seriesColors", type="Array")]
-
- /**
- * The default size of the markers in pixels. The actual drawn size of the
- * markers could end up being different in some cases. For example, bar charts
- * and column charts display markers side-by-side, and a chart may need to make
- * the bars or columns smaller to fit within the required region.
- *
- * <p>An Array of values that correspond to series indices in the data
- * provider. If the number of values in the Array is less than the number
- * of series, then the next series will restart at index zero in the style
- * Array. If the value of this style is an empty Array, then each individual series
- * will use the default or modified value set on the series itself.</p>
- *
- * <p>Example: If the seriesMarkerSizes style is equal to [10, 15] and there
- * are three series in the chart's data provider, then the series at index 0
- * will have a marker size of 10, index 1 will have a marker size of 15, and
- * index 2 will have a marker size of 10 (starting over from the beginning).</p>
- *
- * @default []
- */
- [Style(name="seriesMarkerSizes", type="Array")]
-
- /**
- * An Array containing the default skin classes for each series. These classes
- * are used to instantiate the marker skins. The values may be fully-qualified
- * package and class strings or a reference to the classes themselves.
- *
- * <p>An Array of values that correspond to series indices in the data
- * provider. If the number of values in the Array is less than the number
- * of series, then the next series will restart at index zero in the style
- * Array. If the value of this style is an empty Array, then each individual series
- * will use the default or modified value set on the series itself.</p>
- *
- * <p>Example: If the seriesMarkerSkins style is equal to [CircleSkin, DiamondSkin] and there
- * are three series in the chart's data provider, then the series at index 0
- * will have a marker skin of CircleSkin, index 1 will have a marker skin of DiamondSkin, and
- * index 2 will have a marker skin of CircleSkin (starting over from the beginning).</p>
- *
- * @default []
- */
- [Style(name="seriesMarkerSkins", type="Array")]
-
- /**
- * The TextFormat object to use to render data tips.
- *
- * @default TextFormat("_sans", 11, 0x000000, false, false, false, '', '', TextFormatAlign.LEFT, 0, 0, 0, 0)
- */
- [Style(name="dataTipTextFormat", type="TextFormat")]
-
- /**
- * Name of the class to use as the skin for the background and border of the
- * chart's data tip.
- *
- * @default ChartDataTipBackground
- */
- [Style(name="dataTipBackgroundSkin", type="Class")]
-
- /**
- * If the datatip's content padding is customizable, it will use this value.
- * The padding that separates the border of the component from its contents,
- * in pixels.
- *
- * @default 6
- */
- [Style(name="dataTipContentPadding", type="Number")]
-
- /**
- * Determines if data changes should be displayed with animation.
- *
- * @default true
- */
- [Style(name="animationEnabled", type="Boolean")]
-
- /**
- * Indicates whether embedded font outlines are used to render the text
- * field. If this value is true, Flash Player renders the text field by
- * using embedded font outlines. If this value is false, Flash Player
- * renders the text field by using device fonts.
- *
- * If you set the embedFonts property to true for a text field, you must
- * specify a font for that text by using the font property of a TextFormat
- * object that is applied to the text field. If the specified font is not
- * embedded in the SWF file, the text is not displayed.
- *
- * @default false
- */
- [Style(name="embedFonts", type="Boolean")]
-
- /**
- * Functionality common to most charts. Generally, a <code>Chart</code> object
- * shouldn't be instantiated directly. Instead, a subclass with a concrete
- * implementation should be used. That subclass generally should implement the
- * <code>IPlotArea</code> interface.
- *
- * @author Josh Tynjala
- */
- public class Chart extends UIComponent
- {
-
- //--------------------------------------
- // Class Variables
- //--------------------------------------
-
- /**
- * @private
- */
- private static var defaultStyles:Object =
- {
- seriesMarkerSizes: null,
- seriesMarkerSkins: null,
- seriesColors:
- [
- 0x00b8bf, 0x8dd5e7, 0xedff9f, 0xffa928, 0xc0fff6, 0xd00050,
- 0xc6c6c6, 0xc3eafb, 0xfcffad, 0xcfff83, 0x444444, 0x4d95dd,
- 0xb8ebff, 0x60558f, 0x737d7e, 0xa64d9a, 0x8e9a9b, 0x803e77
- ],
- seriesBorderColors:[],
- seriesFillColors:[],
- seriesLineColors:[],
- seriesBorderAlphas:[1],
- seriesFillAlphas:[1],
- seriesLineAlphas:[1],
- contentPadding: 10,
- backgroundSkin: "ChartBackground",
- backgroundColor: 0xffffff,
- dataTipBackgroundSkin: "ChartDataTipBackground",
- dataTipContentPadding: 6,
- dataTipTextFormat: new TextFormat("_sans", 11, 0x000000, false, false, false, '', '', TextFormatAlign.LEFT, 0, 0, 0, 0),
- animationEnabled: true,
- embedFonts: false
- };
-
- /**
- * @private
- */
- private static const ALL_SERIES_STYLES:Object =
- {
- color: "seriesColors",
- markerSize: "seriesMarkerSizes",
- markerSkin: "seriesMarkerSkins",
- borderColor: "seriesBorderColors",
- fillColor: "seriesFillColors",
- lineColor: "seriesLineColors",
- borderAlpha: "seriesBorderAlphas",
- fillAlpha: "seriesFillAlphas",
- lineAlpha: "seriesLineAlphas"
- };
-
- /**
- * @private
- */
- private static const SHARED_SERIES_STYLES:Object =
- {
- animationEnabled: "animationEnabled"
- };
-
- private static const DATA_TIP_STYLES:Object =
- {
- backgroundSkin: "dataTipBackgroundSkin",
- contentPadding: "dataTipContentPadding",
- textFormat: "dataTipTextFormat",
- embedFonts: "embedFonts"
- };
-
- //--------------------------------------
- // Class Methods
- //--------------------------------------
-
- /**
- * @private
- * @copy fl.core.UIComponent#getStyleDefinition()
- */
- public static function getStyleDefinition():Object
- {
- return mergeStyles(defaultStyles, UIComponent.getStyleDefinition());
- }
-
- //--------------------------------------
- // Constructor
- //--------------------------------------
-
- /**
- * Constructor.
- */
- public function Chart()
- {
- super();
- this.accessibilityProperties = new AccessibilityProperties();
- this.accessibilityProperties.forceSimple = true;
- this.accessibilityProperties.description = "Chart";
- }
-
- //--------------------------------------
- // Variables and Properties
- //--------------------------------------
-
- /**
- * @private
- * The display object representing the chart background.
- */
- protected var background:DisplayObject;
-
- /**
- * @private
- * The area where series are drawn.
- */
- protected var content:Sprite;
-
- /**
- * @private
- * The mouse over data tip that displays information about an item on the chart.
- */
- protected var dataTip:DisplayObject;
-
- /**
- * @private
- * Storage for the data property. Saves a copy of the unmodified data.
- */
- private var _dataProvider:Object;
-
- /**
- * @private
- * Modified version of the stored data.
- */
- protected var series:Array = [];
-
- [Inspectable(type=Array)]
- /**
- * @copy com.yahoo.astra.fl.charts.IChart#dataProvider
- */
- public function get dataProvider():Object
- {
- return this.series;
- }
-
- /**
- * @private
- */
- public function set dataProvider(value:Object):void
- {
- if(this._dataProvider != value)
- {
- this._dataProvider = value;
- this.invalidate(InvalidationType.DATA);
- }
- }
-
- /**
- * @private
- * Storage for the defaultSeriesType property.
- */
- private var _defaultSeriesType:Class;
-
- /**
- * When raw data (like an Array of Numbers) is encountered where an
- * ISeries instance is expected, it will be converted to this default
- * type. Accepts either a Class instance or a String referencing a
- * fully-qualified class name.
- */
- public function get defaultSeriesType():Object
- {
- return this._defaultSeriesType;
- }
-
- /**
- * @private
- */
- public function set defaultSeriesType(value:Object):void
- {
- if(!value) return;
- var classDefinition:Class = null;
- if(value is Class)
- {
- classDefinition = value as Class;
- }
- else
- {
- // borrowed from fl.core.UIComponent#getDisplayObjectInstance()
- try
- {
- classDefinition = getDefinitionByName(value.toString()) as Class;
- }
- catch(e:Error)
- {
- try
- {
- classDefinition = this.loaderInfo.applicationDomain.getDefinition(value.toString()) as Class;
- }
- catch (e:Error)
- {
- // Nothing
- }
- }
- }
-
- this._defaultSeriesType = classDefinition;
- //no need to redraw.
- //if the series have already been created, the user probably wanted it that way.
- //we have no way to tell if the user chose a particular series' type or not anyway.
- }
-
- private var _lastDataTipRenderer:ISeriesItemRenderer;
-
- /**
- * @private
- * Storage for the dataTipFunction property.
- */
- private var _dataTipFunction:Function = defaultDataTipFunction;
-
- /**
- * If defined, the chart will call the input function to determine the
- * text displayed in the chart's data tip. The function uses the following
- * signature:
- *
- * <p><code>function dataTipFunction(item:Object, index:int, series:ISeries):String</code></p>
- */
- public function get dataTipFunction():Function
- {
- return this._dataTipFunction;
- }
-
- /**
- * @private
- */
- public function set dataTipFunction(value:Function):void
- {
- this._dataTipFunction = value;
- }
-
- /**
- * @private
- * Storage for the legend property.
- */
- private var _legend:ILegend;
-
- /**
- * The component that will display a human-readable legend for the chart.
- */
- public function get legend():ILegend
- {
- return this._legend;
- }
-
- /**
- * @private
- */
- public function set legend(value:ILegend):void
- {
- this._legend = value;
- this.invalidate();
- }
-
- /**
- * @private
- * Storage for legendLabelFunction
- */
- private var _legendLabelFunction:Function;
-
- /**
- * If defined, the chart will call the input function to determine the text displayed in
- * in the chart's legend.
- */
- public function get legendLabelFunction():Function
- {
- return this._legendLabelFunction;
- }
-
- /**
- * @private
- */
- public function set legendLabelFunction(value:Function):void
- {
- this._legendLabelFunction = value;
- }
-
- //--------------------------------------
- // Public Methods
- //--------------------------------------
-
- /**
- * Returns the index within this plot area of the input ISeries object.
- *
- * @param series a series that is displayed in this plot area.
- * @return the index of the input series
- */
- public function seriesToIndex(series:ISeries):int
- {
- return this.series.indexOf(series);
- }
-
- /**
- * Returns the ISeries object at the specified index.
- *
- * @param index the index of the series to return
- * @return the series that appears at the input index or null if out of bounds
- */
- public function indexToSeries(index:int):ISeries
- {
- if(index < 0 || index >= this.series.length) return null;
- return this.series[index];
- }
-
- //--------------------------------------
- // Protected Methods
- //--------------------------------------
-
- /**
- * @private
- */
- override protected function configUI():void
- {
- super.width = 400;
- super.height = 300;
-
- super.configUI();
-
- this.content = new Sprite();
- this.addChild(this.content);
-
- this.dataTip = new DataTipRenderer();
- this.dataTip.visible = false;
- this.addChild(this.dataTip);
- }
-
- /**
- * @private
- */
- override protected function draw():void
- {
- var dataInvalid:Boolean = this.isInvalid(InvalidationType.DATA);
- var stylesInvalid:Boolean = this.isInvalid(InvalidationType.STYLES);
- var sizeInvalid:Boolean = this.isInvalid(InvalidationType.SIZE);
-
- if(stylesInvalid || dataInvalid)
- {
- this.refreshSeries();
- }
-
- //update the background if needed
- if(stylesInvalid)
- {
- if(this.background)
- {
- this.removeChild(this.background);
- }
- var skinClass:Object = this.getStyleValue("backgroundSkin");
- this.background = UIComponentUtil.getDisplayObjectInstance(this, skinClass);
- this.addChildAt(this.background, 0);
- }
-
- if(this.background && (stylesInvalid || sizeInvalid))
- {
- this.background.width = this.width;
- this.background.height = this.height;
-
- //force the background to redraw if it is a UIComponent
- if(this.background is UIComponent)
- {
- (this.background as UIComponent).drawNow();
- }
- }
-
- if(this.dataTip is UIComponent)
- {
- var dataTip:UIComponent = UIComponent(this.dataTip);
- this.copyStylesToChild(dataTip, DATA_TIP_STYLES);
- dataTip.drawNow();
- }
-
- super.draw();
- }
-
- /**
- * Analyzes the input data and smartly converts it to the correct ISeries type
- * required for drawing. Adds new ISeries objects to the display list and removes
- * unused series objects that no longer need to be drawn.
- */
- protected function refreshSeries():void
- {
- var modifiedData:Object = this._dataProvider;
-
- //loop through each series and convert it to the correct data type
- if(modifiedData is Array)
- {
- var arrayData:Array = (modifiedData as Array).concat();
- var seriesCount:int = arrayData.length;
- var foundIncompatibleData:Boolean = false;
- for(var i:int = 0; i < seriesCount; i++)
- {
- var currentItem:Object = arrayData[i];
- if(currentItem is Array || currentItem is XMLList)
- {
- var itemSeries:ISeries = new this.defaultSeriesType();
- if(currentItem is Array)
- {
- itemSeries.dataProvider = (currentItem as Array).concat();
- }
- else if(currentItem is XMLList)
- {
- itemSeries.dataProvider = (currentItem as XMLList).copy();
- }
- arrayData[i] = itemSeries;
- }
- else if(!(currentItem is ISeries))
- {
- //we only support Array, XMLList, and ISeries
- //anything else means that we should restore the original data
- var originalData:Array = (modifiedData as Array).concat();
- modifiedData = new this.defaultSeriesType(originalData);
- foundIncompatibleData = true;
- break;
- }
- }
- if(!foundIncompatibleData)
- {
- modifiedData = arrayData;
- }
- }
-
- //attempt to turn a string into XML
- if(modifiedData is String)
- {
- try
- {
- modifiedData = new XML(modifiedData);
- }
- catch(error:Error)
- {
- //this isn't a valid xml string, so ignore it
- return;
- }
- }
-
- //we need an XMLList, so get the elements
- if(modifiedData is XML)
- {
- modifiedData = (modifiedData as XML).elements();
- }
-
- //convert the XMLList to a series
- if(modifiedData is XMLList)
- {
- modifiedData = new this.defaultSeriesType(modifiedData);
- }
-
- //we should have an ISeries object by now, so put it in an Array
- if(modifiedData is ISeries)
- {
- //if the main data is a series, put it in an array
- modifiedData = [modifiedData];
- }
-
- //if it's not an array, we have bad data, so ignore it
- if(!(modifiedData is Array))
- {
- return;
- }
-
- arrayData = modifiedData as Array;
-
- seriesCount = this.series.length;
- for(i = 0; i < seriesCount; i++)
- {
- var currentSeries:ISeries = this.series[i] as ISeries;
- if(arrayData.indexOf(currentSeries) < 0)
- {
- //if the series no longer exists, remove it from the display list and stop listening to it
- this.content.removeChild(DisplayObject(currentSeries));
- currentSeries.removeEventListener("dataChange", seriesDataChangeHandler);
- currentSeries.removeEventListener(ChartEvent.ITEM_ROLL_OVER, chartItemRollOver);
- currentSeries.removeEventListener(ChartEvent.ITEM_ROLL_OUT, chartItemRollOut);
- currentSeries.chart = null;
- }
- }
-
- //rebuild the series Array
- this.series = [];
- seriesCount = arrayData.length;
- for(i = 0; i < seriesCount; i++)
- {
- currentSeries = arrayData[i] as ISeries;
- this.series.push(currentSeries);
- if(!this.contains(DisplayObject(currentSeries)))
- {
- //if this is a new series, add it to the display list and listen for events
- currentSeries.addEventListener("dataChange", seriesDataChangeHandler, false, 0, true);
- currentSeries.addEventListener(ChartEvent.ITEM_ROLL_OVER, chartItemRollOver, false, 0, true);
- currentSeries.addEventListener(ChartEvent.ITEM_ROLL_OUT, chartItemRollOut, false, 0, true);
- currentSeries.chart = this;
- this.content.addChild(DisplayObject(currentSeries));
- }
-
- DisplayObject(currentSeries).x = 0;
- DisplayObject(currentSeries).y = 0;
-
- //make sure the series are displayed in the correct order
- this.content.setChildIndex(DisplayObject(currentSeries), this.content.numChildren - 1);
-
- //update the series styles
- this.copyStylesToSeries(currentSeries, ALL_SERIES_STYLES);
- if(currentSeries is UIComponent)
- {
- this.copyStylesToChild(UIComponent(currentSeries), SHARED_SERIES_STYLES);
- }
- }
- }
-
- /**
- * @private
- * Refreshes the legend's data provider.
- */
- protected function updateLegend():void
- {
- if(!this.legend) return;
-
- var legendData:Array = [];
- var seriesCount:int = this.series.length;
- for(var i:int = 0; i < seriesCount; i++)
- {
- var series:ISeries = ISeries(this.series[i]);
- if(series is ILegendItemSeries)
- {
- if(!(series as ILegendItemSeries).showInLegend) continue;
- var itemData:LegendItemData = ILegendItemSeries(series).createLegendItemData();
- itemData.label = itemData.label ? itemData.label : i.toString();
- if(series.legendLabelFunction != null && series.legendLabelFunction is Function)
- {
- try
- {
- itemData.label = series.legendLabelFunction(itemData.label);
- }
- catch(e:Error)
- {
- var message:String = "There is an error in the series level legendLabelFunction.";
- this.dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, message));
- }
- }
- else if(this.legendLabelFunction != null && this.legendLabelFunction is Function)
- {
- try
- {
- message = "There is an error in the legendLabelFunction.";
- itemData.label = this.legendLabelFunction(itemData.label);
- }
- catch(e:Error)
- {
- this.dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, message));
- }
- }
- legendData.push(itemData);
- }
- else if(series is ICategorySeries)
- {
- legendData = legendData.concat(ICategorySeries(series).createLegendItemData());
- }
- }
-
- this.legend.dataProvider = legendData;
-
- if(UIComponent.inCallLaterPhase)
- {
- UIComponent(this.legend).drawNow();
- }
- }
-
- /**
- * @private
- * Tranfers the chart's styles to the ISeries components it contains. These styles
- * must be of the type Array, and the series index determines the index of the value
- * to use from that Array. If the chart contains more ISeries components than there
- * are values in the Array, the indices are reused starting from zero.
- */
- protected function copyStylesToSeries(child:ISeries, styleMap:Object):void
- {
- var index:int = this.series.indexOf(child);
- var childComponent:UIComponent = child as UIComponent;
- for(var n:String in styleMap)
- {
- var styleValues:Array = this.getStyleValue(styleMap[n]) as Array;
-
- //if it doesn't exist, ignore it and go with the defaults for this series
- if(styleValues == null || styleValues.length == 0) continue;
- childComponent.setStyle(n, styleValues[index % styleValues.length])
- }
- }
-
- /**
- * @private
- */
- protected function defaultDataTipFunction(item:Object, index:int, series:ISeries):String
- {
- if(series.displayName)
- {
- return series.displayName;
- }
- return "";
- }
-
- /**
- * @private
- * Passes data to the data tip.
- */
- protected function refreshDataTip():void
- {
- var item:Object = this._lastDataTipRenderer.data;
- var series:ISeries = this._lastDataTipRenderer.series;
- var index:int = series.itemRendererToIndex(this._lastDataTipRenderer);
-
- var dataTipText:String = "";
- if(series.dataTipFunction != null)
- {
- try
- {
- dataTipText = series.dataTipFunction(item, index, series);
- }
- catch(e:Error)
- {
- var message:String = "There is an error in your series level dataTipFunction";
- this.dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, message));
- }
- }
- else if(this.dataTipFunction != null)
- {
- try
- {
- dataTipText = this.dataTipFunction(item, index, series);
- }
- catch(e:Error)
- {
- message = "There is an error in your dataTipFunction";
- this.dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, message));
- }
- }
-
- var dataTipRenderer:IDataTipRenderer = this.dataTip as IDataTipRenderer;
- dataTipRenderer.text = dataTipText;
- dataTipRenderer.data = item;
-
- this.setChildIndex(this.dataTip, this.numChildren - 1);
- if(this.dataTip is UIComponent)
- {
- UIComponent(this.dataTip).drawNow();
- }
- }
-
- //--------------------------------------
- // Protected Event Handlers
- //--------------------------------------
-
- /**
- * @private
- * Display the data tip when the user moves the mouse over a chart marker.
- */
- protected function chartItemRollOver(event:ChartEvent):void
- {
- this._lastDataTipRenderer = event.itemRenderer;
- this.refreshDataTip();
-
- var position:Point = this.mousePositionToDataTipPosition();
- this.dataTip.x = position.x;
- this.dataTip.y = position.y;
- this.dataTip.visible = true;
-
- this.stage.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false, 0 ,true);
- }
-
- /**
- * @private
- * Hide the data tip when the user moves the mouse off a chart marker.
- */
- protected function chartItemRollOut(event:ChartEvent):void
- {
- this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler);
- this.dataTip.visible = false;
- }
-
- //--------------------------------------
- // Private Methods
- //--------------------------------------
-
- /**
- * @private
- * Determines the position for the data tip based on the mouse position
- * and the bounds of the chart. Attempts to keep the data tip within the
- * chart bounds so that it isn't hidden by any other display objects.
- */
- private function mousePositionToDataTipPosition():Point
- {
- var position:Point = new Point();
- position.x = this.mouseX + 2;
- position.x = Math.min(this.width - this.dataTip.width, position.x);
- position.y = this.mouseY - this.dataTip.height - 2;
- position.y = Math.max(0, position.y);
- return position;
- }
-
- //--------------------------------------
- // Private Event Handlers
- //--------------------------------------
-
- /**
- * @private
- * The plot area needs to redraw the axes if series data changes.
- */
- private function seriesDataChangeHandler(event:Event):void
- {
- this.invalidate(InvalidationType.DATA);
- if(this.dataTip.visible)
- {
- this.refreshDataTip();
- }
- }
-
- /**
- * @private
- * Make the data tip follow the mouse.
- */
- private function stageMouseMoveHandler(event:MouseEvent):void
- {
- var position:Point = this.mousePositionToDataTipPosition();
- this.dataTip.x = position.x;
- this.dataTip.y = position.y;
- }
-
- }
- }