]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.scenegraph.swing/src/org/simantics/scenegraph/swing/JFreeTrendNode.java b/bundles/org.simantics.scenegraph.swing/src/org/simantics/scenegraph/swing/JFreeTrendNode.java
new file mode 100644 (file)
index 0000000..380aa5c
--- /dev/null
@@ -0,0 +1,222 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.scenegraph.swing;
+
+import java.awt.Graphics2D;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.swing.JPanel;\r
+\r
+import org.jfree.chart.ChartFactory;\r
+import org.jfree.chart.ChartPanel;\r
+import org.jfree.chart.JFreeChart;\r
+import org.jfree.chart.axis.ValueAxis;\r
+import org.jfree.chart.plot.PlotOrientation;\r
+import org.jfree.chart.plot.XYPlot;\r
+import org.jfree.data.xy.XYSeries;\r
+import org.jfree.data.xy.XYSeriesCollection;\r
+import org.simantics.scenegraph.ExportableWidget.RasterOutputWidget;\r
+import org.simantics.scenegraph.g2d.IdentityAffineTransform;\r
+import org.simantics.scenegraph.g2d.nodes.Trend2DNode.TrendPoint;\r
+\r
+@RasterOutputWidget
+public class JFreeTrendNode extends ComponentNode<JPanel> {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 8508750881358776559L;
+
+    protected String title = null;
+    protected String yTitle = null;
+    protected String xTitle = null;
+    protected transient List<TrendPoint> points = null;
+
+    protected transient XYSeries series = null;\r
+    
+    @Override\r
+    public void init() {\r
+        series = new XYSeries("Trend");\r
+        final XYSeriesCollection dataset = new XYSeriesCollection(series);\r
+        if(title == null) title = "Trend";\r
+        if(xTitle == null) xTitle = "Value";\r
+        if(yTitle == null) yTitle = "Time";\r
+       scale = true;\r
+\r
+\r
+        final JFreeChart chart = ChartFactory.createXYLineChart(\r
+                title,\r
+                xTitle,\r
+                yTitle,\r
+                dataset,\r
+                PlotOrientation.VERTICAL,\r
+                false,\r
+                true,\r
+                false\r
+        );\r
+        final XYPlot plot = chart.getXYPlot();\r
+        ValueAxis axis = plot.getDomainAxis();\r
+        axis.setAutoRange(true);\r
+//        axis.setFixedAutoRange(60000.0);  // 60 seconds\r
+\r
+        component = new ChartPanel(chart, false);\r
+        ((ChartPanel)component).setRefreshBuffer(false);\r
+        component.setIgnoreRepaint(true); \r
+        component.setDoubleBuffered(false);\r
+        if(bounds != null) {\r
+            component.setBounds(0, 0, 0, 0);\r
+        }\r
+\r
+        if(points != null) {\r
+            for(TrendPoint p : points) {\r
+                try {\r
+                    series.add(p.getX(), p.getY());\r
+                } catch(org.jfree.data.general.SeriesException e) {\r
+\r
+                }\r
+            }\r
+        }\r
+        super.init();\r
+    }\r
+
+    @Override
+    public void render(Graphics2D g2d) {
+        if (component != null) {
+            AffineTransform ot = g2d.getTransform();\r
+\r
+            double scaleX = ot.getScaleX();
+            double scaleY = ot.getScaleY();
+\r
+            if (transform == IdentityAffineTransform.INSTANCE)\r
+                transform = new AffineTransform();
+            synchronized(transform) {
+                transform.setToTranslation(bounds.getMinX(), bounds.getMinY());
+                transform.scale(1/scaleX, 1/scaleY);
+            }
+            g2d.transform(transform);
+            int width = (int)(bounds.getWidth() * scaleX);
+            int height = (int)(bounds.getHeight() * scaleY);
+
+            component.setLocation((int)g2d.getTransform().getTranslateX(), (int)g2d.getTransform().getTranslateY());
+            if(component.getSize().getWidth() != width || component.getSize().getHeight() != height) {
+               component.setSize(width, height);\r
+            }
+            component.paint(g2d);\r
+            \r
+            g2d.setTransform(ot);
+        }
+    }\r
+    
+    @SyncField("title")
+    public void setTitle(String title) {
+        this.title = title;
+        if(component != null)
+            ((ChartPanel)component).getChart().setTitle(title);
+    }
+
+    @SyncField("xTitle")
+    public void setXTitle(String xTitle) {
+        this.xTitle = xTitle;
+        if(component != null)\r
+            ((ChartPanel)component).getChart().getXYPlot().getDomainAxis().setLabel(xTitle);\r
+    }
+
+    @SyncField("yTitle")
+    public void setYTitle(String yTitle) {
+        this.yTitle = yTitle;
+        if(component != null)\r
+            ((ChartPanel)component).getChart().getXYPlot().getRangeAxis().setLabel(yTitle);\r
+    }
+
+    @SyncField("bounds")
+    public void setBounds(Rectangle2D bounds) {
+        this.bounds = bounds;\r
+//        width = (int)bounds.getWidth();\r
+//        height = (int)bounds.getHeight();
+    }
+
+    @SyncField("points")
+    protected void setPoints(List<TrendPoint> points) {
+        this.points = points;
+        if(series != null) {
+            series.clear();
+            for(TrendPoint p : points) {
+                try {
+                    series.add(p.getX(), p.getY());
+                } catch(org.jfree.data.general.SeriesException e) {
+
+                }
+            }
+        }
+    }
+
+    @ClientSide
+    protected void appendPoints(List<TrendPoint> points) {
+        if(this.points == null) this.points = new ArrayList<TrendPoint>();
+        /**
+         * We need to have the same set of points on the both sides, so locally the points are just updated,
+         * but on remote side we send only the new points.
+         * In case we are running on local workbench, the point list is updated and in addition these points
+         * would be added to the list without this check.
+         * FIXME: find out some way to implement this without this check
+         */
+        if(location.equals(Location.REMOTE)) {
+            this.points.addAll(points);
+        }
+
+        for(TrendPoint p : points) {
+            try {
+                series.add(p.getX(), p.getY());
+            } catch(org.jfree.data.general.SeriesException e) {
+
+            }
+        }
+    }
+
+    /**
+     * Update trend points. If
+     * 
+     * @param newpoints
+     */
+    public void updatePoints(List<TrendPoint> newpoints) {
+        if(points == null) points = new ArrayList<TrendPoint>();
+        for(int n = newpoints.size()-1; n >= 0; n--) {
+            int t = 0;
+            for(int o = points.size()-1; o >= 0; o--) {
+                if(!newpoints.get(n-t).equals(points.get(o))) {
+                    break;
+                }
+                if(o == 0 || o < points.size()-10) {
+                    // Now we have 10 matching values, so n tells where the old points ends
+                    ArrayList<TrendPoint> appendedPoints = new ArrayList<TrendPoint>();
+                    for(int i = n; i < newpoints.size()-1; i++) {
+                        appendedPoints.add(newpoints.get(i));
+                    }
+                    points = new ArrayList<TrendPoint>(newpoints);
+                    if(appendedPoints != null && appendedPoints.size() > 0) {
+                        appendPoints(appendedPoints);
+                    }
+                    return;
+                }
+                if((n-t) == 0) {
+                    setPoints(newpoints);
+                    return;
+                }
+                t++;
+            }
+        }
+        setPoints(newpoints);
+    }
+}