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