1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.ui.properties.widgets;
\r
14 import java.awt.BasicStroke;
\r
15 import java.awt.Color;
\r
16 import java.awt.GridLayout;
\r
17 import java.awt.geom.Ellipse2D;
\r
18 import java.io.StringReader;
\r
19 import java.util.ArrayList;
\r
20 import java.util.Iterator;
\r
22 import javax.swing.JComponent;
\r
23 import javax.swing.JPanel;
\r
25 import org.eclipse.jface.layout.GridDataFactory;
\r
26 import org.eclipse.jface.viewers.ISelection;
\r
27 import org.eclipse.swt.SWT;
\r
28 import org.eclipse.swt.widgets.Composite;
\r
29 import org.jfree.chart.ChartFactory;
\r
30 import org.jfree.chart.JFreeChart;
\r
31 import org.jfree.chart.axis.ValueAxis;
\r
32 import org.jfree.chart.plot.PlotOrientation;
\r
33 import org.jfree.chart.plot.XYPlot;
\r
34 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
\r
35 import org.jfree.data.general.SeriesChangeEvent;
\r
36 import org.jfree.data.general.SeriesChangeListener;
\r
37 import org.jfree.data.xy.XYDataItem;
\r
38 import org.jfree.data.xy.XYDataset;
\r
39 import org.jfree.data.xy.XYSeries;
\r
40 import org.jfree.data.xy.XYSeriesCollection;
\r
41 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
\r
42 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
\r
43 import org.simantics.db.ReadGraph;
\r
44 import org.simantics.db.Resource;
\r
45 import org.simantics.db.WriteGraph;
\r
46 import org.simantics.db.common.request.WriteRequest;
\r
47 import org.simantics.db.exception.DatabaseException;
\r
48 import org.simantics.db.management.ISessionContext;
\r
49 import org.simantics.db.procedure.Listener;
\r
50 import org.simantics.db.request.Read;
\r
51 import org.simantics.sysdyn.SysdynResource;
\r
52 import org.simantics.sysdyn.tableParser.ParseException;
\r
53 import org.simantics.sysdyn.tableParser.TableParser;
\r
54 import org.simantics.sysdyn.tableParser.Token;
\r
55 import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupChartPanel;
\r
56 import org.simantics.ui.SimanticsUI;
\r
57 import org.simantics.utils.ui.ISelectionUtils;
\r
58 import org.simantics.utils.ui.SWTAWTComponent;
\r
60 public class ChartWidget implements Widget {
\r
63 LookupChartPanel chartPanel;
\r
64 SWTAWTComponent swtawtcomponent;
\r
66 public ChartWidget(Composite parent, WidgetSupport support, int style) {
\r
67 support.register(this);
\r
68 chartPanel = new LookupChartPanel(createChart());
\r
69 chartPanel.setMouseZoomable(true, false);
\r
70 chartPanel.setDomainZoomable(false);
\r
71 chartPanel.setRangeZoomable(false);
\r
73 swtawtcomponent = new SWTAWTComponent(parent, SWT.BORDER) {
\r
75 protected JComponent createSwingComponent() {
\r
76 JPanel panel = new JPanel();
\r
77 panel.setLayout(new GridLayout(1, 1));
\r
78 panel.add(chartPanel);
\r
83 GridDataFactory.fillDefaults().grab(true, true).applyTo(swtawtcomponent);
\r
84 swtawtcomponent.populate();
\r
89 public void setInput(ISessionContext context, Object input) {
\r
91 final Resource expression = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class);
\r
94 Double minX, minY, maxX, maxY;
\r
99 SimanticsUI.getSession().syncRequest(new Read<Auxiliary>() {
\r
102 public Auxiliary perform(ReadGraph graph) throws DatabaseException {
\r
103 SysdynResource sr = SysdynResource.getInstance(graph);
\r
104 if(!graph.isInstanceOf(expression, sr.WithLookupExpression))
\r
106 Auxiliary auxiliary = new Auxiliary();
\r
107 auxiliary.minX = graph.getPossibleRelatedValue(expression, sr.WithLookupExpression_minX);
\r
108 auxiliary.maxX = graph.getPossibleRelatedValue(expression, sr.WithLookupExpression_maxX);
\r
109 auxiliary.minY = graph.getPossibleRelatedValue(expression, sr.WithLookupExpression_minY);
\r
110 auxiliary.maxY = graph.getPossibleRelatedValue(expression, sr.WithLookupExpression_maxY);
\r
111 auxiliary.table = graph.getPossibleRelatedValue(expression, sr.WithLookupExpression_lookup);
\r
114 }, new Listener<Auxiliary>() {
\r
117 public void exception(Throwable t) {
\r
118 t.printStackTrace();
\r
122 public void execute(Auxiliary result) {
\r
123 if(result == null) return;
\r
124 XYDataset dataset = createDataset(result.table);
\r
125 chartPanel.resetChart(dataset);
\r
126 chartPanel.addSeriesChangeListener(new _SeriesChangeListener(expression));
\r
128 XYPlot plot = (XYPlot) chart.getPlot();
\r
129 ValueAxis rangeAxis = plot.getRangeAxis();
\r
130 rangeAxis.setAutoRange(false);
\r
131 if(result.minY == null) result.minY = rangeAxis.getLowerBound();
\r
132 if(result.maxY == null) result.maxY = rangeAxis.getUpperBound();
\r
133 rangeAxis.setRange(result.minY, result.maxY);
\r
134 ValueAxis domainAxis = plot.getDomainAxis();
\r
135 domainAxis.setAutoRange(false);
\r
136 if(result.minX == null) result.minX = domainAxis.getLowerBound();
\r
137 if(result.maxX == null) result.maxX = domainAxis.getUpperBound();
\r
138 domainAxis.setRange(result.minX, result.maxX);
\r
143 public boolean isDisposed() {
\r
144 return swtawtcomponent.isDisposed();
\r
148 } catch (DatabaseException e) {
\r
149 e.printStackTrace();
\r
153 private JFreeChart createChart() {
\r
154 XYDataset dataset = createDataset(null);
\r
155 chart = ChartFactory.createXYLineChart(null, null, null,
\r
156 dataset, PlotOrientation.VERTICAL, false, true, false);
\r
157 XYPlot plot = (XYPlot) chart.getPlot();
\r
158 XYLineAndShapeRenderer renderer
\r
159 = (XYLineAndShapeRenderer) plot.getRenderer();
\r
160 renderer.setBaseShapesVisible(true);
\r
161 renderer.setDrawOutlines(true);
\r
162 renderer.setUseFillPaint(true);
\r
163 renderer.setBaseFillPaint(Color.white);
\r
164 renderer.setSeriesStroke(0, new BasicStroke(3.0f));
\r
165 renderer.setSeriesOutlineStroke(0, new BasicStroke(2.0f));
\r
166 renderer.setSeriesShape(0, new Ellipse2D.Double(-5.0, -5.0, 10.0, 10.0));
\r
170 public XYDataset createDataset(String table) {
\r
171 XYSeries series = new XYSeries("Series");
\r
173 if(table != null) {
\r
174 TableParser parser = new TableParser(new StringReader(""));
\r
175 parser.ReInit(new StringReader(table));
\r
178 ArrayList<Token> xTokens = parser.getXTokens();
\r
179 ArrayList<Token> yTokens = parser.getYTokens();
\r
180 for(int i = 0; i < xTokens.size(); i++) {
\r
182 Double.parseDouble(xTokens.get(i).image),
\r
183 Double.parseDouble(yTokens.get(i).image));
\r
185 } catch (ParseException e1) {
\r
189 XYSeriesCollection dataset = new XYSeriesCollection();
\r
190 dataset.addSeries(series);
\r
194 public LookupChartPanel getChartPanel() {
\r
195 return this.chartPanel;
\r
198 public JFreeChart getChart() {
\r
202 private class _SeriesChangeListener implements SeriesChangeListener {
\r
204 Resource expression;
\r
206 public _SeriesChangeListener(Resource expression) {
\r
207 this.expression = expression;
\r
210 public void seriesChanged(SeriesChangeEvent event) {
\r
211 if(chartPanel.isDragging()) return;
\r
213 StringBuilder b = new StringBuilder();
\r
215 XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset();
\r
216 XYSeries series = collection.getSeries(0);
\r
217 if(series.isEmpty())
\r
219 Iterator<?> iterator = series.getItems().iterator();
\r
220 while(iterator.hasNext()){
\r
221 XYDataItem item = (XYDataItem)iterator.next();
\r
222 b.append("{" + item.getX() + "," + item.getY() + "}");
\r
223 if(iterator.hasNext())
\r
227 final String table = b.toString();
\r
229 SimanticsUI.getSession().asyncRequest(new WriteRequest() {
\r
232 public void perform(WriteGraph graph) throws DatabaseException {
\r
233 SysdynResource sr = SysdynResource.getInstance(graph);
\r
234 graph.claimLiteral(expression, sr.WithLookupExpression_lookup, table);
\r