first commit
This commit is contained in:
33
com/yahoo/astra/fl/charts/legend/ILegend.as
Executable file
33
com/yahoo/astra/fl/charts/legend/ILegend.as
Executable file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.charts.legend
|
||||
{
|
||||
/**
|
||||
* Properties required by a chart's legend.
|
||||
*
|
||||
* @see com.yahoo.astra.fl.charts.Chart
|
||||
*
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public interface ILegend
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* An Array of LegendItemData objects.
|
||||
*
|
||||
* @see com.yahoo.astra.fl.charts.legend.LegendItemData
|
||||
*/
|
||||
function get dataProvider():Array
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function set dataProvider(value:Array):void;
|
||||
}
|
||||
}
|
297
com/yahoo/astra/fl/charts/legend/Legend.as
Executable file
297
com/yahoo/astra/fl/charts/legend/Legend.as
Executable file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.charts.legend
|
||||
{
|
||||
import com.yahoo.astra.fl.utils.UIComponentUtil;
|
||||
import com.yahoo.astra.layout.modes.BoxLayout;
|
||||
|
||||
import fl.core.InvalidationType;
|
||||
import fl.core.UIComponent;
|
||||
import fl.events.ComponentEvent;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.geom.Rectangle;
|
||||
|
||||
//--------------------------------------
|
||||
// Styles
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* The padding that separates the border of the component from its contents,
|
||||
* in pixels.
|
||||
*
|
||||
* @default 6
|
||||
*/
|
||||
[Style(name="contentPadding", type="Number")]
|
||||
|
||||
/**
|
||||
* The spacing that separates the each legend item.
|
||||
*
|
||||
* @default 6
|
||||
*/
|
||||
[Style(name="gap", type="Number")]
|
||||
|
||||
/**
|
||||
* The DisplayObject subclass used to display the background.
|
||||
*/
|
||||
[Style(name="backgroundSkin", type="Class")]
|
||||
|
||||
/**
|
||||
* 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")]
|
||||
|
||||
/**
|
||||
* Provides a visual reference for the series in a Chart component.
|
||||
*
|
||||
* @see com.yahoo.astra.fl.charts.Chart
|
||||
* @see com.yahoo.astra.fl.charts.legend.LegendItem
|
||||
*
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class Legend extends UIComponent implements ILegend
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Static Variables
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private static var defaultStyles:Object =
|
||||
{
|
||||
backgroundSkin: "ChartLegendBackground",
|
||||
contentPadding: 6,
|
||||
direction: "vertical",
|
||||
gap: 6,
|
||||
embedFonts: false
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Styles to pass to the LegendItems
|
||||
*/
|
||||
private static const ITEM_STYLES:Object =
|
||||
{
|
||||
textFormat: "textFormat",
|
||||
embedFonts: "embedFonts"
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
// Static Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @copy fl.core.UIComponent#getStyleDefinition()
|
||||
*/
|
||||
public static function getStyleDefinition():Object
|
||||
{
|
||||
return mergeStyles(defaultStyles, UIComponent.getStyleDefinition());
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function Legend()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The background skin.
|
||||
*/
|
||||
protected var background:DisplayObject;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The legend items displayed in this Legend.
|
||||
*/
|
||||
protected var legendItems:Array = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Caches LegendItems for reuse when redrawing the Legend.
|
||||
*/
|
||||
private var _legendItemCache:Array;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the dataProvider property.
|
||||
*/
|
||||
private var _dataProvider:Array = [];
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function get dataProvider():Array
|
||||
{
|
||||
return this._dataProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set dataProvider(value:Array):void
|
||||
{
|
||||
this._dataProvider = value;
|
||||
this.invalidate(InvalidationType.DATA);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
var dataInvalid:Boolean = this.isInvalid(InvalidationType.DATA);
|
||||
var stylesInvalid:Boolean = this.isInvalid(InvalidationType.STYLES);
|
||||
|
||||
super.draw();
|
||||
|
||||
if(stylesInvalid)
|
||||
{
|
||||
if(this.background)
|
||||
{
|
||||
this.removeChild(this.background);
|
||||
this.background = null;
|
||||
}
|
||||
var skinClass:Object = this.getStyleValue("backgroundSkin");
|
||||
this.background = UIComponentUtil.getDisplayObjectInstance(this, skinClass);
|
||||
this.addChildAt(this.background, 0);
|
||||
}
|
||||
|
||||
if(dataInvalid && this.dataProvider)
|
||||
{
|
||||
this.createCache();
|
||||
this.updateLegendItems();
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
this.layoutItems();
|
||||
|
||||
if(this.background)
|
||||
{
|
||||
this.background.width = this._width;
|
||||
this.background.height = this._height;
|
||||
|
||||
if(this.background is UIComponent)
|
||||
{
|
||||
UIComponent(this.background).drawNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Loops through the data provider and displays a LegendItem
|
||||
* for each item.
|
||||
*/
|
||||
protected function updateLegendItems():void
|
||||
{
|
||||
var itemCount:int = this.dataProvider.length;
|
||||
for(var i:int = 0; i < itemCount; i++)
|
||||
{
|
||||
var legendItem:LegendItem = this.getItem();
|
||||
legendItem.data = LegendItemData(dataProvider[i]);
|
||||
this.copyStylesToChild(legendItem, ITEM_STYLES);
|
||||
legendItem.drawNow();
|
||||
this.legendItems.push(legendItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Standard renderer caching system.
|
||||
*/
|
||||
protected function createCache():void
|
||||
{
|
||||
this._legendItemCache = this.legendItems.concat();
|
||||
this.legendItems = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Either returns an old renderer from the cache or creates a new one.
|
||||
*/
|
||||
protected function getItem():LegendItem
|
||||
{
|
||||
if(this._legendItemCache.length > 0)
|
||||
{
|
||||
return this._legendItemCache.shift() as LegendItem;
|
||||
}
|
||||
var legendItem:LegendItem = new LegendItem();
|
||||
this.addChild(legendItem);
|
||||
return legendItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Clears any unused renderers from the cache.
|
||||
*/
|
||||
protected function clearCache():void
|
||||
{
|
||||
var cacheLength:int = this._legendItemCache.length;
|
||||
for(var i:int = 0; i < cacheLength; i++)
|
||||
{
|
||||
var legendItem:LegendItem = this._legendItemCache.pop() as LegendItem;
|
||||
this.removeChild(legendItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Positions the LegendItems.
|
||||
*/
|
||||
protected function layoutItems():void
|
||||
{
|
||||
var oldWidth:Number = this._width;
|
||||
var oldHeight:Number = this._height;
|
||||
|
||||
var contentPadding:Number = this.getStyleValue("contentPadding") as Number;
|
||||
var direction:String = this.getStyleValue("direction") as String;
|
||||
var gap:Number = this.getStyleValue("gap") as Number;
|
||||
|
||||
var layout:BoxLayout = new BoxLayout();
|
||||
layout.verticalGap = layout.horizontalGap = gap;
|
||||
layout.direction = direction;
|
||||
layout.paddingTop = layout.paddingRight = layout.paddingBottom = layout.paddingLeft = contentPadding
|
||||
var bounds:Rectangle = layout.layoutObjects(this.legendItems, new Rectangle(0, 0, this.width, this.height));
|
||||
|
||||
this._width = bounds.width;
|
||||
this._height = bounds.height;
|
||||
|
||||
//if the size has changed, dispatch a resize event
|
||||
if(this._width != oldWidth || this._height != oldHeight)
|
||||
{
|
||||
this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
226
com/yahoo/astra/fl/charts/legend/LegendItem.as
Executable file
226
com/yahoo/astra/fl/charts/legend/LegendItem.as
Executable file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.charts.legend
|
||||
{
|
||||
import com.yahoo.astra.fl.charts.events.LegendEvent;
|
||||
import com.yahoo.astra.fl.charts.series.ISeriesItemRenderer;
|
||||
import com.yahoo.astra.fl.charts.series.SeriesItemRenderer;
|
||||
|
||||
import fl.core.InvalidationType;
|
||||
import fl.core.UIComponent;
|
||||
import fl.events.ComponentEvent;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.display.InteractiveObject;
|
||||
import flash.display.Sprite;
|
||||
import flash.events.MouseEvent;
|
||||
import flash.text.TextField;
|
||||
import flash.text.TextFieldAutoSize;
|
||||
import flash.text.TextFormat;
|
||||
|
||||
/**
|
||||
* An item displayed in a chart's Legend.
|
||||
*
|
||||
* @see com.yahoo.astra.fl.charts.legend.Legend
|
||||
*
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class LegendItem extends UIComponent
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Class Variables
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private static var defaultStyles:Object =
|
||||
{
|
||||
markerSkin: Sprite,
|
||||
horizontalSpacing: 3,
|
||||
embedFonts: false
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
// Class Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @copy fl.core.UIComponent#getStyleDefinition()
|
||||
*/
|
||||
public static function getStyleDefinition():Object
|
||||
{
|
||||
return mergeStyles(defaultStyles, UIComponent.getStyleDefinition());
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function LegendItem()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The marker displayed in this LegendItem.
|
||||
*/
|
||||
protected var marker:ISeriesItemRenderer;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* The label displayed in this LegendItem.
|
||||
*/
|
||||
protected var textField:TextField;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Storage for the data property.
|
||||
*/
|
||||
private var _data:LegendItemData;
|
||||
|
||||
/**
|
||||
* The data used to display the legend item.
|
||||
*/
|
||||
public function get data():LegendItemData
|
||||
{
|
||||
return this._data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function set data(value:LegendItemData):void
|
||||
{
|
||||
if(this._data != value)
|
||||
{
|
||||
this._data = value;
|
||||
this.invalidate(InvalidationType.DATA);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Protected Methods
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function configUI():void
|
||||
{
|
||||
super.configUI();
|
||||
|
||||
if(!this.marker)
|
||||
{
|
||||
this.marker = new SeriesItemRenderer();
|
||||
InteractiveObject(this.marker).doubleClickEnabled = true;
|
||||
this.marker.addEventListener(MouseEvent.CLICK, markerMouseEventHandler);
|
||||
this.marker.addEventListener(MouseEvent.DOUBLE_CLICK, markerMouseEventHandler);
|
||||
this.marker.addEventListener(MouseEvent.ROLL_OVER, markerMouseEventHandler);
|
||||
this.marker.addEventListener(MouseEvent.ROLL_OUT, markerMouseEventHandler);
|
||||
this.addChild(DisplayObject(this.marker));
|
||||
}
|
||||
|
||||
if(!this.textField)
|
||||
{
|
||||
this.textField = new TextField();
|
||||
this.textField.autoSize = TextFieldAutoSize.LEFT;
|
||||
this.addChild(this.textField);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override protected function draw():void
|
||||
{
|
||||
var oldWidth:Number = this.width;
|
||||
var oldHeight:Number = this.height;
|
||||
|
||||
var dataInvalid:Boolean = this.isInvalid(InvalidationType.DATA);
|
||||
var stylesInvalid:Boolean = this.isInvalid(InvalidationType.STYLES);
|
||||
|
||||
if(stylesInvalid)
|
||||
{
|
||||
if(this.marker)
|
||||
{
|
||||
UIComponent(this.marker).setStyle("skin", this.data.markerSkin);
|
||||
UIComponent(this.marker).setStyle("fillColor", this.data.fillColor);
|
||||
UIComponent(this.marker).setStyle("borderColor", this.data.borderColor);
|
||||
UIComponent(this.marker).setStyle("fillAlpha", this.data.fillAlpha);
|
||||
UIComponent(this.marker).setStyle("borderAlpha", this.data.borderAlpha);
|
||||
}
|
||||
|
||||
var textFormat:TextFormat = this.getStyleValue("textFormat") as TextFormat;
|
||||
var embedFonts:Boolean = this.getStyleValue("embedFonts") as Boolean;
|
||||
this.textField.setTextFormat(textFormat); //set format for existing text
|
||||
this.textField.defaultTextFormat = textFormat; //set format for future text
|
||||
this.textField.embedFonts = embedFonts;
|
||||
}
|
||||
|
||||
if(dataInvalid)
|
||||
{
|
||||
this.textField.text = this.data.label ? this.data.label : " "; //space used for height calculation if no data
|
||||
}
|
||||
|
||||
//position children
|
||||
var horizontalSpacing:Number = this.getStyleValue("horizontalSpacing") as Number;
|
||||
var xPosition:Number = 0;
|
||||
if(this.marker)
|
||||
{
|
||||
var marker:UIComponent = UIComponent(this.marker);
|
||||
marker.width = marker.height = this.textField.textHeight;
|
||||
marker.y = (this.textField.height - this.textField.textHeight) / 2;
|
||||
marker.drawNow();
|
||||
xPosition = marker.width + horizontalSpacing;
|
||||
}
|
||||
this.textField.x = xPosition;
|
||||
|
||||
this._width = this.textField.x + this.textField.width;
|
||||
this._height = this.textField.height;
|
||||
|
||||
if(oldWidth != this._width || oldHeight != this._height)
|
||||
{
|
||||
this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
|
||||
}
|
||||
|
||||
super.draw();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Dispatch events when the user interacts with the marker.
|
||||
*/
|
||||
protected function markerMouseEventHandler(event:MouseEvent):void
|
||||
{
|
||||
var type:String = LegendEvent.LEGEND_MARKER_CLICK;
|
||||
switch(event.type)
|
||||
{
|
||||
case MouseEvent.DOUBLE_CLICK:
|
||||
type = LegendEvent.LEGEND_MARKER_DOUBLE_CLICK;
|
||||
break;
|
||||
case MouseEvent.ROLL_OVER:
|
||||
type = LegendEvent.LEGEND_MARKER_ROLL_OVER;
|
||||
break;
|
||||
case MouseEvent.ROLL_OUT:
|
||||
type = LegendEvent.LEGEND_MARKER_ROLL_OUT;
|
||||
break;
|
||||
}
|
||||
|
||||
this.dispatchEvent(new LegendEvent(type, this.parent.getChildIndex(this) + 1, true, false));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
71
com/yahoo/astra/fl/charts/legend/LegendItemData.as
Executable file
71
com/yahoo/astra/fl/charts/legend/LegendItemData.as
Executable file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||||
*/
|
||||
package com.yahoo.astra.fl.charts.legend
|
||||
{
|
||||
import flash.display.Shape;
|
||||
|
||||
/**
|
||||
* @author Josh Tynjala
|
||||
*/
|
||||
public class LegendItemData
|
||||
{
|
||||
|
||||
//--------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param label The text to display on the LegendItem.
|
||||
* @param markerSkin The skin to use with the marker on the LegendItem.
|
||||
* @param fillColor The base color (possibly) used by the marker.
|
||||
*/
|
||||
public function LegendItemData(label:String = "", markerSkin:Object = null, fillColor:uint = 0x000000, fillAlpha:Number = 1, borderColor:uint = 0x000000, borderAlpha:Number = 1)
|
||||
{
|
||||
this.label = label;
|
||||
this.markerSkin = markerSkin ? markerSkin : Shape;
|
||||
this.fillColor = fillColor;
|
||||
this.fillAlpha = fillAlpha;
|
||||
this.borderColor = borderColor;
|
||||
this.borderAlpha = borderAlpha;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Properties
|
||||
//--------------------------------------
|
||||
|
||||
/**
|
||||
* The text to display on the LegendItem.
|
||||
*/
|
||||
public var label:String;
|
||||
|
||||
/**
|
||||
* The skin to use for the marker on the LegendItem.
|
||||
*/
|
||||
public var markerSkin:Object;
|
||||
|
||||
/**
|
||||
* The base color (possibly) used by the marker fill.
|
||||
*/
|
||||
public var fillColor:uint;
|
||||
|
||||
/**
|
||||
* The alpha value used by the marker fill.
|
||||
*/
|
||||
public var fillAlpha:Number;
|
||||
|
||||
/**
|
||||
* The base color used by the marker border.
|
||||
*/
|
||||
public var borderColor:uint;
|
||||
|
||||
/**
|
||||
* The alpha value used by the marker border.
|
||||
*/
|
||||
public var borderAlpha:Number;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user