2 // Copyright (c) 2010 Anthony Towns
8 import java.util.ArrayList;
9 import java.util.HashMap;
11 import org.jfree.chart.ChartUtilities;
12 import org.jfree.chart.JFreeChart;
13 import org.jfree.chart.axis.AxisLocation;
14 import org.jfree.chart.axis.NumberAxis;
15 import org.jfree.chart.labels.StandardXYToolTipGenerator;
16 import org.jfree.chart.plot.PlotOrientation;
17 import org.jfree.chart.plot.XYPlot;
18 import org.jfree.chart.plot.ValueMarker;
19 import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
20 import org.jfree.chart.renderer.xy.XYItemRenderer;
21 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
22 import org.jfree.data.xy.XYSeries;
23 import org.jfree.data.xy.XYSeriesCollection;
24 import org.jfree.ui.RectangleAnchor;
25 import org.jfree.ui.TextAnchor;
27 import altosui.AltosDataPoint;
28 import altosui.AltosGraph;
30 class AltosGraphTime extends AltosGraph {
31 static interface Element {
32 void attachGraph(AltosGraphTime g);
33 void gotTimeData(double time, AltosDataPoint d);
34 void addToPlot(AltosGraphTime g, XYPlot plot);
37 static class TimeAxis implements Element {
41 private AxisLocation locn;
42 private double min_y = Double.NaN;
44 public TimeAxis(int axis, String label, Color color, AxisLocation locn)
52 public void setLowerBound(double min_y) {
56 public void attachGraph(AltosGraphTime g) { return; }
57 public void gotTimeData(double time, AltosDataPoint d) { return; }
59 public void addToPlot(AltosGraphTime g, XYPlot plot) {
60 NumberAxis numAxis = new NumberAxis(label);
61 if (!Double.isNaN(min_y))
62 numAxis.setLowerBound(min_y);
63 plot.setRangeAxis(axis, numAxis);
64 plot.setRangeAxisLocation(axis, locn);
65 numAxis.setLabelPaint(color);
66 numAxis.setTickLabelPaint(color);
67 numAxis.setAutoRangeIncludesZero(false);
71 abstract static class TimeSeries implements Element {
72 protected XYSeries series;
73 private String axisName;
76 public TimeSeries(String axisName, String label, Color color) {
77 this.series = new XYSeries(label);
78 this.axisName = axisName;
82 public void attachGraph(AltosGraphTime g) {
83 g.setAxis(this, axisName, color);
85 abstract public void gotTimeData(double time, AltosDataPoint d);
87 public void addToPlot(AltosGraphTime g, XYPlot plot) {
88 XYSeriesCollection dataset = new XYSeriesCollection();
89 dataset.addSeries(this.series);
91 XYItemRenderer renderer = new StandardXYItemRenderer();
92 renderer.setSeriesPaint(0, color);
94 int dataNum = g.getDataNum(this);
95 int axisNum = g.getAxisNum(this);
97 plot.setDataset(dataNum, dataset);
98 plot.mapDatasetToRangeAxis(dataNum, axisNum);
99 plot.setRenderer(dataNum, renderer);
103 static class StateMarker implements Element {
104 private double val = Double.NaN;
108 StateMarker(int state, String name) {
113 public void attachGraph(AltosGraphTime g) { return; }
114 public void gotTimeData(double time, AltosDataPoint d) {
115 if (Double.isNaN(val) || time < val) {
116 if (d.state() == state) {
122 public void addToPlot(AltosGraphTime g, XYPlot plot) {
123 if (Double.isNaN(val))
126 ValueMarker m = new ValueMarker(val);
128 m.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
129 m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
130 plot.addDomainMarker(m);
134 private String title;
135 private ArrayList<Element> elements;
136 private HashMap<String,Integer> axes;
137 private HashMap<Element,Integer> datasets;
138 private ArrayList<Integer> datasetAxis;
140 public AltosGraphTime(String title) {
141 this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png";
143 this.elements = new ArrayList<Element>();
144 this.axes = new HashMap<String,Integer>();
145 this.datasets = new HashMap<Element,Integer>();
146 this.datasetAxis = new ArrayList<Integer>();
149 public AltosGraphTime addElement(Element e) {
155 public void setAxis(Element ds, String axisName, Color color) {
156 Integer axisNum = axes.get(axisName);
157 int dsNum = datasetAxis.size();
158 if (axisNum == null) {
159 axisNum = newAxis(axisName, color);
161 datasets.put(ds, dsNum);
162 datasetAxis.add(axisNum);
165 public int getAxisNum(Element ds) {
166 return datasetAxis.get( datasets.get(ds) ).intValue();
168 public int getDataNum(Element ds) {
169 return datasets.get(ds).intValue();
172 private Integer newAxis(String name, Color color) {
173 int cnt = axes.size();
174 AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT;
176 locn = AxisLocation.TOP_OR_RIGHT;
178 Integer res = new Integer(cnt);
180 this.addElement(new TimeAxis(cnt, name, color, locn));
184 public void addData(AltosDataPoint d) {
185 double time = d.time();
186 for (Element e : elements) {
187 e.gotTimeData(time, d);
191 public JFreeChart createChart() {
192 NumberAxis xAxis = new NumberAxis("Time (s)");
193 xAxis.setAutoRangeIncludesZero(false);
194 XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
195 XYPlot plot = new XYPlot();
196 plot.setDomainAxis(xAxis);
197 plot.setRenderer(renderer);
198 plot.setOrientation(PlotOrientation.VERTICAL);
200 renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
201 JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
203 ChartUtilities.applyCurrentTheme(chart);
205 plot.setDomainPannable(true);
206 plot.setRangePannable(true);
208 for (Element e : elements) {
209 e.addToPlot(this, plot);
215 public void toPNG() throws java.io.IOException {
216 if (axes.size() > 1) {