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