]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
c4a5accf98463263d08e4bad9cb35ac580cf9299
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2010 Association for Decentralized Information Management in\r
3  * 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.sysdyn.ui.properties.widgets.expressions;\r
13 \r
14 import java.awt.BasicStroke;\r
15 import java.awt.Frame;\r
16 import java.awt.event.ActionEvent;\r
17 import java.awt.event.ActionListener;\r
18 import java.awt.geom.Point2D;\r
19 import java.io.StringReader;\r
20 import java.util.ArrayList;\r
21 import java.util.Arrays;\r
22 import java.util.List;\r
23 import java.util.Map;\r
24 \r
25 import javax.swing.Timer;\r
26 \r
27 import org.eclipse.jface.layout.GridDataFactory;\r
28 import org.eclipse.jface.layout.GridLayoutFactory;\r
29 import org.eclipse.jface.text.BadLocationException;\r
30 import org.eclipse.jface.text.IDocument;\r
31 import org.eclipse.swt.SWT;\r
32 import org.eclipse.swt.awt.SWT_AWT;\r
33 import org.eclipse.swt.custom.VerifyKeyListener;\r
34 import org.eclipse.swt.events.FocusAdapter;\r
35 import org.eclipse.swt.events.FocusEvent;\r
36 import org.eclipse.swt.events.FocusListener;\r
37 import org.eclipse.swt.events.KeyListener;\r
38 import org.eclipse.swt.events.ModifyEvent;\r
39 import org.eclipse.swt.events.ModifyListener;\r
40 import org.eclipse.swt.graphics.Point;\r
41 import org.eclipse.swt.widgets.Composite;\r
42 import org.eclipse.swt.widgets.Label;\r
43 import org.jfree.chart.ChartFactory;\r
44 import org.jfree.chart.ChartPanel;\r
45 import org.jfree.chart.JFreeChart;\r
46 import org.jfree.chart.plot.PlotOrientation;\r
47 import org.jfree.data.xy.XYDataset;\r
48 import org.jfree.data.xy.XYSeries;\r
49 import org.jfree.data.xy.XYSeriesCollection;\r
50 import org.simantics.databoard.Bindings;\r
51 import org.simantics.db.ReadGraph;\r
52 import org.simantics.db.Resource;\r
53 import org.simantics.db.VirtualGraph;\r
54 import org.simantics.db.WriteGraph;\r
55 import org.simantics.db.common.request.WriteRequest;\r
56 import org.simantics.db.common.utils.OrderedSetUtils;\r
57 import org.simantics.db.exception.DatabaseException;\r
58 import org.simantics.db.procedure.Listener;\r
59 import org.simantics.db.request.Read;\r
60 import org.simantics.layer0.Layer0;\r
61 import org.simantics.layer0.utils.direct.GraphUtils;\r
62 import org.simantics.sysdyn.SysdynResource;\r
63 import org.simantics.sysdyn.tableParser.ParseException;\r
64 import org.simantics.sysdyn.tableParser.TableParser;\r
65 import org.simantics.sysdyn.tableParser.Token;\r
66 import org.simantics.ui.SimanticsUI;\r
67 \r
68 public class WithLookupExpression implements IExpression {\r
69 \r
70     private ExpressionField expression;\r
71     private ExpressionField lookup;\r
72     private ExpressionField lastSelectedText = expression;\r
73     private Timer updateChartTimer;\r
74 \r
75     private ChartPanel smallPanel;\r
76     private Frame smallFrame;\r
77 \r
78     private Resource expr;\r
79 \r
80     public WithLookupExpression(Resource expression) {\r
81         this.expr = expression;\r
82     }\r
83 \r
84     @Override\r
85     public void createExpressionFields(Composite parent, final Map<String, Object> data) {\r
86         GridLayoutFactory.fillDefaults().numColumns(3).applyTo(parent);\r
87 \r
88         updateChartTimer = new Timer(1000, new ActionListener() {\r
89 \r
90             @Override\r
91             public void actionPerformed(ActionEvent e) {\r
92                 updateChart();\r
93             }\r
94         });\r
95         updateChartTimer.setRepeats(false);\r
96 \r
97         String equation = data.get("equation") != null ? (String)data.get("equation") : "";\r
98         String lookupTable = data.get("lookup") != null ? (String)data.get("lookup") : "";\r
99 \r
100         Label l = new Label(parent, SWT.NONE);\r
101         l.setText("With\nLookup");\r
102 \r
103         expression = new ExpressionField(parent, SWT.BORDER);\r
104         expression.setExpression(equation);\r
105         GridDataFactory.fillDefaults().grab(true, true).applyTo(expression);\r
106 \r
107         expression.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
108 \r
109             @Override\r
110             public void focusLost(FocusEvent e) {\r
111                 lastSelectedText = expression;\r
112             }\r
113         });\r
114 \r
115         Composite chartContainer = new Composite(parent, SWT.NONE);\r
116         createChart(chartContainer, data);\r
117 \r
118 \r
119         l = new Label(parent, SWT.NONE);\r
120         l.setText("Lookup\ntable");\r
121 \r
122         lookup = new ExpressionField(parent, SWT.BORDER);\r
123         lookup.setExpression(lookupTable);\r
124         GridDataFactory.fillDefaults().grab(true, true).applyTo(lookup);\r
125 \r
126         lookup.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
127 \r
128             @Override\r
129             public void focusLost(FocusEvent e) {\r
130                 lastSelectedText = lookup;\r
131                 save(expr, data);\r
132             }\r
133         });\r
134 \r
135         lookup.getSourceViewer().getTextWidget().addModifyListener(new ModifyListener() {\r
136 \r
137             @Override\r
138             public void modifyText(ModifyEvent e) {\r
139                 if(!updateChartTimer.isRunning())\r
140                     updateChartTimer.start();\r
141                 else\r
142                     updateChartTimer.restart();\r
143             }\r
144         });\r
145 \r
146 \r
147         SimanticsUI.getSession().asyncRequest(new Read<String>() {\r
148 \r
149             @Override\r
150             public String perform(ReadGraph graph) throws DatabaseException {\r
151                 SysdynResource sr = SysdynResource.getInstance(graph);\r
152                 String result = "";\r
153                 if (expr != null && graph.isInstanceOf(expr, sr.WithLookupExpression)) {\r
154                     result = graph.getPossibleRelatedValue(expr, sr.WithLookupExpression_lookup);\r
155                 }\r
156                 return result;\r
157             }\r
158         }, new Listener<String>() {\r
159 \r
160             @Override\r
161             public void exception(Throwable t) {\r
162                 t.printStackTrace();\r
163             }\r
164 \r
165             @Override\r
166             public void execute(final String result) {\r
167                 if(lookup != null)\r
168                     lookup.getDisplay().asyncExec(new Runnable() {\r
169 \r
170                         @Override\r
171                         public void run() {\r
172                             lookup.setExpression(result);                            \r
173                         }\r
174                     });\r
175                 updateChart();\r
176             }\r
177 \r
178             @Override\r
179             public boolean isDisposed() {\r
180                 if(lookup != null && !lookup.isDisposed()) {\r
181                     return false;\r
182                 }\r
183                 return true;\r
184             }\r
185         });\r
186 \r
187         updateChart();\r
188     }\r
189 \r
190     @Override\r
191     public void focus() {\r
192         if(this.lastSelectedText != null) this.lastSelectedText.focus();        \r
193     }\r
194 \r
195     @Override\r
196     public List<ExpressionField> getExpressionFields() {\r
197         return Arrays.asList(this.expression, this.lookup);\r
198     }\r
199 \r
200     @Override\r
201     public void readData(final Resource expression, Map<String, Object> data) {\r
202 \r
203         class Auxiliary {\r
204             String equation, lookup;\r
205         }\r
206 \r
207         Auxiliary results = null;\r
208 \r
209         if (data.get("equation") == null) {\r
210             try {\r
211                 results = SimanticsUI.getSession().syncRequest(new Read<Auxiliary>() {\r
212 \r
213                     @Override\r
214                     public Auxiliary perform(ReadGraph graph) throws DatabaseException {\r
215                         Auxiliary results = new Auxiliary();\r
216                         SysdynResource sr = SysdynResource.getInstance(graph);\r
217                         if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) {\r
218                             results.equation = graph.getPossibleRelatedValue(expression, sr.WithLookupExpression_expression);\r
219                             results.lookup = graph.getPossibleRelatedValue(expression, sr.WithLookupExpression_lookup);\r
220                         } else {\r
221                             results.equation = "";\r
222                             results.lookup = "";\r
223                         }\r
224                         return results;\r
225                     }\r
226                 });\r
227             } catch (DatabaseException e1) {\r
228                 e1.printStackTrace();\r
229             }\r
230             data.put("equation", results.equation == null ? "" : results.equation);\r
231             data.put("lookup", results.lookup == null ? "" : results.lookup);\r
232         }\r
233 \r
234     }\r
235 \r
236     @Override\r
237     public void replaceSelection(String var) {\r
238         if(lastSelectedText != null) {\r
239             IDocument doc = lastSelectedText.getDocument();\r
240             try {\r
241                 Point selection = lastSelectedText.getSelection();\r
242                 doc.replace(selection.x, selection.y, var);\r
243                 lastSelectedText.setSelection(selection.x + var.length());\r
244             } catch (BadLocationException e) {\r
245                 e.printStackTrace();\r
246             }\r
247         }        \r
248     }\r
249 \r
250     @Override\r
251     public void save(final Resource expression, Map<String, Object> data) {\r
252         final String currentExpression = this.expression.getExpression();\r
253         final String currentLookupTable = lookup.getExpression();\r
254         String oldExpression = (String)data.get("equation");\r
255         String oldLookupTable = (String)data.get("lookup");\r
256 \r
257         if(oldExpression == null || oldLookupTable == null ||\r
258                 (currentExpression != null && currentLookupTable != null\r
259                         && (!currentExpression.equals(oldExpression) || \r
260                                 !currentLookupTable.equals(oldLookupTable)))) {\r
261             data.putAll(data);\r
262             data.put("equation", currentExpression);\r
263             data.put("lookup", currentLookupTable);\r
264             SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
265                 @Override\r
266                 public void perform(WriteGraph g)\r
267                 throws DatabaseException {\r
268                     SysdynResource sr = SysdynResource.getInstance(g);\r
269                     Layer0 l0 = Layer0.getInstance(g);\r
270                     \r
271                     if(!g.isInstanceOf(expr, sr.WithLookupExpression)) {\r
272                         \r
273                         \r
274                         Resource ownerList = OrderedSetUtils.getSingleOwnerList(g, expression);\r
275                         final Resource newExpression = GraphUtils.create2(g, sr.WithLookupExpression,\r
276                                         sr.HasMinX, 0.0,\r
277                                         sr.HasMaxX, 10.0,\r
278                                         sr.HasMinY, 0.0,\r
279                                         sr.HasMaxY, 10.0);\r
280                         String arrayRange = g.getPossibleRelatedValue(expression, sr.HasArrayRange, Bindings.STRING);\r
281                         if(arrayRange != null)\r
282                                 g.claimLiteral(newExpression, sr.HasArrayRange, arrayRange);\r
283                         \r
284                         final Resource variable = g.getSingleObject(ownerList, sr.HasExpressions_Inverse);\r
285                         OrderedSetUtils.replace(g, ownerList, expression, newExpression);\r
286                         g.deny(expression, l0.PartOf);\r
287                         g.claim(newExpression, l0.PartOf, variable);\r
288                         \r
289                                                 VirtualGraph runtime = g.getService(VirtualGraph.class);\r
290                                                 g.syncRequest(new WriteRequest(runtime) {\r
291                                                         @Override\r
292                                                         public void perform(WriteGraph graph) throws DatabaseException {\r
293                                                                 SysdynResource sr = SysdynResource.getInstance(graph);\r
294                                                                 if(graph.hasStatement(variable, sr.HasActiveExpression))\r
295                                                                         graph.deny(variable, sr.HasActiveExpression);\r
296                                                                 graph.claim(variable, sr.HasActiveExpression, newExpression);\r
297                                                         }\r
298                                                 }\r
299                                                 );\r
300                         expr = newExpression;\r
301                         \r
302                     }\r
303                     g.claimLiteral(expr, sr.WithLookupExpression_expression, currentExpression);\r
304                     g.claimLiteral(expr, sr.WithLookupExpression_lookup, currentLookupTable);\r
305                 }\r
306             });\r
307         }\r
308 \r
309     }\r
310 \r
311     @Override\r
312     public void updateData(Map<String, Object> data) {\r
313         if(this.expression != null && this.expression.getExpression() != null)\r
314             data.put("equation", this.expression.getExpression());\r
315         if(this.lookup != null && this.lookup.getExpression() != null)\r
316             data.put("lookup", this.lookup.getExpression());   \r
317     }\r
318 \r
319     @Override\r
320     public void addKeyListener(KeyListener listener) {\r
321         this.expression.getSourceViewer().getTextWidget().addKeyListener(listener);\r
322         this.lookup.getSourceViewer().getTextWidget().addKeyListener(listener);\r
323     }\r
324     \r
325         @Override\r
326         public void addVerifyKeyListener(VerifyKeyListener listener) {\r
327                 this.expression.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
328                 this.lookup.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
329         }\r
330 \r
331     @Override\r
332     public void addModifyListener(ModifyListener listener) {\r
333         this.expression.getSourceViewer().getTextWidget().addModifyListener(listener);\r
334         this.lookup.getSourceViewer().getTextWidget().addModifyListener(listener);\r
335     }\r
336 \r
337     @Override\r
338     public void addFocusListener(FocusListener listener) {\r
339         this.expression.getSourceViewer().getTextWidget().addFocusListener(listener);\r
340         this.lookup.getSourceViewer().getTextWidget().addFocusListener(listener);\r
341     }\r
342 \r
343     private void createChart(Composite composite, final Map<String, Object> data) {\r
344         GridLayoutFactory.fillDefaults().applyTo(composite);\r
345         GridDataFactory.fillDefaults().span(1, 2).hint(150, SWT.DEFAULT).applyTo(composite);\r
346         final Composite chartComposite = new Composite(composite, \r
347                 SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
348         GridDataFactory.fillDefaults().grab(true, true).applyTo(chartComposite);\r
349         smallFrame = SWT_AWT.new_Frame(chartComposite);\r
350 \r
351         XYDataset dataset = new XYSeriesCollection(new XYSeries("Lookup Table"));\r
352         JFreeChart chart = createChart(dataset);\r
353         smallPanel = new ChartPanel(chart);\r
354         smallFrame.add(smallPanel);\r
355 \r
356     }\r
357 \r
358     private static JFreeChart createChart(XYDataset dataset) {\r
359         JFreeChart chart = ChartFactory.createXYLineChart(\r
360                 null,\r
361                 null,\r
362                 null,\r
363                 dataset,\r
364                 PlotOrientation.VERTICAL,\r
365                 true,\r
366                 true,\r
367                 false\r
368         );\r
369         chart.removeLegend();\r
370         chart.getXYPlot().getDomainAxis().setTickLabelsVisible(true);\r
371         chart.getXYPlot().getDomainAxis().setAxisLineVisible(false);\r
372         chart.getXYPlot().getDomainAxis().setTickMarksVisible(true);\r
373         chart.getXYPlot().getRangeAxis().setTickLabelsVisible(true);\r
374         chart.getXYPlot().getRangeAxis().setAxisLineVisible(false);\r
375         chart.getXYPlot().getRangeAxis().setTickMarksVisible(true);\r
376         chart.getXYPlot().getRenderer().setSeriesStroke(0, new BasicStroke(3.0f));\r
377         return chart;\r
378     }\r
379 \r
380     private void updateChart() {\r
381         ArrayList<Point2D> dataPoints = new ArrayList<Point2D>();\r
382         TableParser parser = new TableParser(new StringReader(""));\r
383         parser.ReInit(new StringReader(lookup.getExpression()));\r
384         try {\r
385             parser.table();\r
386             ArrayList<Token> xTokens = parser.getXTokens();\r
387             ArrayList<Token> yTokens = parser.getYTokens();\r
388             for(int i = 0; i < xTokens.size(); i++) {\r
389                 dataPoints.add(new Point2D.Double(\r
390                         Double.parseDouble(xTokens.get(i).image), \r
391                         Double.parseDouble(yTokens.get(i).image)));\r
392             }\r
393         } catch (ParseException e1) {\r
394             this.lookup.setSyntaxError(e1.currentToken, "Syntax Error");\r
395             System.out.println("MESSAGE: " + e1.getMessage());\r
396             return;\r
397         }\r
398 \r
399         XYSeries series = new XYSeries("Lookup Table");\r
400         for(Point2D point : dataPoints) {\r
401             series.add(point.getX(), point.getY());\r
402         }\r
403         XYSeriesCollection dataset =  new XYSeriesCollection(series);\r
404         smallPanel.getChart().getXYPlot().setDataset(dataset);\r
405     }\r
406 \r
407 \r
408 }\r