--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2012 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.modeling.ui.componentTypeEditor;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.dialogs.IMessageProvider;\r
+import org.eclipse.jface.resource.JFaceResources;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.resource.ResourceManager;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.layout.FormAttachment;\r
+import org.eclipse.swt.layout.FormData;\r
+import org.eclipse.swt.layout.FormLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Sash;\r
+import org.eclipse.ui.forms.IMessageManager;\r
+import org.eclipse.ui.forms.widgets.Form;\r
+import org.eclipse.ui.forms.widgets.FormToolkit;\r
+import org.osgi.framework.BundleContext;\r
+import org.osgi.framework.InvalidSyntaxException;\r
+import org.osgi.framework.ServiceReference;\r
+import org.simantics.Simantics;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.type.NumberType;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.NamedResource;\r
+import org.simantics.db.common.request.UniqueRead;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.db.service.XSupport;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ui.Activator;\r
+import org.simantics.operation.Layer0X;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+import org.simantics.utils.ui.SWTUtils;\r
+\r
+public class ComponentTypeViewer {\r
+\r
+ ComponentTypeViewerData data;\r
+ \r
+ ResourceManager resourceManager;\r
+ \r
+ ArrayList<ComponentTypeViewerSection> sections = new ArrayList<ComponentTypeViewerSection>(3);\r
+\r
+ public ComponentTypeViewer(Composite parent, Resource _componentType, String formTitle) {\r
+ // Form\r
+ FormToolkit tk = new FormToolkit(parent.getDisplay());\r
+ Form form = tk.createForm(parent);\r
+ tk.decorateFormHeading(form);\r
+ resourceManager = new LocalResourceManager(JFaceResources.getResources(), form);\r
+ form.setText(formTitle);\r
+ form.setImage(resourceManager.createImage(Activator.COMPONENT_TYPE_ICON));\r
+ {\r
+ FormLayout layout = new FormLayout();\r
+ layout.marginBottom = 10;\r
+ layout.marginTop = 10;\r
+ layout.marginLeft = 10;\r
+ layout.marginRight = 10;\r
+ form.getBody().setLayout(layout);\r
+ }\r
+ \r
+ // Data\r
+ data = new ComponentTypeViewerData(tk, _componentType, form);\r
+\r
+ // Sections\r
+ \r
+ sections.add(new ConfigurationPropertiesSection(data));\r
+ sections.add(new DerivedPropertiesSection(data));\r
+\r
+ BundleContext bundleContext = Activator.getContext();\r
+ try {\r
+ ArrayList<ComponentTypeViewerSectionFactory> factories = \r
+ Simantics.getSession().syncRequest(new Read<ArrayList<ComponentTypeViewerSectionFactory>>() {\r
+ @Override\r
+ public ArrayList<ComponentTypeViewerSectionFactory> perform(\r
+ ReadGraph graph) throws DatabaseException {\r
+ ArrayList<ComponentTypeViewerSectionFactory> factories =\r
+ new ArrayList<ComponentTypeViewerSectionFactory>(3);\r
+ try {\r
+ String className = ComponentTypeViewerSectionFactory.class.getName();\r
+ ServiceReference<?>[] references = bundleContext.getAllServiceReferences(className, null);\r
+ if(references != null)\r
+ for(ServiceReference<?> reference : references) {\r
+ ComponentTypeViewerSectionFactory factory = (ComponentTypeViewerSectionFactory)bundleContext.getService(reference);\r
+ if(factory.doesSupport(graph, _componentType))\r
+ factories.add(factory);\r
+ }\r
+ } catch (InvalidSyntaxException e) {\r
+ e.printStackTrace();\r
+ }\r
+ return factories;\r
+ }\r
+ });\r
+ for(ComponentTypeViewerSectionFactory factory : factories)\r
+ sections.add(factory.create(data));\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ \r
+ sections.sort((a,b) -> { return Double.compare(a.getPriority(), b.getPriority()); });\r
+ \r
+ // Sashes\r
+ \r
+ Sash[] sashes = new Sash[sections.size()-1];\r
+ for(int i=0;i<sections.size()-1;++i) {\r
+ Sash sash = new Sash(form.getBody(), SWT.HORIZONTAL);\r
+ sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_WHITE));\r
+ {\r
+ FormData data = new FormData();\r
+ data.top = new FormAttachment(100*(i+1)/sections.size(), 0);\r
+ data.left = new FormAttachment(0, 0);\r
+ data.right = new FormAttachment(100, 0);\r
+ data.height = 10;\r
+ sash.setLayoutData(data);\r
+ }\r
+ sash.addSelectionListener(new SelectionAdapter() {\r
+ public void widgetSelected(SelectionEvent e) {\r
+ sash.setBounds(e.x, e.y, e.width, e.height);\r
+ FormData data = new FormData();\r
+ data.top = new FormAttachment(0, e.y);\r
+ data.left = new FormAttachment(0, 0);\r
+ data.right = new FormAttachment(100, 0);\r
+ data.height = 10;\r
+ sash.setLayoutData(data);\r
+ form.getBody().layout(true);\r
+ }\r
+ });\r
+ sashes[i] = sash;\r
+ }\r
+ for(int i=0;i<sections.size();++i) {\r
+ {\r
+ FormData formData = new FormData();\r
+ formData.top = i > 0 ? new FormAttachment(sashes[i-1]) : new FormAttachment(0, 0);\r
+ formData.left = new FormAttachment(0, 0);\r
+ formData.right = new FormAttachment(100, 0);\r
+ formData.bottom = i < sections.size()-1 \r
+ ? new FormAttachment(sashes[i]) : new FormAttachment(100, 0);\r
+ sections.get(i).getSection().setLayoutData(formData);\r
+ }\r
+ }\r
+\r
+ // Listening\r
+ createGraphListener();\r
+ }\r
+ \r
+ private void createGraphListener() {\r
+ Simantics.getSession().asyncRequest(new UniqueRead<ComponentTypePropertiesResult>() {\r
+ @Override\r
+ public ComponentTypePropertiesResult perform(ReadGraph graph) throws DatabaseException {\r
+ List<ComponentTypeViewerPropertyInfo> result = new ArrayList<>();\r
+ List<NamedResource> connectionPoints = new ArrayList<>();\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ Layer0X L0X = Layer0X.getInstance(graph);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+ for(Resource relation : graph.getObjects(data.componentType, L0.DomainOf)) {\r
+ if(graph.isSubrelationOf(relation, L0.HasProperty)) {\r
+ String name = graph.getRelatedValue(relation, L0.HasName);\r
+ String type = graph.getPossibleRelatedValue(relation, L0.RequiresValueType);\r
+ String label = graph.getPossibleRelatedValue(relation, L0.HasLabel);\r
+ if (label == null)\r
+ label = "";\r
+ String description = graph.getPossibleRelatedValue(relation, L0.HasDescription);\r
+ if (description == null)\r
+ description = "";\r
+ NumberType numberType = null;\r
+ if(type == null)\r
+ type = "Double";\r
+ String unit = graph.getPossibleRelatedValue(relation, L0X.HasUnit, Bindings.STRING);\r
+ String defaultValue = "0";\r
+ String expression = null;\r
+ \r
+ for(Resource assertion : graph.getAssertedObjects(data.componentType, relation)) {\r
+ try {\r
+ expression = graph.getPossibleRelatedValue(assertion, L0.SCLValue_expression, Bindings.STRING);\r
+ if(expression != null) {\r
+ defaultValue = "=" + expression;\r
+ } else {\r
+ Datatype dt = getPossibleDatatype(graph, assertion);\r
+ if (dt == null)\r
+ continue;\r
+ if (dt instanceof NumberType)\r
+ numberType = (NumberType) dt;\r
+ Binding binding = Bindings.getBinding(dt);\r
+ Object value = graph.getValue(assertion, binding);\r
+ try {\r
+ defaultValue = binding.toString(value, true);\r
+ } catch (BindingException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ }\r
+ }\r
+ } catch(DatabaseException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ }\r
+ }\r
+ \r
+ String valid = expression != null ? DerivedPropertiesSection.validateMonitorExpression(graph, data.componentType, relation, expression) : null; \r
+\r
+ boolean immutable = graph.isImmutable(relation);\r
+ ComponentTypeViewerPropertyInfo info =\r
+ new ComponentTypeViewerPropertyInfo(relation, name, type, defaultValue, numberType, unit, label, description, expression, valid, immutable);\r
+ \r
+ Object sectionSpecificData = null;\r
+ double priority = Double.NEGATIVE_INFINITY;\r
+ for(ComponentTypeViewerSection section : sections) {\r
+ Object temp = section.getSectionSpecificData(graph, info);\r
+ if(temp != null) {\r
+ double sectionPriority = section.getDataPriority();\r
+ if(sectionPriority > priority) {\r
+ sectionSpecificData = temp;\r
+ priority = sectionPriority;\r
+ }\r
+ }\r
+ }\r
+ info.sectionSpecificData = sectionSpecificData;\r
+ \r
+ result.add(info);\r
+\r
+ } else if (graph.isInstanceOf(relation, STR.ConnectionRelation)) {\r
+ NamedResource nr = new NamedResource(NameUtils.getSafeName(graph, relation), relation);\r
+ connectionPoints.add(nr);\r
+ }\r
+ }\r
+ Collections.sort(result);\r
+ XSupport xs = graph.peekService(XSupport.class);\r
+ boolean immutable = xs != null ? xs.getImmutable(data.componentType) : false;\r
+ return new ComponentTypePropertiesResult(result, connectionPoints, immutable);\r
+ }\r
+ }, new Listener<ComponentTypePropertiesResult>() {\r
+ @Override\r
+ public void execute(final ComponentTypePropertiesResult result) { \r
+ SWTUtils.asyncExec(data.form.getDisplay(), new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ // Store loaded properties\r
+ data.properties = result.getProperties().toArray(new ComponentTypeViewerPropertyInfo[result.getProperties().size()]);\r
+ data.connectionPoints = result.getConnectionPoints().toArray(new NamedResource[result.getConnectionPoints().size()]);\r
+\r
+ for(ComponentTypeViewerSection section : sections)\r
+ section.update(result);\r
+ setReadOnly(result.isImmutable());\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ ErrorLogger.defaultLogError(t);\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return data.form.isDisposed();\r
+ }\r
+\r
+ });\r
+ }\r
+\r
+ protected Datatype getPossibleDatatype(ReadGraph graph, Resource literal) throws DatabaseException {\r
+ Binding binding = Bindings.getBindingUnchecked(Datatype.class);\r
+ for (Resource dataTypeResource : graph.getObjects(literal, Layer0.getInstance(graph).HasDataType)) {\r
+ Datatype dt = graph.getPossibleValue(dataTypeResource, binding);\r
+ if (dt != null)\r
+ return dt;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public void setFocus() {\r
+ data.form.setFocus();\r
+ }\r
+\r
+ /**\r
+ * @param readOnly\r
+ * @thread SWT\r
+ */\r
+ private void setReadOnly(boolean readOnly) {\r
+ if (readOnly == data.readOnly)\r
+ return;\r
+ data.readOnly = readOnly;\r
+ for(ComponentTypeViewerSection section : sections)\r
+ section.setReadOnly(readOnly);\r
+ IMessageManager mm = data.form.getMessageManager();\r
+ if (readOnly)\r
+ mm.addMessage("readonly", "(Opened in read-only mode)", null, IMessageProvider.INFORMATION);\r
+ else\r
+ mm.removeMessage("readonly");\r
+ }\r
+\r
+}\r