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