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