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