1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling.ui.componentTypeEditor;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
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.browsing.ui.graph.impl.GetEnumerationValue;
38 import org.simantics.databoard.Bindings;
39 import org.simantics.databoard.binding.Binding;
40 import org.simantics.databoard.binding.error.BindingException;
41 import org.simantics.databoard.type.Datatype;
42 import org.simantics.databoard.type.NumberType;
43 import org.simantics.db.ReadGraph;
44 import org.simantics.db.Resource;
45 import org.simantics.db.common.NamedResource;
46 import org.simantics.db.common.request.IsEnumeratedValue;
47 import org.simantics.db.common.request.UniqueRead;
48 import org.simantics.db.common.utils.NameUtils;
49 import org.simantics.db.exception.DatabaseException;
50 import org.simantics.db.layer0.util.Layer0Utils;
51 import org.simantics.db.procedure.Listener;
52 import org.simantics.db.request.Read;
53 import org.simantics.layer0.Layer0;
54 import org.simantics.modeling.ui.Activator;
55 import org.simantics.operation.Layer0X;
56 import org.simantics.structural.stubs.StructuralResource2;
57 import org.simantics.utils.ui.ErrorLogger;
58 import org.simantics.utils.ui.SWTUtils;
60 public class ComponentTypeViewer {
62 ComponentTypeViewerData data;
64 ResourceManager resourceManager;
66 ArrayList<ComponentTypeViewerSection> sections = new ArrayList<ComponentTypeViewerSection>(3);
68 public ComponentTypeViewer(Composite parent, Resource _componentType, String formTitle) {
70 FormToolkit tk = new FormToolkit(parent.getDisplay());
71 Form form = tk.createForm(parent);
72 tk.decorateFormHeading(form);
73 resourceManager = new LocalResourceManager(JFaceResources.getResources(), form);
74 form.setText(formTitle);
75 form.setImage(resourceManager.createImage(Activator.COMPONENT_TYPE_ICON));
77 FormLayout layout = new FormLayout();
78 layout.marginBottom = 10;
79 layout.marginTop = 10;
80 layout.marginLeft = 10;
81 layout.marginRight = 10;
82 form.getBody().setLayout(layout);
86 data = new ComponentTypeViewerData(tk, _componentType, form);
90 sections.add(new ConfigurationPropertiesSection(data));
91 sections.add(new DerivedPropertiesSection(data));
93 BundleContext bundleContext = Activator.getContext();
95 ArrayList<ComponentTypeViewerSectionFactory> factories =
96 Simantics.getSession().syncRequest(new Read<ArrayList<ComponentTypeViewerSectionFactory>>() {
98 public ArrayList<ComponentTypeViewerSectionFactory> perform(
99 ReadGraph graph) throws DatabaseException {
100 ArrayList<ComponentTypeViewerSectionFactory> factories =
101 new ArrayList<ComponentTypeViewerSectionFactory>(3);
103 String className = ComponentTypeViewerSectionFactory.class.getName();
104 ServiceReference<?>[] references = bundleContext.getAllServiceReferences(className, null);
105 if(references != null)
106 for(ServiceReference<?> reference : references) {
107 ComponentTypeViewerSectionFactory factory = (ComponentTypeViewerSectionFactory)bundleContext.getService(reference);
108 if(factory.doesSupport(graph, _componentType))
109 factories.add(factory);
111 } catch (InvalidSyntaxException e) {
117 for(ComponentTypeViewerSectionFactory factory : factories)
118 sections.add(factory.create(data));
119 } catch(DatabaseException e) {
123 sections.sort((a,b) -> { return Double.compare(a.getPriority(), b.getPriority()); });
127 Sash[] sashes = new Sash[sections.size()-1];
128 for(int i=0;i<sections.size()-1;++i) {
129 Sash sash = new Sash(form.getBody(), SWT.HORIZONTAL);
130 sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_WHITE));
132 FormData data = new FormData();
133 data.top = new FormAttachment(100*(i+1)/sections.size(), 0);
134 data.left = new FormAttachment(0, 0);
135 data.right = new FormAttachment(100, 0);
137 sash.setLayoutData(data);
139 sash.addSelectionListener(new SelectionAdapter() {
140 public void widgetSelected(SelectionEvent e) {
141 sash.setBounds(e.x, e.y, e.width, e.height);
142 FormData data = new FormData();
143 data.top = new FormAttachment(0, e.y);
144 data.left = new FormAttachment(0, 0);
145 data.right = new FormAttachment(100, 0);
147 sash.setLayoutData(data);
148 form.getBody().layout(true);
153 for(int i=0;i<sections.size();++i) {
155 FormData formData = new FormData();
156 formData.top = i > 0 ? new FormAttachment(sashes[i-1]) : new FormAttachment(0, 0);
157 formData.left = new FormAttachment(0, 0);
158 formData.right = new FormAttachment(100, 0);
159 formData.bottom = i < sections.size()-1
160 ? new FormAttachment(sashes[i]) : new FormAttachment(100, 0);
161 sections.get(i).getSection().setLayoutData(formData);
166 createGraphListener();
169 private void createGraphListener() {
170 Simantics.getSession().asyncRequest(new UniqueRead<ComponentTypePropertiesResult>() {
172 public ComponentTypePropertiesResult perform(ReadGraph graph) throws DatabaseException {
173 List<ComponentTypeViewerPropertyInfo> result = new ArrayList<>();
174 List<NamedResource> connectionPoints = new ArrayList<>();
175 Layer0 L0 = Layer0.getInstance(graph);
176 Layer0X L0X = Layer0X.getInstance(graph);
177 StructuralResource2 STR = StructuralResource2.getInstance(graph);
179 boolean typeIsImmutable = graph.isImmutable(data.componentType)
180 || graph.hasStatement(data.componentType, STR.ComponentType_Locked)
181 || Layer0Utils.isPublished(graph, data.componentType)
182 || Layer0Utils.isContainerPublished(graph, data.componentType);
184 for(Resource relation : graph.getObjects(data.componentType, L0.DomainOf)) {
185 if(graph.isSubrelationOf(relation, L0.HasProperty)) {
186 String name = graph.getRelatedValue(relation, L0.HasName);
187 String type = graph.getPossibleRelatedValue(relation, L0.RequiresValueType);
188 String label = graph.getPossibleRelatedValue(relation, L0.HasLabel);
190 label = ""; //$NON-NLS-1$
191 String description = graph.getPossibleRelatedValue(relation, L0.HasDescription);
192 if (description == null)
193 description = ""; //$NON-NLS-1$
194 NumberType numberType = null;
196 type = "Double"; //$NON-NLS-1$
197 String unit = graph.getPossibleRelatedValue(relation, L0X.HasUnit, Bindings.STRING);
198 String defaultValue = "0"; //$NON-NLS-1$
199 String expression = null;
201 for(Resource assertion : graph.getAssertedObjects(data.componentType, relation)) {
203 expression = graph.getPossibleRelatedValue(assertion, L0.SCLValue_expression, Bindings.STRING);
204 if(expression != null) {
205 defaultValue = "=" + expression; //$NON-NLS-1$
206 } else if (graph.sync(new IsEnumeratedValue(assertion))) {
207 defaultValue = GetEnumerationValue.getEnumerationValueName(graph, assertion);
209 Datatype dt = getPossibleDatatype(graph, assertion);
212 if (dt instanceof NumberType)
213 numberType = (NumberType) dt;
214 Binding binding = Bindings.getBinding(dt);
215 Object value = graph.getValue(assertion, binding);
217 defaultValue = binding.toString(value, true);
218 } catch (BindingException e) {
219 ErrorLogger.defaultLogError(e);
222 } catch(DatabaseException e) {
223 ErrorLogger.defaultLogError(e);
227 String valid = expression != null ? DerivedPropertiesSection.validateMonitorExpression(graph, data.componentType, relation, expression) : null;
229 boolean immutable = typeIsImmutable || graph.isImmutable(relation);
230 ComponentTypeViewerPropertyInfo info =
231 new ComponentTypeViewerPropertyInfo(relation, name, type, defaultValue, numberType, unit, label, description, expression, valid, immutable);
233 Object sectionSpecificData = null;
234 double priority = Double.NEGATIVE_INFINITY;
235 for(ComponentTypeViewerSection section : sections) {
236 Object temp = section.getSectionSpecificData(graph, info);
238 double sectionPriority = section.getDataPriority();
239 if(sectionPriority > priority) {
240 sectionSpecificData = temp;
241 priority = sectionPriority;
245 info.sectionSpecificData = sectionSpecificData;
249 } else if (graph.isInstanceOf(relation, STR.ConnectionRelation)) {
250 NamedResource nr = new NamedResource(NameUtils.getSafeName(graph, relation), relation);
251 connectionPoints.add(nr);
254 Collections.sort(result);
255 return new ComponentTypePropertiesResult(result, connectionPoints, typeIsImmutable);
257 }, new Listener<ComponentTypePropertiesResult>() {
259 public void execute(final ComponentTypePropertiesResult result) {
260 SWTUtils.asyncExec(data.form.getDisplay(), new Runnable() {
263 // Store loaded properties
264 data.properties = result.getProperties().toArray(new ComponentTypeViewerPropertyInfo[result.getProperties().size()]);
265 data.connectionPoints = result.getConnectionPoints().toArray(new NamedResource[result.getConnectionPoints().size()]);
267 for(ComponentTypeViewerSection section : sections)
268 section.update(result);
269 setReadOnly(result.isImmutable());
275 public void exception(Throwable t) {
276 ErrorLogger.defaultLogError(t);
280 public boolean isDisposed() {
281 return data.form.isDisposed();
287 protected Datatype getPossibleDatatype(ReadGraph graph, Resource literal) throws DatabaseException {
288 Binding binding = Bindings.getBindingUnchecked(Datatype.class);
289 for (Resource dataTypeResource : graph.getObjects(literal, Layer0.getInstance(graph).HasDataType)) {
290 Datatype dt = graph.getPossibleValue(dataTypeResource, binding);
297 public void setFocus() {
298 data.form.setFocus();
305 private void setReadOnly(boolean readOnly) {
306 if (readOnly == data.readOnly)
308 data.readOnly = readOnly;
309 for(ComponentTypeViewerSection section : sections)
310 section.setReadOnly(readOnly);
311 IMessageManager mm = data.form.getMessageManager();
313 mm.addMessage("readonly", Messages.ComponentTypeViewer_OpenedInReadOnly, null, IMessageProvider.INFORMATION); //$NON-NLS-1$
315 mm.removeMessage("readonly"); //$NON-NLS-1$