package flare.scale { import flare.util.Dates; import flare.util.Maths; /** * Scale for timelines represented using Date values. This * scale represents a linear, quantitative time line. The class attempts * to automatically configure date value labels based on the time span * between the earliest and latest date in the scale. The label formatting * pattern can also be manually set using the labelFormat * property. */ public class TimeScale extends Scale { private var _dmin : Date = new Date(0); private var _dmax : Date = new Date(0); private var _smin : Date; private var _smax : Date; private var _autofmt : Boolean = true; /** * Creates a new TimeScale. * @param min the minimum (earliest) date value * @param max the maximum (latest) date value * @param flush the flush flag for scale padding * @param labelFormat the formatting pattern for value labels */ public function TimeScale(min : Date = null, max : Date = null, flush : Boolean = false, labelFormat : String = null) { if (min) this.dataMin = min; if (max) this.dataMax = max; this.flush = flush; this.labelFormat = labelFormat; } /** @inheritDoc */ public override function get scaleType() : String { return ScaleType.TIME; } /** @inheritDoc */ public override function clone() : Scale { return new TimeScale(_dmin, _dmax, _flush, _format); } // -- Properties ------------------------------------------------------ /** @inheritDoc */ public override function set flush(val : Boolean) : void { _flush = val; updateScale(); } /** @inheritDoc */ public override function get labelFormat() : String { return (_autofmt ? null : super.labelFormat); } public override function set labelFormat(fmt : String) : void { if (fmt != null) { super.labelFormat = fmt; _autofmt = false; } else { _autofmt = true; updateScale(); } } /** @inheritDoc */ public override function get min() : Object { return dataMin; } public override function set min(o : Object) : void { dataMin = o as Date; } /** @inheritDoc */ public override function get max() : Object { return dataMax; } public override function set max(o : Object) : void { dataMax = o as Date } /** The minimum (earliest) Date value in the underlying data. * This property is the same as the minimum * property, but properly typed. */ public function get dataMin() : Date { return _dmin; } public function set dataMin(val : Date) : void { _dmin = val; updateScale(); } /** The maximum (latest) Date value in the underlying data. * This property is the same as the maximum * property, but properly typed. */ public function get dataMax() : Date { return _dmax; } public function set dataMax(val : Date) : void { _dmax = val; updateScale(); } /** The minimum (earliest) Date value in the scale. */ public function get scaleMin() : Date { return _smin; } /** The maximum (latest) Date value in the underlying data. */ public function get scaleMax() : Date { return _smax; } // -- Scale Methods --------------------------------------------------- /** @inheritDoc */ public override function interpolate(value : Object) : Number { var t : Number = value is Date ? (value as Date).time : Number(value); return Maths.invLinearInterp(t, _smin.time, _smax.time); } /** @inheritDoc */ public override function lookup(f : Number) : Object { var t : Number = Math.round(Maths.linearInterp(f, _smin.time, _smax.time)); return new Date(t); } /** * Updates the scale range when the data range is changed. */ protected function updateScale() : void { var span : int = Dates.timeSpan(_dmin, _dmax); if (_flush) { _smin = _dmin; _smax = _dmax; } else { _smin = Dates.roundTime(_dmin, span, false); _smax = Dates.roundTime(_dmax, span, true); } if (_autofmt) { super.labelFormat = formatString(span); } } /** * Determines the format string to be used based on a measure of * the time span covered by this scale. * @param span the time span covered by this scale. Should use the * format of the flare.util.Dates class. * @return the label formatting pattern */ protected function formatString(span : int) : String { if (span >= Dates.YEARS) { return "yyyy"; } else if (span == Dates.MONTHS) { return "MMM"; } else if (span == Dates.DAYS) { return "d"; } else if (span == Dates.HOURS) { return "h:mmt"; } else if (span == Dates.MINUTES) { return "h:mmt"; } else if (span == Dates.SECONDS) { return "h:mm:ss"; } else { return "s.fff"; } } /** @inheritDoc */ public override function values(num : int = -1) : Vector. { var a : Vector. = new Vector.(); var span : int = Dates.timeSpan(_dmin, _dmax); var step : Number = Dates.timeStep(span); var max : Number = _smax.time; var d : Date = _flush ? Dates.roundTime(scaleMin, span, true) : scaleMin; if (span < Dates.MONTHS) { for (var x : Number = _smin.time;x <= max;x += step) { a.push(new Date(x)); } } else if (span == Dates.MONTHS) { for (;d.time <= max;d = Dates.addMonths(d, 1)) { a.push(d); } } else { var y : int = int(step); for (;d.time <= max;d = Dates.addYears(d, y)) { a.push(d); } } return a; } } // end of class TimeScale }