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