]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewer.java
3cc4bbbf3ce68aa6d08f2b99438fad0190e134bc
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / componentTypeEditor / ComponentTypeViewer.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012 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.modeling.ui.componentTypeEditor;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collections;\r
16 import java.util.List;\r
17 \r
18 import org.eclipse.jface.dialogs.IMessageProvider;\r
19 import org.eclipse.jface.resource.JFaceResources;\r
20 import org.eclipse.jface.resource.LocalResourceManager;\r
21 import org.eclipse.jface.resource.ResourceManager;\r
22 import org.eclipse.swt.SWT;\r
23 import org.eclipse.swt.events.SelectionAdapter;\r
24 import org.eclipse.swt.events.SelectionEvent;\r
25 import org.eclipse.swt.layout.FormAttachment;\r
26 import org.eclipse.swt.layout.FormData;\r
27 import org.eclipse.swt.layout.FormLayout;\r
28 import org.eclipse.swt.widgets.Composite;\r
29 import org.eclipse.swt.widgets.Sash;\r
30 import org.eclipse.ui.forms.IMessageManager;\r
31 import org.eclipse.ui.forms.widgets.Form;\r
32 import org.eclipse.ui.forms.widgets.FormToolkit;\r
33 import org.osgi.framework.BundleContext;\r
34 import org.osgi.framework.InvalidSyntaxException;\r
35 import org.osgi.framework.ServiceReference;\r
36 import org.simantics.Simantics;\r
37 import org.simantics.databoard.Bindings;\r
38 import org.simantics.databoard.binding.Binding;\r
39 import org.simantics.databoard.binding.error.BindingException;\r
40 import org.simantics.databoard.type.Datatype;\r
41 import org.simantics.databoard.type.NumberType;\r
42 import org.simantics.db.ReadGraph;\r
43 import org.simantics.db.Resource;\r
44 import org.simantics.db.common.NamedResource;\r
45 import org.simantics.db.common.request.UniqueRead;\r
46 import org.simantics.db.common.utils.NameUtils;\r
47 import org.simantics.db.exception.DatabaseException;\r
48 import org.simantics.db.procedure.Listener;\r
49 import org.simantics.db.request.Read;\r
50 import org.simantics.db.service.XSupport;\r
51 import org.simantics.layer0.Layer0;\r
52 import org.simantics.modeling.ui.Activator;\r
53 import org.simantics.operation.Layer0X;\r
54 import org.simantics.structural.stubs.StructuralResource2;\r
55 import org.simantics.utils.ui.ErrorLogger;\r
56 import org.simantics.utils.ui.SWTUtils;\r
57 \r
58 public class ComponentTypeViewer {\r
59 \r
60     ComponentTypeViewerData data;\r
61     \r
62     ResourceManager resourceManager;\r
63     \r
64     ArrayList<ComponentTypeViewerSection> sections = new ArrayList<ComponentTypeViewerSection>(3);\r
65 \r
66     public ComponentTypeViewer(Composite parent, Resource _componentType, String formTitle) {\r
67         // Form\r
68         FormToolkit tk = new FormToolkit(parent.getDisplay());\r
69         Form form = tk.createForm(parent);\r
70         tk.decorateFormHeading(form);\r
71         resourceManager = new LocalResourceManager(JFaceResources.getResources(), form);\r
72         form.setText(formTitle);\r
73         form.setImage(resourceManager.createImage(Activator.COMPONENT_TYPE_ICON));\r
74         {\r
75             FormLayout layout = new FormLayout();\r
76             layout.marginBottom = 10;\r
77             layout.marginTop = 10;\r
78             layout.marginLeft = 10;\r
79             layout.marginRight = 10;\r
80             form.getBody().setLayout(layout);\r
81         }\r
82         \r
83         // Data\r
84         data = new ComponentTypeViewerData(tk, _componentType, form);\r
85 \r
86         // Sections\r
87         \r
88         sections.add(new ConfigurationPropertiesSection(data));\r
89         sections.add(new DerivedPropertiesSection(data));\r
90 \r
91         BundleContext bundleContext = Activator.getContext();\r
92         try {\r
93             ArrayList<ComponentTypeViewerSectionFactory> factories = \r
94                     Simantics.getSession().syncRequest(new Read<ArrayList<ComponentTypeViewerSectionFactory>>() {\r
95                         @Override\r
96                         public ArrayList<ComponentTypeViewerSectionFactory> perform(\r
97                                 ReadGraph graph) throws DatabaseException {\r
98                             ArrayList<ComponentTypeViewerSectionFactory> factories =\r
99                                     new ArrayList<ComponentTypeViewerSectionFactory>(3);\r
100                             try {\r
101                                 String className = ComponentTypeViewerSectionFactory.class.getName();\r
102                                 ServiceReference<?>[] references = bundleContext.getAllServiceReferences(className, null);\r
103                                 if(references != null)\r
104                                     for(ServiceReference<?> reference : references) {\r
105                                         ComponentTypeViewerSectionFactory factory = (ComponentTypeViewerSectionFactory)bundleContext.getService(reference);\r
106                                         if(factory.doesSupport(graph, _componentType))\r
107                                             factories.add(factory);\r
108                                     }\r
109                             } catch (InvalidSyntaxException e) {\r
110                                 e.printStackTrace();\r
111                             }\r
112                             return factories;\r
113                         }\r
114                     });\r
115             for(ComponentTypeViewerSectionFactory factory : factories)\r
116                 sections.add(factory.create(data));\r
117         } catch(DatabaseException e) {\r
118             e.printStackTrace();\r
119         }\r
120         \r
121         sections.sort((a,b) -> { return Double.compare(a.getPriority(), b.getPriority()); });\r
122         \r
123         // Sashes\r
124         \r
125         Sash[] sashes = new Sash[sections.size()-1];\r
126         for(int i=0;i<sections.size()-1;++i) {\r
127             Sash sash = new Sash(form.getBody(), SWT.HORIZONTAL);\r
128             sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_WHITE));\r
129             {\r
130                 FormData data = new FormData();\r
131                 data.top = new FormAttachment(100*(i+1)/sections.size(), 0);\r
132                 data.left = new FormAttachment(0, 0);\r
133                 data.right = new FormAttachment(100, 0);\r
134                 data.height = 10;\r
135                 sash.setLayoutData(data);\r
136             }\r
137             sash.addSelectionListener(new SelectionAdapter() {\r
138                 public void widgetSelected(SelectionEvent e) {\r
139                     sash.setBounds(e.x, e.y, e.width, e.height);\r
140                     FormData data = new FormData();\r
141                     data.top = new FormAttachment(0, e.y);\r
142                     data.left = new FormAttachment(0, 0);\r
143                     data.right = new FormAttachment(100, 0);\r
144                     data.height = 10;\r
145                     sash.setLayoutData(data);\r
146                     form.getBody().layout(true);\r
147                 }\r
148             });\r
149             sashes[i] = sash;\r
150         }\r
151         for(int i=0;i<sections.size();++i) {\r
152             {\r
153                 FormData formData = new FormData();\r
154                 formData.top = i > 0 ? new FormAttachment(sashes[i-1]) : new FormAttachment(0, 0);\r
155                 formData.left = new FormAttachment(0, 0);\r
156                 formData.right = new FormAttachment(100, 0);\r
157                 formData.bottom = i < sections.size()-1 \r
158                         ? new FormAttachment(sashes[i]) : new FormAttachment(100, 0);\r
159                 sections.get(i).getSection().setLayoutData(formData);\r
160             }\r
161         }\r
162 \r
163         // Listening\r
164         createGraphListener();\r
165     }\r
166     \r
167     private void createGraphListener() {\r
168         Simantics.getSession().asyncRequest(new UniqueRead<ComponentTypePropertiesResult>() {\r
169             @Override\r
170             public ComponentTypePropertiesResult perform(ReadGraph graph) throws DatabaseException {\r
171                 List<ComponentTypeViewerPropertyInfo> result = new ArrayList<>();\r
172                 List<NamedResource> connectionPoints = new ArrayList<>();\r
173                 Layer0 L0 = Layer0.getInstance(graph);\r
174                 Layer0X L0X = Layer0X.getInstance(graph);\r
175                 StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
176                 for(Resource relation : graph.getObjects(data.componentType, L0.DomainOf)) {\r
177                     if(graph.isSubrelationOf(relation, L0.HasProperty)) {\r
178                         String name = graph.getRelatedValue(relation, L0.HasName);\r
179                         String type =  graph.getPossibleRelatedValue(relation, L0.RequiresValueType);\r
180                         String label = graph.getPossibleRelatedValue(relation, L0.HasLabel);\r
181                         if (label == null)\r
182                             label = "";\r
183                         String description = graph.getPossibleRelatedValue(relation, L0.HasDescription);\r
184                         if (description == null)\r
185                             description = "";\r
186                         NumberType numberType = null;\r
187                         if(type == null)\r
188                             type = "Double";\r
189                         String unit = graph.getPossibleRelatedValue(relation, L0X.HasUnit, Bindings.STRING);\r
190                         String defaultValue = "0";\r
191                         String expression = null;\r
192                         \r
193                         for(Resource assertion : graph.getAssertedObjects(data.componentType, relation)) {\r
194                             try {\r
195                                 expression = graph.getPossibleRelatedValue(assertion, L0.SCLValue_expression, Bindings.STRING);\r
196                                 if(expression != null) {\r
197                                         defaultValue = "=" + expression;\r
198                                 } else {\r
199                                         Datatype dt = getPossibleDatatype(graph, assertion);\r
200                                         if (dt == null)\r
201                                             continue;\r
202                                         if (dt instanceof NumberType)\r
203                                             numberType = (NumberType) dt;\r
204                                         Binding binding = Bindings.getBinding(dt);\r
205                                         Object value = graph.getValue(assertion, binding);\r
206                                         try {\r
207                                             defaultValue = binding.toString(value, true);\r
208                                         } catch (BindingException e) {\r
209                                             ErrorLogger.defaultLogError(e);\r
210                                         }\r
211                                 }\r
212                             } catch(DatabaseException e) {\r
213                                 ErrorLogger.defaultLogError(e);\r
214                             }\r
215                         }\r
216                         \r
217                         String valid = expression != null ? DerivedPropertiesSection.validateMonitorExpression(graph, data.componentType, relation, expression) : null; \r
218 \r
219                         boolean immutable = graph.isImmutable(relation);\r
220                         ComponentTypeViewerPropertyInfo info =\r
221                                 new ComponentTypeViewerPropertyInfo(relation, name, type, defaultValue, numberType, unit, label, description, expression, valid, immutable);\r
222                         \r
223                         Object sectionSpecificData = null;\r
224                         double priority = Double.NEGATIVE_INFINITY;\r
225                         for(ComponentTypeViewerSection section : sections) {\r
226                             Object temp = section.getSectionSpecificData(graph, info);\r
227                             if(temp != null) {\r
228                                 double sectionPriority = section.getDataPriority();\r
229                                 if(sectionPriority > priority) {\r
230                                     sectionSpecificData = temp;\r
231                                     priority = sectionPriority;\r
232                                 }\r
233                             }\r
234                         }\r
235                         info.sectionSpecificData = sectionSpecificData;\r
236                         \r
237                         result.add(info);\r
238 \r
239                     } else if (graph.isInstanceOf(relation, STR.ConnectionRelation)) {\r
240                         NamedResource nr = new NamedResource(NameUtils.getSafeName(graph, relation), relation);\r
241                         connectionPoints.add(nr);\r
242                     }\r
243                 }\r
244                 Collections.sort(result);\r
245                 XSupport xs = graph.peekService(XSupport.class);\r
246                 boolean immutable = xs != null ? xs.getImmutable(data.componentType) : false;\r
247                 return new ComponentTypePropertiesResult(result, connectionPoints, immutable);\r
248             }\r
249         }, new Listener<ComponentTypePropertiesResult>() {\r
250             @Override\r
251             public void execute(final ComponentTypePropertiesResult result) {  \r
252                 SWTUtils.asyncExec(data.form.getDisplay(), new Runnable() {\r
253                     @Override\r
254                     public void run() {\r
255                         // Store loaded properties\r
256                         data.properties = result.getProperties().toArray(new ComponentTypeViewerPropertyInfo[result.getProperties().size()]);\r
257                         data.connectionPoints = result.getConnectionPoints().toArray(new NamedResource[result.getConnectionPoints().size()]);\r
258 \r
259                         for(ComponentTypeViewerSection section : sections)\r
260                             section.update(result);\r
261                         setReadOnly(result.isImmutable());\r
262                     }\r
263                 });\r
264             }\r
265 \r
266             @Override\r
267             public void exception(Throwable t) {\r
268                 ErrorLogger.defaultLogError(t);\r
269             }\r
270 \r
271             @Override\r
272             public boolean isDisposed() {\r
273                 return data.form.isDisposed();\r
274             }\r
275 \r
276         });\r
277     }\r
278 \r
279     protected Datatype getPossibleDatatype(ReadGraph graph, Resource literal) throws DatabaseException {\r
280         Binding binding = Bindings.getBindingUnchecked(Datatype.class);\r
281         for (Resource dataTypeResource : graph.getObjects(literal, Layer0.getInstance(graph).HasDataType)) {\r
282             Datatype dt = graph.getPossibleValue(dataTypeResource, binding);\r
283             if (dt != null)\r
284                 return dt;\r
285         }\r
286         return null;\r
287     }\r
288 \r
289     public void setFocus() {\r
290         data.form.setFocus();\r
291     }\r
292 \r
293     /**\r
294      * @param readOnly\r
295      * @thread SWT\r
296      */\r
297     private void setReadOnly(boolean readOnly) {\r
298         if (readOnly == data.readOnly)\r
299             return;\r
300         data.readOnly = readOnly;\r
301         for(ComponentTypeViewerSection section : sections)\r
302             section.setReadOnly(readOnly);\r
303         IMessageManager mm = data.form.getMessageManager();\r
304         if (readOnly)\r
305             mm.addMessage("readonly", "(Opened in read-only mode)", null, IMessageProvider.INFORMATION);\r
306         else\r
307             mm.removeMessage("readonly");\r
308     }\r
309 \r
310 }\r