package eclipse.view.gui.tab; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Date; import java.util.List; import java.util.Observable; import java.util.Observer; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import org.apache.log4j.Logger; import org.jfree.chart.ChartMouseEvent; import org.jfree.chart.ChartMouseListener; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.entity.XYItemEntity; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.time.Second; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import org.jfree.ui.RectangleInsets; import eclipse.model.data.Data; import eclipse.model.data.DataManager; import eclipse.model.data.Device; import eclipse.model.data.DeviceItem; /** * DEfault Graphic interface for GRAPH data. * Technically this class can graph any DeviceItem * * This is also an observer on DeviceItem * * @author Eclipse * */ public class TelemetryGraph extends JPanel implements TabPane, Observer { private static final long serialVersionUID = 7068305431504601524L; TimeSeries graphedValues; ChartPanel chartPanel; int deviceId; int itemDeviceId; DeviceItem item; Device device; TimeSeriesCollection dataset; double x; double y; public TelemetryGraph(int deviceId, int itemDeviceId) { this.deviceId = deviceId; this.itemDeviceId = itemDeviceId; try { device = DataManager.getInstance().getDeviceByID(deviceId); item = device.getItemByID(itemDeviceId); } catch (Exception e) { StringWriter stack = new StringWriter(); e.printStackTrace(new PrintWriter(stack)); Logger.getLogger("main").error("Caught exception; decorating with appropriate status template : " + stack.toString()); } item.addObserver(this); addHistory(); createGraph(); this.setLayout(new GridLayout(1,1)); this.add(chartPanel); } /** * Ugly code creating the graph, layer and all that stuff */ private void createGraph() { //graphedValues = new TimeSeries(item.getUnit()); //graphedValues = new TimeSeries(item.getUnit(), Second.class); //graphedValues.setMaximumItemAge(3000); //graphedValues.setMaximumItemCount(30); dataset= new TimeSeriesCollection(); //dataset.addSeries(this.graphedValues); dataset.addSeries(graphedValues); DateAxis domain = new DateAxis("Time"); NumberAxis range = new NumberAxis(item.getUnit()); //range.setRange(item.getMinValue(), item.getMaxValue()); range.setAutoRange(true); domain.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12)); range.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12)); domain.setLabelFont(new Font("SansSerif", Font.PLAIN, 14)); range.setLabelFont(new Font("SansSerif", Font.PLAIN, 14)); XYItemRenderer renderer = new XYLineAndShapeRenderer(true,true); renderer.setSeriesPaint(0, Color.RED); //renderer.setSeriesPaint(1, Color.GREEN); renderer.setBaseStroke(new BasicStroke(3f, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL)); XYPlot plot = new XYPlot(dataset, domain, range, renderer); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); domain.setAutoRange(true); domain.setLowerMargin(0.0); domain.setUpperMargin(0.0); domain.setTickLabelsVisible(true); range.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); JFreeChart chart = new JFreeChart("(Id: " + item.getItemId() + ")", new Font("SansSerif",Font.BOLD, 24), plot, true); //List<String> subtitles = new List<String>(); //subtitles.add("(on " + device.getName() + ")"); //chart.setSubtitles(subtitles); chart.setBackgroundPaint(Color.white); chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(4, 4, 4, 4), BorderFactory.createLineBorder(Color.black))); chartPanel.setSize(new Dimension(400, 400)); chartPanel.addChartMouseListener(new ChartMouseListener(){ public void chartMouseClicked(ChartMouseEvent e){ try{ XYItemEntity xyitem=(XYItemEntity) e.getEntity(); double x = dataset.getXValue(xyitem.getSeriesIndex(), xyitem.getItem()); double y = dataset.getYValue(xyitem.getSeriesIndex(), xyitem.getItem()); JOptionPane.showMessageDialog(new JFrame(), ""+y+" :: "+new Second(new Date((long)x))); } catch(Exception exception ) { } } public void chartMouseMoved(ChartMouseEvent arg0) { } }); } /** * Add new value to the graph (every second in the best condition * @param value */ private void addValuetoGraph(double value) { graphedValues.addOrUpdate(new Second(), value); } /** * Add all data before we create the graph. If we open the graph after 10 min we are going to have 10 min of data graphed */ private void addHistory() { List<Data> tmp = item.getAllData(); graphedValues = new TimeSeries("value"); for (int i=1;i<tmp.size();i++) graphedValues.addOrUpdate(new Second(new Date((long) tmp.get(i).getDate())), tmp.get(i).getData()); } /** * Update Every Second. In our case not usefull because maybe data is not new every second */ public void updateValues() { // double value = item.getLastData(); // addValuetoGraph(value); // graphedValues.fireSeriesChanged(); } /** * This updater is observer on data themself, everytime there is a new data graph get updated */ public void update(Observable o, Object arg) { double value = ((DeviceItem) o).getLastData(); addValuetoGraph(value); graphedValues.fireSeriesChanged(); } }