package flare.vis.legend {
import flare.display.RectSprite;
import flare.display.TextSprite;
import flare.scale.IScaleMap;
import flare.scale.Scale;
import flare.util.Colors;
import flare.util.Orientation;
import flare.util.Stats;
import flare.util.Vectors;
import flare.util.palette.ColorPalette;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.text.TextFormat;
/**
* A range in a continuous legend, consisting of a continuous
* visual scale and value labels. Legend ranges use a
* ColorPalette instance for creating a gradient of
* color values. If the stats property
* is set with the Stats object for a backing data
* variable, a histogram of values will also be drawn in the legend
* range. To draw only a histogram, set the palette
* property to null.
*/
public class LegendRange extends RectSprite implements IScaleMap
{
private var _dataField:String;
private var _scale:Scale;
private var _stats:Stats;
private var _palette:ColorPalette;
private var _matrix:Matrix = new Matrix();
private var _margin:Number = 5;
private var _labels:Sprite;
private var _fmt:TextFormat;
private var _labelMode:int = TextSprite.BITMAP;
private var _range:Shape;
private var _rs:Number = 20;
private var _borderColor:uint = 0xcccccc;
private var _histogramColor:uint = 0x888888;
private var _orient:String;
private var _vert:Boolean;
private var _rev:Boolean;
/** The data field described by this legend range. */
public function get dataField():String { return _dataField; }
/** Sprite containing the range's labels. */
public function get labels():Sprite { return _labels; }
/** Stats object describing the data range. */
public function get stats():Stats { return _stats; }
public function set stats(s:Stats):void { _stats = s; dirty(); }
/** Text format (font, size, style) of legend range labels. */
public function get labelTextFormat():TextFormat { return _fmt; }
public function set labelTextFormat(fmt:TextFormat):void {
_fmt = fmt; dirty();
}
/** TextFormat (font, size, style) of legend range labels. */
public function get labelTextMode():int { return _labelMode; }
public function set labelTextMode(mode:int):void {
_labelMode = mode; dirty();
}
/** Margin value for padding within the legend item. */
public function get margin():Number { return _margin; }
public function set margin(m:Number):void {
_margin = m; dirty();
}
/** The size of the range, this is either the width or height of
* the range, depending on the current orientation. */
public function get rangeSize():Number { return _rs; }
public function set rangeSize(s:Number):void { _rs = s; }
/** The color of the legend range border. */
public function get borderColor():uint { return _borderColor; }
public function set borderColor(c:uint):void {
if (c != _borderColor) { _borderColor = c; dirty(); }
}
/** The color of bars in a generated histogram. */
public function get histogramColor():uint { return _histogramColor; }
public function set histogramColor(c:uint):void {
if (c == _histogramColor) return;
_histogramColor = c;
if (_stats) dirty();
}
/** The desired orientation of this legend range. */
public function get orientation():String { return _orient; }
public function set orientation(o:String):void {
_orient = o;
_vert = Orientation.isVertical(o);
_rev = o==Orientation.RIGHT_TO_LEFT || o==Orientation.BOTTOM_TO_TOP;
dirty();
}
// --------------------------------------------------------------------
/**
* Creates a new LegendRange.
* @param dataField the data field described by this range
* @param palette the color palette for the data field
* @param scale the Scale instance mapping the data field to a visual
* variable
*/
public function LegendRange(dataField:String, scale:Scale,
palette:ColorPalette=null,
orientation:String=Orientation.LEFT_TO_RIGHT)
{
_dataField = dataField;
_palette = palette;
_scale = scale;
this.orientation = orientation;
addChild(_range = new Shape());
addChild(_labels = new Sprite());
_range.cacheAsBitmap = true;
}
// --------------------------------------------------------------------
// Lookup
/** @inheritDoc */
public function get x1():Number {
return _vert || !_rev ? _margin : _w-_margin;
}
/** @inheritDoc */
public function get x2():Number {
return _vert ? _margin+_rs : (_rev ? _margin : _w-_margin);
}
/** @inheritDoc */
public function get y1():Number {
return _vert && !_rev ? _h-_margin : _margin;
}
/** @inheritDoc */
public function get y2():Number {
return _vert ? (_rev ? _h-_margin : _margin) : _margin+_rs;
}
private var _bounds:Rectangle = new Rectangle();
/**
* Bounds for the visual range portion of this legend range.
* @return the bounds of the range display
*/
public function get bounds():Rectangle {
_bounds.x = x1;
_bounds.y = y1;
_bounds.width = x2 - x1;
_bounds.height = y2 - y1;
return _bounds;
}
/** @inheritDoc */
public function value(x:Number, y:Number, stayInBounds:Boolean=true):Object
{
var f:Number;
if (_vert) {
f = (y-_margin) / (_h - 2*_margin);
} else {
f = (x-_margin) / (_w - 2*_margin);
}
// correct bounds
if (stayInBounds) {
if (f < 0) f = 0;
if (f > 1) f = 1;
}
if (_rev) f = 1-f;
// lookup and return value
return _scale.lookup(f);
}
/** @inheritDoc */
public function X(val:Object):Number
{
return x1 + (_vert ? 0 : _scale.interpolate(val) * (x2 - x1));
}
/** @inheritDoc */
public function Y(val:Object):Number
{
return y1 + (_vert ? _scale.interpolate(val) * (y2-y1) : y1);
}
// --------------------------------------------------------------------
// Layout and Render
/**
* Update the labels shown by this legend range.
*/
public function updateLabels():void
{
var pts:Vector.