]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
258ee4849eba235d138fb1bf86edf5a29608a4b1
[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.util.Arrays;\r
15 import java.util.List;\r
16 import java.util.Map;\r
17 \r
18 import org.eclipse.jface.layout.GridDataFactory;\r
19 import org.eclipse.jface.layout.GridLayoutFactory;\r
20 import org.eclipse.jface.text.BadLocationException;\r
21 import org.eclipse.jface.text.IDocument;\r
22 import org.eclipse.swt.SWT;\r
23 import org.eclipse.swt.custom.VerifyKeyListener;\r
24 import org.eclipse.swt.events.FocusAdapter;\r
25 import org.eclipse.swt.events.FocusEvent;\r
26 import org.eclipse.swt.events.FocusListener;\r
27 import org.eclipse.swt.events.KeyListener;\r
28 import org.eclipse.swt.events.ModifyEvent;\r
29 import org.eclipse.swt.events.ModifyListener;\r
30 import org.eclipse.swt.events.SelectionAdapter;\r
31 import org.eclipse.swt.events.SelectionEvent;\r
32 import org.eclipse.swt.graphics.Point;\r
33 import org.eclipse.swt.widgets.Combo;\r
34 import org.eclipse.swt.widgets.Composite;\r
35 import org.eclipse.swt.widgets.Label;\r
36 import org.eclipse.swt.widgets.Spinner;\r
37 import org.eclipse.swt.widgets.Table;\r
38 import org.simantics.databoard.Bindings;\r
39 import org.simantics.db.ReadGraph;\r
40 import org.simantics.db.Resource;\r
41 import org.simantics.db.VirtualGraph;\r
42 import org.simantics.db.WriteGraph;\r
43 import org.simantics.db.common.CommentMetadata;\r
44 import org.simantics.db.common.request.WriteRequest;\r
45 import org.simantics.db.common.utils.ListUtils;\r
46 import org.simantics.db.exception.DatabaseException;\r
47 import org.simantics.db.request.Read;\r
48 import org.simantics.layer0.Layer0;\r
49 import org.simantics.layer0.utils.direct.GraphUtils;\r
50 import org.simantics.sysdyn.SysdynResource;\r
51 import org.simantics.ui.SimanticsUI;\r
52 \r
53 /**\r
54  * IExpression for displaying fields of DelayExpression\r
55  * @author Teemu Lempinen\r
56  * @author Tuomas Miettinen\r
57  *\r
58  */\r
59 public class DelayExpression implements IExpression {\r
60 \r
61     private ExpressionField equation, delayTime, initialValue;\r
62     private ExpressionField lastSelectedText;\r
63     private Spinner order;\r
64     private final ExpressionWidgetInput input;\r
65     private Resource expression;\r
66         private Combo delayTypeCombo;\r
67 \r
68     /**\r
69      * Creates a new DelayExpression\r
70      * @param expression\r
71      */\r
72     public DelayExpression(ExpressionWidgetInput input) {\r
73         this.input = input;\r
74         this.expression = input.expression;\r
75     }\r
76 \r
77     /**\r
78      * Displays the fields for delayExpression\r
79      */\r
80     @Override\r
81     public void createExpressionFields(Composite parent, final Map<String, Object> data, Table allowedVariables) {\r
82         // Get possible existing data\r
83         GridLayoutFactory.fillDefaults().numColumns(5).applyTo(parent);\r
84         String eq = data.get("equation") != null ? (String)data.get("equation") : "";\r
85         String dt = data.get("delayTime") != null ? (String)data.get("delayTime") : "";\r
86         String iv = data.get("initialValue") != null ? (String)data.get("initialValue") : "";\r
87         int o = data.get("order") != null ? (Integer)data.get("order") : 3;\r
88 \r
89         Label l = new Label(parent, SWT.NONE);\r
90         l.setText("Expression");\r
91 \r
92         // Equation that is delayed\r
93         equation = new ExpressionField(parent, SWT.BORDER, allowedVariables, true, input);\r
94         equation.setExpression(eq);\r
95         GridDataFactory.fillDefaults().span(4, 1).grab(true, true).applyTo(equation);\r
96         equation.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
97 \r
98             @Override\r
99             public void focusLost(FocusEvent e) {\r
100                 lastSelectedText = equation;\r
101             }\r
102         });\r
103 \r
104         l = new Label(parent, SWT.NONE);\r
105         l.setText("Delay time");\r
106 \r
107         // How much the equation is delayed\r
108         delayTime = new ExpressionField(parent, SWT.BORDER, allowedVariables, true, input);\r
109         delayTime.setExpression(dt);\r
110         GridDataFactory.fillDefaults().span(4, 1).grab(true, true).applyTo(delayTime);\r
111 \r
112         delayTime.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
113 \r
114             @Override\r
115             public void focusLost(FocusEvent e) {\r
116                 lastSelectedText = delayTime;\r
117             }\r
118         });\r
119 \r
120         l = new Label(parent, SWT.NONE);\r
121         l.setText("Initial value");\r
122 \r
123         // What is the initial value of the delay (empty == same as equation)\r
124         initialValue = new ExpressionField(parent, SWT.BORDER, allowedVariables, true, input);\r
125         initialValue.setExpression(iv);\r
126         GridDataFactory.fillDefaults().span(4, 1).grab(true, true).applyTo(initialValue);\r
127 \r
128         initialValue.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
129 \r
130             @Override\r
131             public void focusLost(FocusEvent e) {\r
132                 lastSelectedText = initialValue;\r
133             }\r
134         });\r
135 \r
136 \r
137         l = new Label(parent, SWT.NONE);\r
138         l.setText("Order");\r
139 \r
140         // The order of the delay (default == 3)\r
141         order = new Spinner(parent, SWT.BORDER);\r
142         order.setMinimum(1);\r
143         order.setSelection(o);\r
144         order.addSelectionListener(new SelectionAdapter() {\r
145             @Override\r
146             public void widgetSelected(SelectionEvent e) {\r
147                 save(expression, data);\r
148             }\r
149         });\r
150         GridDataFactory.fillDefaults().grab(false, false).applyTo(order);\r
151         \r
152         l = new Label(parent, SWT.NONE);\r
153         l.setText("Delay type");\r
154         GridDataFactory.fillDefaults().grab(true, false).align(SWT.END, SWT.CENTER).applyTo(l);\r
155         \r
156         // The type of the delay (material / information delay)\r
157         delayTypeCombo = new Combo(parent, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY);\r
158         delayTypeCombo.add("Material");\r
159         delayTypeCombo.add("Information");\r
160         GridDataFactory.fillDefaults().applyTo(delayTypeCombo);\r
161         \r
162                 // Initial selection to the combo\r
163         try {\r
164                         boolean isInformationDelay = SimanticsUI.getSession().syncRequest(new Read<Boolean>(){\r
165 \r
166                                 @Override\r
167                                 public Boolean perform(ReadGraph graph) throws DatabaseException {\r
168                                         SysdynResource sr = SysdynResource.getInstance(graph);\r
169                                         return graph.hasStatement(expression, sr.DelayExpression_isInformationDelay, expression);\r
170                                 }\r
171                         });\r
172                         delayTypeCombo.select(isInformationDelay ? 1 : 0);\r
173             } catch (DatabaseException e1) {\r
174                         delayTypeCombo.select(0);\r
175                 e1.printStackTrace();\r
176                 }\r
177         \r
178         // Modify listener for selecting the delay type\r
179         delayTypeCombo.addModifyListener(new ModifyListener() {\r
180 \r
181                         @Override\r
182                         public void modifyText(ModifyEvent e) {\r
183                                 save(expression, data);\r
184                         }\r
185                 });\r
186         \r
187         lastSelectedText = equation;\r
188     }\r
189 \r
190     @Override\r
191     public void focus() {\r
192         lastSelectedText.setFocus();\r
193     }\r
194 \r
195     @Override\r
196     public List<ExpressionField> getExpressionFields() {\r
197         return Arrays.asList(equation, delayTime, initialValue);\r
198     }\r
199 \r
200     @Override\r
201     public void readData(final Resource expression, Map<String, Object> data) {\r
202         class Auxiliary {\r
203             String equation, delayTime, initialValue;\r
204             Integer order;\r
205             Boolean isInformationDelay;\r
206         }\r
207 \r
208         Auxiliary results = null;\r
209 \r
210         try {\r
211             results = SimanticsUI.getSession().syncRequest(new Read<Auxiliary>() {\r
212 \r
213                 @Override\r
214                 public Auxiliary perform(ReadGraph graph) throws DatabaseException {\r
215                     Auxiliary results = new Auxiliary();\r
216                     SysdynResource sr = SysdynResource.getInstance(graph);\r
217                     if (expression != null && graph.isInstanceOf(expression, sr.DelayExpression)) {\r
218                         results.equation = graph.getPossibleRelatedValue(expression, sr.DelayExpression_expression);\r
219                         results.delayTime = graph.getPossibleRelatedValue(expression, sr.DelayExpression_delayTime);\r
220                         results.initialValue = graph.getPossibleRelatedValue(expression, sr.DelayExpression_initialValue);\r
221                         results.order = graph.getPossibleRelatedValue(expression, sr.DelayExpression_order);\r
222                         results.isInformationDelay = graph.hasStatement(expression, sr.DelayExpression_isInformationDelay, expression);\r
223                     } else {\r
224                         results.equation = "";\r
225                         results.delayTime = "";\r
226                         results.order = 1;\r
227                         results.isInformationDelay = false;\r
228                     }\r
229                     return results;\r
230                 }\r
231             });\r
232         } catch (DatabaseException e1) {\r
233             e1.printStackTrace();\r
234         }\r
235         if(results.equation != null)\r
236             data.put("equation", results.equation);\r
237         if(results.delayTime != null)\r
238             data.put("delayTime", results.delayTime);\r
239         if(results.initialValue != null)\r
240             data.put("initialValue", results.initialValue);\r
241         if(results.order != null)\r
242             data.put("order", results.order);\r
243         if(results.isInformationDelay != null)\r
244             data.put("isInformationDelay", results.isInformationDelay);\r
245     }\r
246 \r
247     @Override\r
248     public void replaceSelection(String var) {\r
249         if(lastSelectedText != null) {\r
250             IDocument doc = lastSelectedText.getDocument();\r
251             try {\r
252                 Point selection = lastSelectedText.getSelection();\r
253                 doc.replace(selection.x, selection.y, var);\r
254                 lastSelectedText.setSelection(selection.x + var.length());\r
255             } catch (BadLocationException e) {\r
256                 e.printStackTrace();\r
257             }\r
258         }    \r
259     }\r
260 \r
261     @Override\r
262     public void save(Resource expr, Map<String, Object> data) {\r
263         this.expression = expr;\r
264         final String currentEquation = this.equation.getExpression();\r
265         final String currentDelayTime =  this.delayTime.getExpression();\r
266         final String currentInitialValue = this.initialValue.getExpression();\r
267         final Integer currentOrder = this.order.getSelection();\r
268         final Boolean currentIsInformationDelay = (this.delayTypeCombo.getSelectionIndex() == 1);\r
269 \r
270         String oldEquation = (String)data.get("equation");\r
271         String oldDelayTime = (String)data.get("delayTime");\r
272         String oldInitialValue = (String)data.get("initialValue");\r
273         Integer oldOrder = (Integer)data.get("order");\r
274         Boolean oldIsInformationDelay = (Boolean)data.get("isInformationDelay");\r
275 \r
276         if(oldEquation == null || oldDelayTime == null || oldOrder == null \r
277                         || oldInitialValue == null || oldIsInformationDelay == null \r
278                         || !oldEquation.equals(currentEquation) || !oldDelayTime.equals(currentDelayTime) \r
279                         || !oldOrder.equals(currentOrder) || !oldInitialValue.equals(currentInitialValue)\r
280                         || !oldIsInformationDelay.equals(currentIsInformationDelay)) {\r
281             // old value was null or value has changed -> Do save\r
282 \r
283             data.putAll(data);\r
284             data.put("equation", currentEquation);\r
285             data.put("delayTime", currentDelayTime);\r
286             data.put("initialValue", currentInitialValue);\r
287             data.put("order", currentOrder);\r
288             data.put("isInformationDelay", currentIsInformationDelay);\r
289 \r
290             SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
291                 @Override\r
292                 public void perform(WriteGraph g)\r
293                         throws DatabaseException {\r
294                     SysdynResource sr = SysdynResource.getInstance(g);\r
295                     Layer0 l0 = Layer0.getInstance(g);\r
296 \r
297                     if(!g.isInstanceOf(expression, sr.DelayExpression)) {\r
298                         // Create a new DelayExpression, if the old expression was something else\r
299                         final Resource newExpression = GraphUtils.create2(g, sr.DelayExpression);\r
300                         String arrayRange = g.getPossibleRelatedValue(expression, sr.Expression_arrayRange, Bindings.STRING);\r
301                         if(arrayRange != null)\r
302                             g.claimLiteral(newExpression, sr.Expression_arrayRange, arrayRange);\r
303 \r
304                         final Resource variable = g.getPossibleObject(expression, l0.PartOf);\r
305                         Resource ownerList = g.getPossibleObject(variable, sr.Variable_expressionList);\r
306                         ListUtils.replace(g, ownerList, expression, newExpression);\r
307                         g.deny(expression, l0.PartOf);\r
308                         g.claim(newExpression, l0.PartOf, variable);\r
309 \r
310                         VirtualGraph runtime = g.getService(VirtualGraph.class);\r
311                         g.syncRequest(new WriteRequest(runtime) {\r
312                             @Override\r
313                             public void perform(WriteGraph graph) throws DatabaseException {\r
314                                 SysdynResource sr = SysdynResource.getInstance(graph);\r
315                                 if(graph.hasStatement(variable, sr.IndependentVariable_activeExpression))\r
316                                     graph.deny(variable, sr.IndependentVariable_activeExpression);\r
317                                 graph.claim(variable, sr.IndependentVariable_activeExpression, newExpression);\r
318                             }\r
319                         });\r
320                         expression = newExpression;\r
321                     }\r
322                     \r
323                     // Claim values\r
324                     g.claimLiteral(expression, sr.DelayExpression_expression, currentEquation);\r
325                     g.claimLiteral(expression, sr.DelayExpression_delayTime, currentDelayTime);\r
326                     g.claimLiteral(expression, sr.DelayExpression_initialValue, currentInitialValue);\r
327                     g.claimLiteral(expression, sr.DelayExpression_order, currentOrder);\r
328                     if (currentIsInformationDelay)\r
329                         g.claim(expression, sr.DelayExpression_isInformationDelay, expression);\r
330                     else\r
331                         g.deny(expression, sr.DelayExpression_isInformationDelay, expression);\r
332                     \r
333                     g.startUndoContext();\r
334                                 CommentMetadata cm = g.getMetadata(CommentMetadata.class);\r
335                                 g.addMetadata(cm.add("Set delay expression"));\r
336                     \r
337                 }\r
338             });\r
339         }\r
340 \r
341     }\r
342 \r
343     @Override\r
344     public void updateData(Map<String, Object> data) {\r
345         if(this.equation != null && this.equation.getExpression() != null)\r
346             data.put("equation", this.equation.getExpression());\r
347         if(this.delayTime != null && this.delayTime.getExpression() != null)\r
348             data.put("delayTime", this.delayTime.getExpression());   \r
349         if(this.initialValue != null && this.initialValue.getExpression() != null)\r
350             data.put("initialValue", this.initialValue.getExpression());   \r
351         if(this.order != null)\r
352             data.put("order", this.order.getSelection());   \r
353         if(this.delayTypeCombo != null)\r
354             data.put("isInformationDelay", (this.delayTypeCombo.getSelectionIndex() == 1));\r
355     }\r
356 \r
357     @Override\r
358     public void addKeyListener(KeyListener listener) {\r
359         this.equation.getSourceViewer().getTextWidget().addKeyListener(listener);\r
360         this.delayTime.getSourceViewer().getTextWidget().addKeyListener(listener);\r
361         this.initialValue.getSourceViewer().getTextWidget().addKeyListener(listener);\r
362     }\r
363 \r
364     @Override\r
365     public void addModifyListener(ModifyListener listener) {\r
366         this.equation.getSourceViewer().getTextWidget().addModifyListener(listener);\r
367         this.delayTime.getSourceViewer().getTextWidget().addModifyListener(listener);\r
368         this.initialValue.getSourceViewer().getTextWidget().addModifyListener(listener);\r
369     }\r
370 \r
371     @Override\r
372     public void addFocusListener(FocusListener listener) {\r
373         this.equation.getSourceViewer().getTextWidget().addFocusListener(listener);\r
374         this.delayTime.getSourceViewer().getTextWidget().addFocusListener(listener);\r
375         this.initialValue.getSourceViewer().getTextWidget().addFocusListener(listener);\r
376     }\r
377 \r
378     @Override\r
379     public void addVerifyKeyListener(VerifyKeyListener listener) {\r
380         this.equation.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
381         this.delayTime.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
382         this.initialValue.getSourceViewer().getTextWidget().addVerifyKeyListener(listener);\r
383     }\r
384 \r
385 }\r