298 lines
7.3 KiB
ActionScript
Executable File
298 lines
7.3 KiB
ActionScript
Executable File
/*
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|