]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
a39568bc470175ee1634cdaae9f3cbb669ac04f5
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2011 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.functions;\r
13 \r
14 import java.awt.event.ActionEvent;\r
15 import java.awt.event.ActionListener;\r
16 import java.io.StringReader;\r
17 \r
18 import javax.swing.Timer;\r
19 \r
20 import org.eclipse.jface.layout.GridDataFactory;\r
21 import org.eclipse.swt.SWT;\r
22 import org.eclipse.swt.custom.StyledText;\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.ModifyEvent;\r
27 import org.eclipse.swt.events.ModifyListener;\r
28 import org.eclipse.swt.events.VerifyEvent;\r
29 import org.eclipse.swt.widgets.Composite;\r
30 import org.eclipse.swt.widgets.Listener;\r
31 import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
32 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
33 import org.simantics.db.ReadGraph;\r
34 import org.simantics.db.Resource;\r
35 import org.simantics.db.WriteGraph;\r
36 import org.simantics.db.common.request.WriteRequest;\r
37 import org.simantics.db.exception.DatabaseException;\r
38 import org.simantics.db.management.ISessionContext;\r
39 import org.simantics.db.request.Read;\r
40 import org.simantics.layer0.Layer0;\r
41 import org.simantics.sysdyn.SysdynResource;\r
42 import org.simantics.sysdyn.modelParser.ModelParser;\r
43 import org.simantics.sysdyn.modelParser.ParseException;\r
44 import org.simantics.sysdyn.modelParser.Token;\r
45 import org.simantics.sysdyn.modelParser.TokenMgrError;\r
46 import org.simantics.sysdyn.manager.FunctionUtils;\r
47 import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionField;\r
48 import org.simantics.ui.SimanticsUI;\r
49 import org.simantics.ui.utils.AdaptionUtils;\r
50 \r
51 public class FunctionCodeWidget implements Widget {\r
52         \r
53         private ExpressionField modelicaCode;\r
54         private Resource function;\r
55         \r
56     private Timer updateChartTimer;\r
57     private static int VALIDATION_DELAY_TIME = 500;\r
58         \r
59         public FunctionCodeWidget(Composite parent, WidgetSupport support, int style) {\r
60                 support.register(this);\r
61                 \r
62         modelicaCode = new ExpressionField(parent, SWT.BORDER);\r
63         GridDataFactory.fillDefaults().grab(true, true).applyTo(modelicaCode);\r
64         \r
65 \r
66         // Support shift+enter for line change\r
67         modelicaCode.getSourceViewer().getTextWidget().addVerifyKeyListener(new VerifyKeyListener() {\r
68 \r
69                 @Override\r
70                 public void verifyKey(VerifyEvent event) {\r
71                         if(event.keyCode == SWT.CR || event.keyCode == SWT.KEYPAD_CR) {\r
72                                 if((event.stateMask & SWT.SHIFT) == 0) {\r
73                                         event.doit = false;\r
74                                         Listener[] listeners = modelicaCode.getSourceViewer().getTextWidget().getListeners(SWT.FocusOut);\r
75                                         for(Listener l : listeners) {\r
76                                                 modelicaCode.getSourceViewer().getTextWidget().removeListener(SWT.FocusOut, l);\r
77                                         }\r
78                                         ((StyledText)event.widget).getParent().forceFocus();\r
79                                         save();\r
80                                         for(Listener l : listeners) {\r
81                                                 modelicaCode.getSourceViewer().getTextWidget().addListener(SWT.FocusOut, l);\r
82                                         }\r
83                                 \r
84                                 }\r
85                         }\r
86                 }\r
87         });\r
88         \r
89         \r
90         modelicaCode.getSourceViewer().getTextWidget().addModifyListener(new ModifyListener() {\r
91 \r
92                         @Override\r
93                         public void modifyText(ModifyEvent e) {\r
94                                 validateFieldsTimed();\r
95                         }\r
96                 });\r
97         \r
98         modelicaCode.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() {\r
99                         @Override\r
100                         public void focusLost(FocusEvent e) {\r
101                                 save();\r
102                         }\r
103                 });\r
104                 \r
105         \r
106         updateChartTimer = new Timer(VALIDATION_DELAY_TIME, new ActionListener() {\r
107 \r
108             @Override\r
109             public void actionPerformed(ActionEvent e) {\r
110                 if(modelicaCode == null || modelicaCode.isDisposed())\r
111                         return;\r
112                 modelicaCode.getDisplay().asyncExec(new Runnable() {\r
113                                 \r
114                                 @Override\r
115                                 public void run() {\r
116                                         validate();\r
117                                 }\r
118                         });\r
119             }\r
120         });\r
121         updateChartTimer.setRepeats(false);\r
122         }\r
123 \r
124         @Override\r
125         public void setInput(ISessionContext context, Object input) {\r
126                 function = AdaptionUtils.adaptToSingle(input, Resource.class);\r
127                 \r
128                 try {\r
129                         String code = context.getSession().syncRequest(new Read<String>() {\r
130 \r
131                                 @Override\r
132                                 public String perform(ReadGraph graph) throws DatabaseException {\r
133                                         String code = graph.getPossibleRelatedValue(\r
134                                                         function, SysdynResource.getInstance(graph).SysdynModelicaFunction_modelicaFunctionCode);\r
135                                         return code;\r
136                                 }\r
137                                 \r
138                         });\r
139                         if(code != null) {\r
140                                 modelicaCode.setExpression(code);\r
141                                 validate();\r
142                         }\r
143                 } catch (DatabaseException e) {\r
144                         e.printStackTrace();\r
145                 }\r
146         }\r
147         \r
148         \r
149     public void validateFieldsTimed() {         \r
150         validateFieldsTimed(VALIDATION_DELAY_TIME);\r
151     }\r
152     \r
153     public void validateFieldsTimed(int delay) {\r
154         updateChartTimer.setDelay(delay);\r
155         if(!updateChartTimer.isRunning())\r
156             updateChartTimer.start();\r
157         else\r
158             updateChartTimer.restart();\r
159     }\r
160     \r
161     public void validate() {\r
162         modelicaCode.resetAnnotations();\r
163         String code = modelicaCode.getExpression();\r
164         StringReader sr = new StringReader(code);\r
165         ModelParser modelParser = new ModelParser(sr);\r
166         try {\r
167                         modelParser.parse_composition();\r
168                 } catch (ParseException e1) {\r
169                         Token token = e1.currentToken;\r
170                         modelicaCode.setSyntaxError(token.image, "Syntax error", token.beginLine, token.beginColumn, token.endLine, token.endColumn);\r
171                 } catch (TokenMgrError err) {\r
172                         String message = err.getMessage();\r
173                         String line = message.substring(0, message.indexOf(","));\r
174                         line = line.substring(line.lastIndexOf(" ") + 1);\r
175                         String column = message.substring(message.indexOf(",") + 1, message.indexOf("."));\r
176                         column = column.substring(column.lastIndexOf(" ") + 1);\r
177                         try {\r
178                                 Integer endLine = Integer.parseInt(line);\r
179                                 Integer endColumn = Integer.parseInt(column);\r
180                                 Token token = modelParser.token;\r
181                                 modelicaCode.setSyntaxError(token.image, "Syntax error", token.endLine, token.endColumn, endLine, endColumn);\r
182                         } catch (NumberFormatException e) {\r
183                                 \r
184                         }\r
185                         \r
186                 }\r
187         }\r
188     \r
189     private void save() {\r
190         final String code = modelicaCode.getExpression();\r
191         SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
192                         \r
193                         @Override\r
194                         public void perform(WriteGraph graph) throws DatabaseException {\r
195                                 graph.claimLiteral(\r
196                                                 function, \r
197                                                 SysdynResource.getInstance(graph).SysdynModelicaFunction_modelicaFunctionCode, \r
198                                                 code);\r
199                                 Resource library = graph.getSingleObject(function, Layer0.getInstance(graph).PartOf);\r
200                                 FunctionUtils.updateFunctionFileForLibrary(graph, library);\r
201                         }\r
202                 });\r
203     }\r
204 \r
205 }\r