]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph.swing/src/org/simantics/scenegraph/swing/JFreeTrendNode.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scenegraph.swing / src / org / simantics / scenegraph / swing / JFreeTrendNode.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph.swing;
13
14 import java.awt.Graphics2D;\r
15 import java.awt.geom.AffineTransform;\r
16 import java.awt.geom.Rectangle2D;\r
17 import java.util.ArrayList;\r
18 import java.util.List;\r
19 \r
20 import javax.swing.JPanel;\r
21 \r
22 import org.jfree.chart.ChartFactory;\r
23 import org.jfree.chart.ChartPanel;\r
24 import org.jfree.chart.JFreeChart;\r
25 import org.jfree.chart.axis.ValueAxis;\r
26 import org.jfree.chart.plot.PlotOrientation;\r
27 import org.jfree.chart.plot.XYPlot;\r
28 import org.jfree.data.xy.XYSeries;\r
29 import org.jfree.data.xy.XYSeriesCollection;\r
30 import org.simantics.scenegraph.ExportableWidget.RasterOutputWidget;\r
31 import org.simantics.scenegraph.g2d.IdentityAffineTransform;\r
32 import org.simantics.scenegraph.g2d.nodes.Trend2DNode.TrendPoint;\r
33 \r
34 @RasterOutputWidget
35 public class JFreeTrendNode extends ComponentNode<JPanel> {
36
37     /**
38      * 
39      */
40     private static final long serialVersionUID = 8508750881358776559L;
41
42     protected String title = null;
43     protected String yTitle = null;
44     protected String xTitle = null;
45     protected transient List<TrendPoint> points = null;
46
47     protected transient XYSeries series = null;\r
48     
49     @Override\r
50     public void init() {\r
51         series = new XYSeries("Trend");\r
52         final XYSeriesCollection dataset = new XYSeriesCollection(series);\r
53         if(title == null) title = "Trend";\r
54         if(xTitle == null) xTitle = "Value";\r
55         if(yTitle == null) yTitle = "Time";\r
56         scale = true;\r
57 \r
58 \r
59         final JFreeChart chart = ChartFactory.createXYLineChart(\r
60                 title,\r
61                 xTitle,\r
62                 yTitle,\r
63                 dataset,\r
64                 PlotOrientation.VERTICAL,\r
65                 false,\r
66                 true,\r
67                 false\r
68         );\r
69         final XYPlot plot = chart.getXYPlot();\r
70         ValueAxis axis = plot.getDomainAxis();\r
71         axis.setAutoRange(true);\r
72 //        axis.setFixedAutoRange(60000.0);  // 60 seconds\r
73 \r
74         component = new ChartPanel(chart, false);\r
75         ((ChartPanel)component).setRefreshBuffer(false);\r
76         component.setIgnoreRepaint(true); \r
77         component.setDoubleBuffered(false);\r
78         if(bounds != null) {\r
79             component.setBounds(0, 0, 0, 0);\r
80         }\r
81 \r
82         if(points != null) {\r
83             for(TrendPoint p : points) {\r
84                 try {\r
85                     series.add(p.getX(), p.getY());\r
86                 } catch(org.jfree.data.general.SeriesException e) {\r
87 \r
88                 }\r
89             }\r
90         }\r
91         super.init();\r
92     }\r
93
94     @Override
95     public void render(Graphics2D g2d) {
96         if (component != null) {
97             AffineTransform ot = g2d.getTransform();\r
98 \r
99             double scaleX = ot.getScaleX();
100             double scaleY = ot.getScaleY();
101 \r
102             if (transform == IdentityAffineTransform.INSTANCE)\r
103                 transform = new AffineTransform();
104             synchronized(transform) {
105                 transform.setToTranslation(bounds.getMinX(), bounds.getMinY());
106                 transform.scale(1/scaleX, 1/scaleY);
107             }
108             g2d.transform(transform);
109             int width = (int)(bounds.getWidth() * scaleX);
110             int height = (int)(bounds.getHeight() * scaleY);
111
112             component.setLocation((int)g2d.getTransform().getTranslateX(), (int)g2d.getTransform().getTranslateY());
113             if(component.getSize().getWidth() != width || component.getSize().getHeight() != height) {
114                 component.setSize(width, height);\r
115             }
116             component.paint(g2d);\r
117             \r
118             g2d.setTransform(ot);
119         }
120     }\r
121     
122     @SyncField("title")
123     public void setTitle(String title) {
124         this.title = title;
125         if(component != null)
126             ((ChartPanel)component).getChart().setTitle(title);
127     }
128
129     @SyncField("xTitle")
130     public void setXTitle(String xTitle) {
131         this.xTitle = xTitle;
132         if(component != null)\r
133             ((ChartPanel)component).getChart().getXYPlot().getDomainAxis().setLabel(xTitle);\r
134     }
135
136     @SyncField("yTitle")
137     public void setYTitle(String yTitle) {
138         this.yTitle = yTitle;
139         if(component != null)\r
140             ((ChartPanel)component).getChart().getXYPlot().getRangeAxis().setLabel(yTitle);\r
141     }
142
143     @SyncField("bounds")
144     public void setBounds(Rectangle2D bounds) {
145         this.bounds = bounds;\r
146 //        width = (int)bounds.getWidth();\r
147 //        height = (int)bounds.getHeight();
148     }
149
150     @SyncField("points")
151     protected void setPoints(List<TrendPoint> points) {
152         this.points = points;
153         if(series != null) {
154             series.clear();
155             for(TrendPoint p : points) {
156                 try {
157                     series.add(p.getX(), p.getY());
158                 } catch(org.jfree.data.general.SeriesException e) {
159
160                 }
161             }
162         }
163     }
164
165     @ClientSide
166     protected void appendPoints(List<TrendPoint> points) {
167         if(this.points == null) this.points = new ArrayList<TrendPoint>();
168         /**
169          * We need to have the same set of points on the both sides, so locally the points are just updated,
170          * but on remote side we send only the new points.
171          * In case we are running on local workbench, the point list is updated and in addition these points
172          * would be added to the list without this check.
173          * FIXME: find out some way to implement this without this check
174          */
175         if(location.equals(Location.REMOTE)) {
176             this.points.addAll(points);
177         }
178
179         for(TrendPoint p : points) {
180             try {
181                 series.add(p.getX(), p.getY());
182             } catch(org.jfree.data.general.SeriesException e) {
183
184             }
185         }
186     }
187
188     /**
189      * Update trend points. If
190      * 
191      * @param newpoints
192      */
193     public void updatePoints(List<TrendPoint> newpoints) {
194         if(points == null) points = new ArrayList<TrendPoint>();
195         for(int n = newpoints.size()-1; n >= 0; n--) {
196             int t = 0;
197             for(int o = points.size()-1; o >= 0; o--) {
198                 if(!newpoints.get(n-t).equals(points.get(o))) {
199                     break;
200                 }
201                 if(o == 0 || o < points.size()-10) {
202                     // Now we have 10 matching values, so n tells where the old points ends
203                     ArrayList<TrendPoint> appendedPoints = new ArrayList<TrendPoint>();
204                     for(int i = n; i < newpoints.size()-1; i++) {
205                         appendedPoints.add(newpoints.get(i));
206                     }
207                     points = new ArrayList<TrendPoint>(newpoints);
208                     if(appendedPoints != null && appendedPoints.size() > 0) {
209                         appendPoints(appendedPoints);
210                     }
211                     return;
212                 }
213                 if((n-t) == 0) {
214                     setPoints(newpoints);
215                     return;
216                 }
217                 t++;
218             }
219         }
220         setPoints(newpoints);
221     }
222 }