]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
a0bcf27acf849328cd5fb6fca0e5783a46fbfba3
[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                 save(variable, data);\r
117             }\r
118         });\r
119 \r
120         lookup.getSourceViewer().getTextWidget().addModifyListener(new ModifyListener() {\r
121 \r
122             @Override\r
123             public void modifyText(ModifyEvent e) {\r
124                 if(!updateChartTimer.isRunning())\r
125                     updateChartTimer.start();\r
126                 else\r
127                     updateChartTimer.restart();\r
128             }\r
129         });\r
130 \r
131 \r
132         SimanticsUI.getSession().asyncRequest(new Read<String>() {\r
133 \r
134             @Override\r
135             public String perform(ReadGraph graph) throws DatabaseException {\r
136                 SysdynResource sr = SysdynResource.getInstance(graph);\r
137                 Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
138                 String result = "";\r
139                 if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) {\r
140                     result = graph.getRelatedValue(expression, sr.HasLookup);\r
141                 }\r
142                 return result;\r
143             }\r
144         }, new Listener<String>() {\r
145 \r
146             @Override\r
147             public void exception(Throwable t) {\r
148                 t.printStackTrace();\r
149             }\r
150 \r
151             @Override\r
152             public void execute(final String result) {\r
153                 if(lookup != null)\r
154                     lookup.getDisplay().asyncExec(new Runnable() {\r
155 \r
156                         @Override\r
157                         public void run() {\r
158                             lookup.setExpression(result);                            \r
159                         }\r
160                     });\r
161                 updateChart();\r
162             }\r
163 \r
164             @Override\r
165             public boolean isDisposed() {\r
166                 if(lookup != null && !lookup.isDisposed()) {\r
167                     return false;\r
168                 }\r
169                 return true;\r
170             }\r
171         });\r
172 \r
173         updateChart();\r
174     }\r
175 \r
176     @Override\r
177     public void focus() {\r
178         if(this.lastSelectedText != null) this.lastSelectedText.focus();        \r
179     }\r
180 \r
181     @Override\r
182     public List<ExpressionField> getExpressionFields() {\r
183         return Arrays.asList(this.expression, this.lookup);\r
184     }\r
185 \r
186     @Override\r
187     public void readData(final Resource variable, Map<String, Object> data) {\r
188 \r
189         class Auxiliary {\r
190             String equation, lookup;\r
191         }\r
192 \r
193         Auxiliary results = null;\r
194 \r
195         if (variable != null && data.get("equation") == null) {\r
196             try {\r
197                 results = SimanticsUI.getSession().syncRequest(new Read<Auxiliary>() {\r
198 \r
199                     @Override\r
200                     public Auxiliary perform(ReadGraph graph) throws DatabaseException {\r
201                         Auxiliary results = new Auxiliary();\r
202                         SysdynResource sr = SysdynResource.getInstance(graph);\r
203                         Resource expression = graph.getPossibleObject(variable, sr.HasExpression);\r
204                         if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) {\r
205                             results.equation = graph.getRelatedValue(expression, sr.HasEquation);\r
206                             results.lookup = graph.getRelatedValue(expression, sr.HasLookup);\r
207                         } else {\r
208                             results.equation = "";\r
209                             results.lookup = "";\r
210                         }\r
211                         return results;\r
212                     }\r
213                 });\r
214             } catch (DatabaseException e1) {\r
215                 e1.printStackTrace();\r
216             }\r
217             data.put("equation", results.equation);\r
218             data.put("lookup", results.lookup);\r
219         }\r
220 \r
221     }\r
222 \r
223     @Override\r
224     public void replaceSelection(String var) {\r
225         if(lastSelectedText != null) {\r
226             IDocument doc = lastSelectedText.getDocument();\r
227             try {\r
228                 Point selection = lastSelectedText.getSelection();\r
229                 doc.replace(selection.x, selection.y, var);\r
230                 lastSelectedText.setSelection(selection.x + var.length());\r
231             } catch (BadLocationException e) {\r
232                 e.printStackTrace();\r
233             }\r
234         }        \r
235     }\r
236 \r
237     @Override\r
238     public void save(final Resource variable, Map<String, Object> data) {\r
239         final String currentExpression = expression.getExpression();\r
240         final String currentLookupTable = lookup.getExpression();\r
241         String oldExpression = (String)data.get("equation");\r
242         String oldLookupTable = (String)data.get("lookup");\r
243 \r
244         if(oldExpression == null || oldLookupTable == null ||\r
245                 (currentExpression != null && currentLookupTable != null\r
246                         && (!currentExpression.equals(oldExpression) || \r
247                                 !currentLookupTable.equals(oldLookupTable)))) {\r
248             data.putAll(data);\r
249             data.put("equation", currentExpression);\r
250             data.put("lookup", currentLookupTable);\r
251             SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
252                 @Override\r
253                 public void perform(WriteGraph g)\r
254                 throws DatabaseException {\r
255                     SysdynResource sr = SysdynResource.getInstance(g);\r
256                     Resource expression = g.getPossibleObject(variable, sr.HasExpression);\r
257                     Layer0 l0 = Layer0.getInstance(g);\r
258                     if(expression != null && !g.isInstanceOf(expression, sr.WithLookupExpression)) {\r
259                         g.deny(variable, sr.HasExpression);\r
260                         expression = null;\r
261                     }\r
262                     if(expression == null) {\r
263                         expression = g.newResource();\r
264                         g.claim(expression, l0.InstanceOf, null, sr.WithLookupExpression);\r
265                         g.claim(variable, sr.HasExpression, expression);\r
266                         g.claimLiteral(expression, sr.HasMinX, 0.0);\r
267                         g.claimLiteral(expression, sr.HasMaxX, 10.0);\r
268                         g.claimLiteral(expression, sr.HasMinY, 0.0);\r
269                         g.claimLiteral(expression, sr.HasMaxY, 10.0);\r
270 \r
271                     } \r
272                     g.claimLiteral(expression, sr.HasEquation, currentExpression);\r
273                     g.claimLiteral(expression, sr.HasLookup, currentLookupTable);\r
274                 }\r
275             });\r
276         }\r
277 \r
278     }\r
279 \r
280     @Override\r
281     public void updateData(Map<String, Object> data) {\r
282         if(this.expression != null && this.expression.getExpression() != null)\r
283             data.put("equation", this.expression.getExpression());\r
284         if(this.lookup != null && this.lookup.getExpression() != null)\r
285             data.put("lookup", this.lookup.getExpression());   \r
286     }\r
287 \r
288     @Override\r
289     public void addKeyListener(KeyListener listener) {\r
290         this.expression.getSourceViewer().getTextWidget().addKeyListener(listener);\r
291         this.lookup.getSourceViewer().getTextWidget().addKeyListener(listener);\r
292     }\r
293 \r
294     @Override\r
295     public void addModifyListener(ModifyListener listener) {\r
296         this.expression.getSourceViewer().getTextWidget().addModifyListener(listener);\r
297         this.lookup.getSourceViewer().getTextWidget().addModifyListener(listener);\r
298     }\r
299 \r
300     @Override\r
301     public void addFocusListener(FocusListener listener) {\r
302         this.expression.getSourceViewer().getTextWidget().addFocusListener(listener);\r
303         this.lookup.getSourceViewer().getTextWidget().addFocusListener(listener);\r
304     }\r
305 \r
306     private void createChart(Composite composite, final Map<String, Object> data) {\r
307         GridLayoutFactory.fillDefaults().applyTo(composite);\r
308         GridDataFactory.fillDefaults().span(1, 2).hint(150, SWT.DEFAULT).applyTo(composite);\r
309         final Composite chartComposite = new Composite(composite, \r
310                 SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
311         GridDataFactory.fillDefaults().grab(true, true).applyTo(chartComposite);\r
312         smallFrame = SWT_AWT.new_Frame(chartComposite);\r
313 \r
314         XYDataset dataset = new XYSeriesCollection(new XYSeries("Lookup Table"));\r
315         JFreeChart chart = createChart(dataset);\r
316         smallPanel = new ChartPanel(chart);\r
317         smallFrame.add(smallPanel);\r
318 \r
319     }\r
320 \r
321     private static JFreeChart createChart(XYDataset dataset) {\r
322         JFreeChart chart = ChartFactory.createXYLineChart(\r
323                 null,\r
324                 null,\r
325                 null,\r
326                 dataset,\r
327                 PlotOrientation.VERTICAL,\r
328                 true,\r
329                 true,\r
330                 false\r
331         );\r
332         chart.removeLegend();\r
333         chart.getXYPlot().getDomainAxis().setTickLabelsVisible(true);\r
334         chart.getXYPlot().getDomainAxis().setAxisLineVisible(false);\r
335         chart.getXYPlot().getDomainAxis().setTickMarksVisible(true);\r
336         chart.getXYPlot().getRangeAxis().setTickLabelsVisible(true);\r
337         chart.getXYPlot().getRangeAxis().setAxisLineVisible(false);\r
338         chart.getXYPlot().getRangeAxis().setTickMarksVisible(true);\r
339         chart.getXYPlot().getRenderer().setSeriesStroke(0, new BasicStroke(3.0f));\r
340         return chart;\r
341     }\r
342 \r
343     private void updateChart() {\r
344         ArrayList<Point2D> dataPoints = new ArrayList<Point2D>();\r
345         TableParser parser = new TableParser(new StringReader(""));\r
346         parser.ReInit(new StringReader(lookup.getExpression()));\r
347         try {\r
348             parser.table();\r
349             ArrayList<Token> xTokens = parser.getXTokens();\r
350             ArrayList<Token> yTokens = parser.getYTokens();\r
351             for(int i = 0; i < xTokens.size(); i++) {\r
352                 dataPoints.add(new Point2D.Double(\r
353                         Double.parseDouble(xTokens.get(i).image), \r
354                         Double.parseDouble(yTokens.get(i).image)));\r
355             }\r
356         } catch (ParseException e1) {\r
357 //            e1.printStackTrace();\r
358             return;\r
359         }\r
360 \r
361         XYSeries series = new XYSeries("Lookup Table");\r
362         for(Point2D point : dataPoints) {\r
363             series.add(point.getX(), point.getY());\r
364         }\r
365         XYSeriesCollection dataset =  new XYSeriesCollection(series);\r
366         smallPanel.getChart().getXYPlot().setDataset(dataset);\r
367     }\r
368 \r
369 \r
370 }\r