]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
619aeaf1a6d5c6214ee458ade4b83dfd22ffbca6
[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.Builtins;\r
39 import org.simantics.db.ReadGraph;\r
40 import org.simantics.db.Resource;\r
41 import org.simantics.db.WriteGraph;\r
42 import org.simantics.db.common.request.WriteRequest;\r
43 import org.simantics.db.exception.DatabaseException;\r
44 import org.simantics.db.procedure.Listener;\r
45 import org.simantics.db.request.Read;\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 \r
241         if(currentExpression != null && currentLookupTable != null) {\r
242             data.putAll(data);\r
243             data.put("equation", currentExpression);\r
244             data.put("lookup", currentLookupTable);\r
245             SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
246                 @Override\r
247                 public void perform(WriteGraph g)\r
248                 throws DatabaseException {\r
249                     SysdynResource sr = SysdynResource.getInstance(g);\r
250                     Resource expression = g.getPossibleObject(variable, sr.HasExpression);\r
251                     Builtins b = g.getBuiltins();\r
252                     if(expression != null) {\r
253                         g.deny(variable, sr.HasExpression);\r
254                     }\r
255                     expression = g.newResource();\r
256                     g.claim(expression, b.InstanceOf, null, sr.WithLookupExpression);\r
257                     g.claim(variable, sr.HasExpression, expression);\r
258                     g.claimValue(expression, sr.HasEquation, currentExpression);\r
259                     g.claimValue(expression, sr.HasLookup, currentLookupTable);\r
260                     if(!g.hasStatement(expression, sr.HasMinX))\r
261                         g.claimValue(expression, sr.HasMinX, 0.0);\r
262                     if(!g.hasStatement(expression, sr.HasMaxX))\r
263                         g.claimValue(expression, sr.HasMaxX, 10.0);\r
264                     if(!g.hasStatement(expression, sr.HasMinY))\r
265                         g.claimValue(expression, sr.HasMinY, 0.0);\r
266                     if(!g.hasStatement(expression, sr.HasMaxY))\r
267                         g.claimValue(expression, sr.HasMaxY, 10.0);\r
268                 }\r
269             });\r
270         }\r
271 \r
272     }\r
273 \r
274     @Override\r
275     public void updateData(Map<String, Object> data) {\r
276         if(this.expression != null && this.expression.getExpression() != null)\r
277             data.put("equation", this.expression.getExpression());\r
278         if(this.lookup != null && this.lookup.getExpression() != null)\r
279             data.put("lookup", this.lookup.getExpression());   \r
280     }\r
281 \r
282     @Override\r
283     public void addKeyListener(KeyListener listener) {\r
284         this.expression.getSourceViewer().getTextWidget().addKeyListener(listener);\r
285         this.lookup.getSourceViewer().getTextWidget().addKeyListener(listener);\r
286     }\r
287 \r
288     @Override\r
289     public void addModifyListener(ModifyListener listener) {\r
290         this.expression.getSourceViewer().getTextWidget().addModifyListener(listener);\r
291         this.lookup.getSourceViewer().getTextWidget().addModifyListener(listener);\r
292     }\r
293 \r
294     @Override\r
295     public void addFocusListener(FocusListener listener) {\r
296         this.expression.getSourceViewer().getTextWidget().addFocusListener(listener);\r
297         this.lookup.getSourceViewer().getTextWidget().addFocusListener(listener);\r
298     }\r
299 \r
300     private void createChart(Composite composite, final Map<String, Object> data) {\r
301         GridLayoutFactory.fillDefaults().applyTo(composite);\r
302         GridDataFactory.fillDefaults().span(1, 2).hint(150, SWT.DEFAULT).applyTo(composite);\r
303         final Composite chartComposite = new Composite(composite, \r
304                 SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
305         GridDataFactory.fillDefaults().grab(true, true).applyTo(chartComposite);\r
306         smallFrame = SWT_AWT.new_Frame(chartComposite);\r
307 \r
308         XYDataset dataset = new XYSeriesCollection(new XYSeries("Lookup Table"));\r
309         JFreeChart chart = createChart(dataset);\r
310         smallPanel = new ChartPanel(chart);\r
311         smallFrame.add(smallPanel);\r
312 \r
313     }\r
314 \r
315     private static JFreeChart createChart(XYDataset dataset) {\r
316         JFreeChart chart = ChartFactory.createXYLineChart(\r
317                 null,\r
318                 null,\r
319                 null,\r
320                 dataset,\r
321                 PlotOrientation.VERTICAL,\r
322                 true,\r
323                 true,\r
324                 false\r
325         );\r
326         chart.removeLegend();\r
327         chart.getXYPlot().getDomainAxis().setTickLabelsVisible(false);\r
328         chart.getXYPlot().getDomainAxis().setAxisLineVisible(false);\r
329         chart.getXYPlot().getDomainAxis().setTickMarksVisible(false);\r
330         chart.getXYPlot().getRangeAxis().setTickLabelsVisible(false);\r
331         chart.getXYPlot().getRangeAxis().setAxisLineVisible(false);\r
332         chart.getXYPlot().getRangeAxis().setTickMarksVisible(false);\r
333         chart.getXYPlot().getRenderer().setSeriesStroke(0, new BasicStroke(3.0f));\r
334         return chart;\r
335     }\r
336 \r
337     private void updateChart() {\r
338         ArrayList<Point2D> dataPoints = new ArrayList<Point2D>();\r
339         TableParser parser = new TableParser(new StringReader(""));\r
340         parser.ReInit(new StringReader(lookup.getExpression()));\r
341         try {\r
342             parser.table();\r
343             ArrayList<Token> xTokens = parser.getXTokens();\r
344             for(Token token : xTokens) {\r
345                 dataPoints.add(new Point2D.Double(\r
346                         Double.parseDouble(token.image), \r
347                         Double.parseDouble(token.next.next.image)));\r
348             }\r
349         } catch (ParseException e1) {\r
350             return;\r
351         }\r
352 \r
353         if(dataPoints.size() == 0) return;\r
354 \r
355         XYSeries series = new XYSeries("Lookup Table");\r
356         for(Point2D point : dataPoints) {\r
357             series.add(point.getX(), point.getY());\r
358         }\r
359         XYSeriesCollection dataset =  new XYSeriesCollection(series);\r
360         smallPanel.getChart().getXYPlot().setDataset(dataset);\r
361     }\r
362 \r
363 \r
364 }\r