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