[Ovirt-devel] Re: [PATCH server] Add time range and data type selection to flexchart.
Steve Linabery
slinabery at redhat.com
Thu Nov 20 05:10:21 UTC 2008
Gaah! Just noticed that I broke the date display somehow while editing out whitespace, etc. Revision 1st thing in AM.
Thanks,
Steve
On Wed, Nov 19, 2008 at 10:12:04PM -0600, Steve Linabery wrote:
> Also
> -change color scheme to match tallen prototype pallette
> -change SingleBar elements to dynamically resized Canvas objects instead of HBox objects
> -add new route to accept second-resolution timestamps for time range selection
> ---
> src/app/controllers/graph_controller.rb | 59 ++++-
> src/app/util/stats/StatsTypes.rb | 8 +-
> src/app/views/graph/history_graphs.rhtml | 2 +-
> src/config/routes.rb | 1 +
> src/flexchart/flexchart.mxml | 12 +-
> src/flexchart/org/ovirt/ApplicationBus.as | 39 ++++
> src/flexchart/org/ovirt/Constants.as | 2 +-
> src/flexchart/org/ovirt/DataSource.as | 7 +-
> src/flexchart/org/ovirt/charts/BarChart.as | 287 ++++++++++++++++++------
> src/flexchart/org/ovirt/charts/Chart.as | 38 +++-
> src/flexchart/org/ovirt/data/DataPoint.as | 7 +-
> src/flexchart/org/ovirt/data/DataSeries.as | 12 +-
> src/flexchart/org/ovirt/elements/SingleBar.as | 51 ++++-
> src/flexchart/org/ovirt/elements/XAxisLabel.as | 66 ++++++
> src/flexchart/org/ovirt/elements/YAxisLabel.as | 17 +--
> 15 files changed, 476 insertions(+), 132 deletions(-)
> create mode 100644 src/flexchart/org/ovirt/ApplicationBus.as
> create mode 100644 src/flexchart/org/ovirt/elements/XAxisLabel.as
>
> diff --git a/src/app/controllers/graph_controller.rb b/src/app/controllers/graph_controller.rb
> index 0105ea6..d636544 100644
> --- a/src/app/controllers/graph_controller.rb
> +++ b/src/app/controllers/graph_controller.rb
> @@ -4,20 +4,53 @@ class GraphController < ApplicationController
> layout nil
>
> def flexchart_data
> -
> - #FIXME: use the stats package aggregation (when it's available)
> - #instead of the old method
> - graph_obj = history_graph_data_object
> -
> - #FIXME: for this release, the flexchart shows only peak values,
> - # and only shows a default of the last 40 data points in rrd.
> - graph_data = { :labels => graph_obj[:timepoints].last(40),
> - :values => graph_obj[:dataset][2][:values].last(40) }
> - my_data = graph_data[:labels].zip(graph_data[:values])
> - graph = { :vectors => my_data,
> - :max_value => graph_obj[:total_peak],
> - :description => params[:target]
> - }
> + @id = params[:id]
> + target = params[:target]
> + startTime = params[:startTime].to_i
> + endTime = params[:endTime].to_i
> + duration = endTime - startTime
> +
> + #the maximum number of data points we want in any chart
> + maxPoints = 100
> + resolution =
> + case
> + when duration / RRDResolution::Minimum < maxPoints
> + RRDResolution::Minimum
> + when duration / RRDResolution::Short < maxPoints
> + RRDResolution::Short
> + when duration / RRDResolution::Medium < maxPoints
> + RRDResolution::Medium
> + when duration / RRDResolution::Long < maxPoints
> + RRDResolution::Long
> + else
> + RRDResolution::Maximum
> + end
> + devclass = DEV_KEY_CLASSES[target]
> + counter = DEV_KEY_COUNTERS[target]
> +
> + #FIXME: until stats aggregation is pushed, we just get stats data for
> + # the first host in the pool. If no host in pool, the chart will be
> + # empty.
> + pool = Pool.find(@id)
> + hosts = pool.hosts
> + host = pool.hosts[0]
> + requestList = [ ]
> + requestList.push StatsRequest.new(host.hostname, devclass, 0, counter, startTime, duration, resolution, DataFunction::Peak)
> + statsList = getStatsData?(requestList)
> +
> + #The aggregated (summed) stats will come back as a single stats list
> + stat = statsList[0]
> + vectors = [ ]
> + data = stat.get_data?
> + data.each{ |datum|
> + val = datum.get_value?
> + val = 0 if val.nan?
> + vectors.push [datum.get_timestamp?.to_i, val]
> + }
> + graph = { :vectors => vectors,
> + :max_value => stat.get_max_value?,
> + :description => target
> + }
> render :json => graph
> end
>
> diff --git a/src/app/util/stats/StatsTypes.rb b/src/app/util/stats/StatsTypes.rb
> index 41c2977..4896bb3 100644
> --- a/src/app/util/stats/StatsTypes.rb
> +++ b/src/app/util/stats/StatsTypes.rb
> @@ -324,10 +324,12 @@ class RRDResolution
> end
>
> # Set up the resolutions for our rrd
> + RRDResolution.add_item :Minimum, 10 # Ten secs
> + RRDResolution.add_item :Short, 70 # Seventy secs
> + RRDResolution.add_item :Medium, 500 # 500 secs ( 8minute, 20 sec)
> + RRDResolution.add_item :Long, 2230
> + RRDResolution.add_item :Maximum, 26350
> RRDResolution.add_item :Default, 10 # Ten secs
> - RRDResolution.add_item :Short, 500 # 500 secs ( 8minute, 20 sec)
> - RRDResolution.add_item :Medium, 2230
> - RRDResolution.add_item :Long, 26350
> end
>
>
> diff --git a/src/app/views/graph/history_graphs.rhtml b/src/app/views/graph/history_graphs.rhtml
> index bebe5d9..97ed67f 100644
> --- a/src/app/views/graph/history_graphs.rhtml
> +++ b/src/app/views/graph/history_graphs.rhtml
> @@ -10,7 +10,7 @@ $('#flex_history_chart').flash(
> height: 300,
> wmode: 'transparent',
> menu: false,
> - flashvars: { flexchart_data: "<%= url_for :controller =>'/graph', :action => 'flexchart_data' %>/<%= @id %>/memory/1" }
> + flashvars: { flexchart_data: "<%= url_for :controller =>'/graph', :action => 'flexchart_data' %>/<%= @id %>/memory/<%= Time.now.to_i - 60 * 60 * 24 %>/<%= Time.now.to_i %>" }
> },
> { version: 9 }
> );
> diff --git a/src/config/routes.rb b/src/config/routes.rb
> index 8d538cb..0dbe0d6 100644
> --- a/src/config/routes.rb
> +++ b/src/config/routes.rb
> @@ -41,6 +41,7 @@ ActionController::Routing::Routes.draw do |map|
> map.connect ':controller/service.wsdl', :action => 'wsdl'
>
> # Install the default route as the lowest priority.
> + map.connect 'graph/flexchart_data/:id/:target/:startTime/:endTime', :controller => 'graph', :action => 'flexchart_data'
> map.connect 'graph/flexchart_data/:id/:target/:days', :controller => 'graph', :action => 'flexchart_data'
> map.connect ':controller/:action/:id.:format'
> map.connect ':controller/:action/:id'
> diff --git a/src/flexchart/flexchart.mxml b/src/flexchart/flexchart.mxml
> index 35fa9a6..c4a089f 100644
> --- a/src/flexchart/flexchart.mxml
> +++ b/src/flexchart/flexchart.mxml
> @@ -6,6 +6,7 @@
> import mx.containers.VBox;
> import mx.effects.Resize;
> import org.ovirt.Constants;
> + import org.ovirt.ApplicationBus;
> import org.ovirt.charts.Chart;
> import org.ovirt.charts.BarChart;
>
> @@ -21,6 +22,7 @@
> private var contractResources:Resize = new Resize();
>
> private function myInit():void {
> +
> mainChart.height = Constants.height;
> mainChart.width = Constants.width;
> hostsChart.width = Constants.width;
> @@ -42,6 +44,9 @@
> contractResources.heightTo = 0;
> contractResources.target = hostsChart;
> contractResources.duration = 500;
> +
> + ApplicationBus.instance().barClickAction = zoomIntoSeries;
> +
> }
>
> private function zoomOutSeries(e:Event):void {
> @@ -61,7 +66,8 @@
>
> </mx:Script>
>
> - <mx:VBox id="mainChart" click="zoomIntoSeries(event)" />
> - <mx:VBox id="hostsChart" visible="false" opaqueBackground="0x00ff00" click="zoomOutSeries(event)"/>
> -
> + <mx:VBox id="mainChart" />
> + <mx:VBox id="hostsChart" visible="false" opaqueBackground="0x00ff00" click="zoomOutSeries(event)">
> + <mx:Text text="This Space Reserved for Drill-down Hosts Chart" />
> + </mx:VBox>
> </mx:Application>
> diff --git a/src/flexchart/org/ovirt/ApplicationBus.as b/src/flexchart/org/ovirt/ApplicationBus.as
> new file mode 100644
> index 0000000..7d6d431
> --- /dev/null
> +++ b/src/flexchart/org/ovirt/ApplicationBus.as
> @@ -0,0 +1,39 @@
> +/*
> + Copyright (C) 2008 Red Hat, Inc.
> + Written by Steve Linabery <slinabery at redhat.com>
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; version 2 of the License.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program; if not, write to the Free Software
> + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + MA 02110-1301, USA. A copy of the GNU General Public License is
> + also available at http://www.gnu.org/copyleft/gpl.html.
> +*/
> +
> +//A way to expose some functions that are defined in flexchart.mxml to
> +//our ActionScript classes without needing to access Application directly
> +
> +package org.ovirt {
> + public class ApplicationBus {
> +
> + private static var _instance:ApplicationBus;
> +
> + public static function instance():ApplicationBus {
> + if (_instance == null) {
> + _instance = new ApplicationBus();
> + }
> + return _instance;
> + }
> +
> + public var barClickAction:Function;
> +
> + }
> +}
> diff --git a/src/flexchart/org/ovirt/Constants.as b/src/flexchart/org/ovirt/Constants.as
> index 996a31e..14f6465 100644
> --- a/src/flexchart/org/ovirt/Constants.as
> +++ b/src/flexchart/org/ovirt/Constants.as
> @@ -23,6 +23,6 @@ package org.ovirt {
> public static var width:int = 722;
> public static var height:int = 297;
> public static var barSpacing:int = 2;
> - public static var labelHeight:int = 40;
> + public static var labelHeight:int = 20;
> }
> }
> diff --git a/src/flexchart/org/ovirt/DataSource.as b/src/flexchart/org/ovirt/DataSource.as
> index 44e482d..4438900 100644
> --- a/src/flexchart/org/ovirt/DataSource.as
> +++ b/src/flexchart/org/ovirt/DataSource.as
> @@ -20,13 +20,13 @@
>
> package org.ovirt {
>
> - import flash.net.URLLoader;
> - import flash.net.URLRequest;
> import com.adobe.serialization.json.JSON;
> import flash.events.Event;
> import flash.events.IOErrorEvent;
> - import org.ovirt.data.DataSeries;
> + import flash.net.URLLoader;
> + import flash.net.URLRequest;
> import org.ovirt.charts.Chart;
> + import org.ovirt.data.DataSeries;
>
> public class DataSource {
>
> @@ -52,6 +52,7 @@ package org.ovirt {
> }
>
> private function ioError( e:IOErrorEvent ):void {
> + trace("ioError");
> //FIXME:
> //do something useful with this error
> }
> diff --git a/src/flexchart/org/ovirt/charts/BarChart.as b/src/flexchart/org/ovirt/charts/BarChart.as
> index 83cf0bb..88a75ca 100644
> --- a/src/flexchart/org/ovirt/charts/BarChart.as
> +++ b/src/flexchart/org/ovirt/charts/BarChart.as
> @@ -19,40 +19,127 @@
> */
>
> package org.ovirt.charts {
> -
> + import flash.events.Event;
> + import flash.events.MouseEvent;
> + import mx.collections.ArrayCollection;
> import mx.containers.Box;
> import mx.containers.HBox;
> import mx.containers.VBox;
> - import mx.controls.Text;
> import mx.containers.Canvas;
> + import mx.controls.TextInput;
> + import mx.controls.DateField;
> + import mx.controls.Button;
> + import mx.controls.PopUpMenuButton;
> + import mx.controls.Text;
> + import mx.events.MenuEvent;
> + import mx.formatters.DateFormatter;
> import org.ovirt.data.*;
> import org.ovirt.elements.*;
> import org.ovirt.Constants;
> + import org.ovirt.ApplicationBus;
>
> public class BarChart extends Chart {
>
> - private var chartArea:HBox;
> - private var labelArea:Canvas;
> + private var chartArea:Canvas;
> + private var XAxisLabelArea:Canvas;
> + private var startDateField:DateField;
> + private var endDateField:DateField;
> + private var startTimeField:TextInput;
> + private var endTimeField:TextInput;
> + private var button:Button;
> + private var menu:PopUpMenuButton;
> + private var dateBar:Box;
> + private var datePattern:RegExp;
> +
>
> public function BarChart(container:Box,
> datasourceUrl:String) {
> super(container,datasourceUrl);
> - chartArea = new HBox();
> - chartArea.setStyle("horizontalGap",Constants.barSpacing);
> - chartArea.setStyle("verticalAlign","bottom");
> + container.setStyle("verticalGap","2");
> + datePattern = /^(\d+):(\d+)$/;
> + }
> +
> +
> + private function timeRangeAdjusted(event:Event):void {
> + var t1:Number = startDateField.selectedDate.getTime()
> + + (parseHour(startTimeField.text) * 3600 * 1000)
> + + (parseMinute(startTimeField.text) * 60 * 1000);
> + setStartTime(Math.floor(t1 / 1000));
> + var t2:Number = endDateField.selectedDate.getTime()
> + + (parseHour(endTimeField.text) * 3600 * 1000)
> + + (parseMinute(endTimeField.text) * 60 * 1000);
> + setEndTime(Math.floor(t2 / 1000));
> + load();
> + }
> +
> + private function typeSelected(event:MenuEvent):void {
> + target = event.label;
> + load();
> + }
> +
> +
> + private function pad(input:int):String {
> + if (input < 10) {
> + return "0" + input;
> + } else {
> + return "" + input;
> + }
> + }
> +
> + private function parseHour(input:String):int {
> + var answer:int = 0;
> + try {
> + var obj:Object = datePattern.exec(input);
> + if (obj != null) {
> + answer = int(obj[1].toString());
> + }
> + } catch (e:Error) {}
> + return answer;
> + }
> +
> + private function parseMinute(input:String):int {
> + var answer:int = 0;
> + try {
> + var obj:Object = datePattern.exec(input);
> + if (obj != null) {
> + answer = int(obj[2].toString());
> + }
> + } catch (e:Error) {}
> + return answer;
> + }
> +
> + override public function addData(dataSeries:DataSeries):void {
> + container.removeAllChildren();
> +
> + var dateFormat:DateFormatter = new DateFormatter();
> +
> + //since we're reusing objects, we need to get rid of stale
> + //EventListener references
> + if (chartArea != null) {
> + var kids:Array = chartArea.getChildren();
> + var i:int;
> + for (i = 0; i < kids.length; i++) {
> + (kids[i] as SingleBar).destroy();
> + }
> + }
> +
> + chartArea = new Canvas();
> chartArea.percentHeight = 80;
> chartArea.percentWidth = 100;
> + chartArea.setStyle("backgroundColor","0xbbccdd");
> this.container.addChild(chartArea);
>
> - labelArea = new Canvas();
> - labelArea.height = Constants.labelHeight;
> - labelArea.minHeight = Constants.labelHeight;
> - labelArea.percentWidth = 100;
> - this.container.addChild(labelArea);
> - }
> + XAxisLabelArea = new Canvas();
> + XAxisLabelArea.height = Constants.labelHeight;
> + XAxisLabelArea.minHeight = Constants.labelHeight;
> + XAxisLabelArea.percentWidth = 100;
> + this.container.addChild(XAxisLabelArea);
>
> - override public function addData(dataSeries:DataSeries):void {
> try {
> +
> + dateBar = new HBox();
> + dateBar.setVisible(true);
> + this.container.addChild(dateBar);
> var dataPoints:Array = dataSeries.getDataPoints();
> var maxValue:Number = dataSeries.getMaxValue();
> var scale:Number = maxValue;
> @@ -65,74 +152,72 @@ package org.ovirt.charts {
> throw new Error("No data points in range");
> }
>
> - //have to iterate through datapoint.timestamp strings,
> - //create a TextLiberation object with them, and add them to
> - //a parent container before we can tell how wide they are in pixels.
> - var labelWidth:Number = 0;
> - for (var i:int = 0; i < size; i++) {
> - var dataPoint:DataPoint = dataPoints[i] as DataPoint;
> - var textTemp:TextLiberation =
> - new TextLiberation(dataPoint.getTimestamp());
> - textTemp.setVisible(false);
> - chartArea.addChild(textTemp);
> - var tempLabelWidth:Number = textTemp.getTextWidth();
> - if (! isNaN(tempLabelWidth)) {
> - labelWidth = Math.max(labelWidth, tempLabelWidth);
> - }
> - }
> - //now we have to remove all the children we just added, since we don't
> - //really want them to be part of the chart.
> - chartArea.removeAllChildren();
> -
> - //we always want an odd number of y-axis labels, and we'll
> - //determine this by using the labelWidth we just determined
> - var labelCount:int = Math.floor(Constants.width / labelWidth);
> - if (labelCount > 3 && labelCount % 2 == 1) {
> - labelCount--;
> - }
> -
> //the distance between left edges of adjacent bars
> - var gridWidth:Number = Constants.width / size;
> + var gridWidth:Number = Math.floor(Constants.width / size);
>
> //the width of each SingleBar (does not including padding between bars)
> var barWidth:Number = gridWidth - Constants.barSpacing;
>
> - //use this to center y-axis labels on the bars
> - var labelOffset:Number = barWidth / 2;
> + //due to the discrete number of pixels, there may be space at the
> + //right side of the graph that needs to be made up by padding
> + //bars here and there
> + var shortfall:Number = Constants.width - (gridWidth * size);
> + var makeup:Number = Math.round(size / shortfall);
> + var madeup:Number = 0;
> +
> + //variable to hold the numbered day of the month of the last
> + //XAxisLabel added to the label area
> + var lastDate:Number;
>
> - //distance between first and last label
> - var labelSpace:Number = Constants.width - gridWidth;
> - var labelSpacing:Number = labelSpace / labelCount;
> + //variable to hold the x-coordinate of the next bar to be added to
> + //the chart
> + var currentBarPosition:int = 0;
>
> //add the bars & labels to the chart
> var labelCounter:int = 0;
> for (i = 0; i < size; i++) {
> - dataPoint = dataPoints[i] as DataPoint;
> +
> + var dataPoint:DataPoint = dataPoints[i] as DataPoint;
> + if (i == 0) {
> + lastDate = dataPoint.getTimestamp().date;
> + }
> +
> + //show long date format for first & last XAxisLabels,
> + //as well as whenever the date changes
> + if (i == 0 || i == size - 1
> + || dataPoint.getTimestamp().date != lastDate) {
> + dateFormat.formatString = "DD-MMM-YYYY JJ:NN";
> + } else {
> + dateFormat.formatString = "JJ:NN";
> + }
> +
> var value:Number = dataPoint.getValue();
> - var bar:SingleBar = new SingleBar(dataPoint);
> - bar.percentHeight = ((value / scale) * 80);
> - bar.width = barWidth;
> - bar.setVisible(true);
> + var bar:SingleBar = new SingleBar(dataPoint,scale);
> chartArea.addChild(bar);
> - var currentLabelPosition:int = labelCounter * labelSpacing +
> - labelOffset;
> -
> - if (currentLabelPosition >= i * gridWidth &&
> - currentLabelPosition < (i + 1) * gridWidth) {
> - var label:YAxisLabel = new YAxisLabel(dataPoint.getTimestamp());
> - label.setVisible(false);
> - label.y = ((labelCounter + 1) % 2) * 13 + 4;
> - labelArea.addChild(label);
> - //make sure the label is fully within the chart width
> - label.x = Math.max(0,
> - Math.min((i) * gridWidth -
> - (label.labelText.getTextWidth() / 2) +
> - labelOffset,
> - Constants.width -
> - label.labelText.getTextWidth() - 6)
> - );
> + bar.width = barWidth;
> + bar.addEventListener(MouseEvent.CLICK,
> + ApplicationBus.instance().barClickAction);
> + bar.x = currentBarPosition;
> + if (makeup > 0 && i % makeup == 0 && madeup < shortfall) {
> + bar.width = bar.width + 1;
> + madeup++;
> + }
> +
> + //add XAxisLabels at the endpoints of the time range,
> + //as well as the center if there are more than 6 points
> + //and two more if there are more than 14 points
> + if ((size > 6 && i == Math.floor(size / 2))
> + || (size > 14
> + && (i == Math.floor(size / 4)
> + || i == Math.floor(size * 3 / 4)))
> + || i == 0
> + || i == size - 1) {
> + var label:XAxisLabel =
> + new XAxisLabel(dateFormat.format(dataPoint.getTimestamp()));
> + label.setCenter(currentBarPosition + bar.width / 2);
> label.setVisible(true);
> - labelCounter++;
> + label.y = 6;
> + XAxisLabelArea.addChild(label);
>
> //add a 'tick' in the center of the bar to which this label
> //corresponds
> @@ -140,13 +225,73 @@ package org.ovirt.charts {
> ind.opaqueBackground = 0x000000;
> ind.width=1;
> ind.height=3;
> - ind.x = (i) * gridWidth + labelOffset;
> + ind.x = label.getCenter();
> ind.y = 0;
> ind.setVisible(true);
> ind.setStyle("backgroundColor","0x000000");
> - labelArea.addChild(ind);
> + XAxisLabelArea.addChild(ind);
> + lastDate = dataPoint.getTimestamp().date;
> }
> + currentBarPosition += (bar.width + Constants.barSpacing);
> + }
> +
> + //fill in the time range selection bar
> + var t:Date;
> + var f1:Text = new Text();
> + f1.text = "View data between";
> + dateBar.addChild(f1);
> + t = new Date(dataPoints[0].getTimestamp().getTime());
> + startDateField = new DateField();
> + startDateField.selectedDate = t;
> + startDateField.editable = true;
> + startTimeField = new TextInput();
> + startTimeField.minWidth = 50;
> + startTimeField.maxWidth = 50;
> + startTimeField.text = pad(t.hours) + ":" + pad(t.minutes);
> + dateBar.addChild(startTimeField);
> + dateBar.addChild(startDateField);
> + var f2:Text = new Text();
> + f2.text = "and";
> + dateBar.addChild(f2);
> +
> + t = new Date(dataPoints[size - 1].getTimestamp().getTime());
> + endDateField = new DateField();
> + endDateField.selectedDate = t;
> + endDateField.editable = true;
> + endTimeField = new TextInput();
> + endTimeField.minWidth = 50;
> + endTimeField.maxWidth = 50;
> + endTimeField.text = pad(t.hours) + ":" + pad(t.minutes);
> + dateBar.addChild(endTimeField);
> + dateBar.addChild(endDateField);
> +
> + button = new Button();
> + button.label = "go";
> + button.addEventListener(MouseEvent.CLICK,timeRangeAdjusted);
> + dateBar.addChild(button);
> +
> + //FIXME: these should be fetched from the graph controller so
> + //that different types can be added (or restricted) dynamically
> + var menuItems:ArrayCollection =
> + new ArrayCollection( [{label: "memory"},
> + {label: "cpu"},
> + {label: "load"},
> + {label: "netin"},
> + {label: "netout"},
> + {label: "disk"}
> + ]);
> +
> +
> + if (menu != null) {
> + menu.removeEventListener(MenuEvent.ITEM_CLICK,typeSelected);
> }
> +
> + menu = new PopUpMenuButton();
> + menu.label = "Select Data Type";
> + menu.dataProvider = menuItems;
> + menu.addEventListener(MenuEvent.ITEM_CLICK,typeSelected);
> + dateBar.addChild(menu);
> +
> } catch (e:Error) {
> var err:Text = new Text();
> err.text = e.message;
> diff --git a/src/flexchart/org/ovirt/charts/Chart.as b/src/flexchart/org/ovirt/charts/Chart.as
> index 26c8d02..f2faf33 100644
> --- a/src/flexchart/org/ovirt/charts/Chart.as
> +++ b/src/flexchart/org/ovirt/charts/Chart.as
> @@ -19,19 +19,32 @@
> */
>
> package org.ovirt.charts {
> -
> - public class Chart {
> -
> import org.ovirt.DataSource;
> import mx.containers.Box;
> import org.ovirt.data.DataSeries;
>
> + public class Chart {
> +
> protected var container:Box;
> protected var datasourceUrl:String;
>
> + protected var startTime:Number;
> + protected var endTime:Number;
> + protected var target:String;
> + protected var id:int;
> +
> public function Chart(container:Box, datasourceUrl:String) {
> this.container = container;
> this.datasourceUrl = datasourceUrl;
> + if (datasourceUrl != null) {
> + var results:Array = datasourceUrl.split("/");
> + if (results != null && results.length > 7) {
> + setId(new int(results[4]));
> + setTarget(results[5] as String);
> + setStartTime(new int(results[6]));
> + setEndTime(new int(results[7]));
> + }
> + }
> }
>
> public function addData(dataSeries:DataSeries):void {
> @@ -40,7 +53,24 @@ package org.ovirt.charts {
>
> public function load():void {
> var dataSource:DataSource = new DataSource(this);
> - dataSource.retrieveData(datasourceUrl);
> + var myString:String = "/ovirt/graph/flexchart_data/" + id + "/" + target + "/" + startTime + "/" + endTime;
> + dataSource.retrieveData(myString);
> + }
> +
> + public function setStartTime(startTime:Number):void {
> + this.startTime = startTime;
> + }
> +
> + public function setEndTime(endTime:Number):void {
> + this.endTime = endTime;
> + }
> +
> + public function setTarget(target:String):void {
> + this.target = target;
> + }
> +
> + public function setId(id:int):void {
> + this.id = id;
> }
> }
> }
> diff --git a/src/flexchart/org/ovirt/data/DataPoint.as b/src/flexchart/org/ovirt/data/DataPoint.as
> index 00cd0a4..5d59de9 100644
> --- a/src/flexchart/org/ovirt/data/DataPoint.as
> +++ b/src/flexchart/org/ovirt/data/DataPoint.as
> @@ -22,17 +22,18 @@ package org.ovirt.data {
>
> public class DataPoint {
>
> - private var timestamp:String;
> + private var timestamp:Date;
> private var value:Number;
> private var description:String;
>
> - public function DataPoint (timestamp:String, value:Number, description:String) {
> + public function DataPoint (timestamp:Date, value:Number,
> + description:String) {
> this.timestamp = timestamp;
> this.value = value;
> this.description = description;
> }
>
> - public function getTimestamp():String {
> + public function getTimestamp():Date {
> return timestamp;
> }
>
> diff --git a/src/flexchart/org/ovirt/data/DataSeries.as b/src/flexchart/org/ovirt/data/DataSeries.as
> index 764fd34..eb653e9 100644
> --- a/src/flexchart/org/ovirt/data/DataSeries.as
> +++ b/src/flexchart/org/ovirt/data/DataSeries.as
> @@ -36,9 +36,15 @@ package org.ovirt.data {
> dataPoints = new Array();
> var inDataPoints:Array = object["vectors"] as Array;
> for (var i:int = 0; i < inDataPoints.length; i++) {
> - dataPoints.push(new DataPoint((inDataPoints[i] as Array)[0] as String,
> - (inDataPoints[i] as Array)[1] as Number,
> - description));
> + var value:Number = 0;
> + var valuea:Number = (inDataPoints[i] as Array)[1] as Number;
> + if (!isNaN(valuea)) {
> + value = (inDataPoints[i] as Array)[1] as Number;
> + }
> + var seconds:int = int((inDataPoints[i] as Array)[0]) * 1000;
> + dataPoints.push(new DataPoint(new Date(seconds),
> + value,
> + description));
> }
> maxValue = object["max_value"] as Number;
> }
> diff --git a/src/flexchart/org/ovirt/elements/SingleBar.as b/src/flexchart/org/ovirt/elements/SingleBar.as
> index 6e09bff..e7caf93 100644
> --- a/src/flexchart/org/ovirt/elements/SingleBar.as
> +++ b/src/flexchart/org/ovirt/elements/SingleBar.as
> @@ -20,39 +20,66 @@
>
> package org.ovirt.elements {
>
> - import mx.containers.Box;
> - import mx.controls.ToolTip;
> - import mx.managers.ToolTipManager;
> + import flash.display.DisplayObject;
> import flash.events.Event;
> import flash.events.MouseEvent;
> import flash.geom.Rectangle;
> - import flash.display.DisplayObject;
> + import mx.containers.Canvas;
> + import mx.controls.ToolTip;
> + import mx.events.FlexEvent;
> + import mx.events.ResizeEvent;
> + import mx.formatters.DateFormatter;
> + import mx.managers.ToolTipManager;
> import org.ovirt.data.DataPoint;
>
> - public class SingleBar extends Box {
> + public class SingleBar extends Canvas {
>
> private var tip:ToolTip;
> private var dataPoint:DataPoint;
> + private var scale:Number;
> + private var dateFormat:DateFormatter = new DateFormatter();
>
> - public function SingleBar(dataPoint:DataPoint) {
> + public function SingleBar(dataPoint:DataPoint,scale:Number) {
> super();
> this.dataPoint = dataPoint;
> + this.scale = scale;
> addEventListener(MouseEvent.MOUSE_OVER,showTip);
> addEventListener(MouseEvent.MOUSE_OUT,destroyTip);
> - this.setStyle("backgroundColor","0x0000FF");
> - this.setStyle("left","1");
> - this.setStyle("right","1");
> + addEventListener(ResizeEvent.RESIZE,myResize);
> + addEventListener(FlexEvent.CREATION_COMPLETE,myResize);
> + addEventListener(Event.RENDER,myResize);
> + this.setStyle("backgroundColor","0x2875c1");
> + dateFormat.formatString = "DD-MMM-YYYY JJ:NN";
> + }
> +
> + public function destroy():void {
> + removeEventListener(MouseEvent.MOUSE_OVER,showTip);
> + removeEventListener(MouseEvent.MOUSE_OUT,destroyTip);
> + removeEventListener(ResizeEvent.RESIZE,myResize);
> + removeEventListener(FlexEvent.CREATION_COMPLETE,myResize);
> + removeEventListener(FlexEvent.UPDATE_COMPLETE,myResize);
> + removeEventListener(Event.RENDER,myResize);
> + }
> +
> +
> + private function myResize(event:Event):void {
> + trace(event.type);
> + this.height = (dataPoint.getValue() / scale) * parent.height * .9 * -1;
> + this.y = parent.height;
> }
>
> private function showTip(event:Event):void {
> +
> var w:Number = this.stage.width;
> var target:DisplayObject = event.currentTarget as DisplayObject;
> var pt:Rectangle = this.stage.getBounds(target);
> var yPos:Number = pt.y * -1;
> var xPos:Number = pt.x * -1;
> - tip = ToolTipManager.createToolTip(dataPoint.getDescription() + "\n" +
> - dataPoint.getTimestamp() + "\n" +
> - dataPoint.getValue(),
> + tip = ToolTipManager.createToolTip(dataPoint.getDescription() +
> + "\n" +
> + dateFormat.format(dataPoint.getTimestamp()) +
> + "\n" +
> + dataPoint.getValue(),
> xPos,yPos) as ToolTip;
> tip.x = Math.min(tip.x,
> w - tip.width);
> diff --git a/src/flexchart/org/ovirt/elements/XAxisLabel.as b/src/flexchart/org/ovirt/elements/XAxisLabel.as
> new file mode 100644
> index 0000000..9bf4c26
> --- /dev/null
> +++ b/src/flexchart/org/ovirt/elements/XAxisLabel.as
> @@ -0,0 +1,66 @@
> +/*
> + Copyright (C) 2008 Red Hat, Inc.
> + Written by Steve Linabery <slinabery at redhat.com>
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; version 2 of the License.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program; if not, write to the Free Software
> + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + MA 02110-1301, USA. A copy of the GNU General Public License is
> + also available at http://www.gnu.org/copyleft/gpl.html.
> +*/
> +
> +package org.ovirt.elements {
> +
> + import mx.containers.Box;
> + import mx.core.ScrollPolicy;
> + import flash.events.*;
> + import flash.events.MouseEvent;
> + import mx.events.*;
> + import mx.events.FlexEvent;
> +
> + public class XAxisLabel extends Box {
> +
> + public var labelText:TextLiberation;
> + private var center:int;
> +
> + public function XAxisLabel(text:String) {
> + super();
> + labelText = new TextLiberation(text);
> + labelText.setVisible(true);
> + this.addChild(labelText);
> + this.horizontalScrollPolicy = ScrollPolicy.OFF;
> + this.verticalScrollPolicy = ScrollPolicy.OFF;
> + this.setStyle("paddingLeft","0");
> + this.setStyle("paddingRight","0");
> + addEventListener(FlexEvent.CREATION_COMPLETE,centerLabel);
> + }
> +
> + public function setCenter(center:int):void {
> + this.center = center;
> + }
> +
> + public function getCenter():int {
> + return center;
> + }
> +
> + private function centerLabel(event:Event):void {
> + this.x = center - labelText.getTextWidth() / 2;
> + if (parent != null) {
> + if (this.x < 0) {
> + this.x = 0;
> + } else if (this.x > parent.width - labelText.getTextWidth() - 5) {
> + this.x = parent.width - labelText.getTextWidth() - 5;
> + }
> + }
> + }
> + }
> +}
> diff --git a/src/flexchart/org/ovirt/elements/YAxisLabel.as b/src/flexchart/org/ovirt/elements/YAxisLabel.as
> index 0e93b97..73e1239 100644
> --- a/src/flexchart/org/ovirt/elements/YAxisLabel.as
> +++ b/src/flexchart/org/ovirt/elements/YAxisLabel.as
> @@ -18,24 +18,11 @@
> also available at http://www.gnu.org/copyleft/gpl.html.
> */
>
> -package org.ovirt.elements {
> +//class for labeling the scale of the y-axis of a chart
>
> - import mx.containers.Box;
> - import mx.core.ScrollPolicy;
> +package org.ovirt.elements {
>
> public class YAxisLabel extends Box {
>
> - public var labelText:TextLiberation;
> -
> - public function YAxisLabel(text:String) {
> - super();
> - labelText = new TextLiberation(text);
> - labelText.setVisible(true);
> - this.addChild(labelText);
> - this.horizontalScrollPolicy = ScrollPolicy.OFF;
> - this.verticalScrollPolicy = ScrollPolicy.OFF;
> - this.setStyle("paddingLeft","0");
> - this.setStyle("paddingRight","0");
> - }
> }
> }
> --
> 1.5.6.5
>
More information about the ovirt-devel
mailing list