package org.simantics.modeling.ui.componentTypeEditor; import gnu.trove.map.hash.THashMap; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.db.procedure.Listener; import org.simantics.db.request.Read; import org.simantics.graphviz.Edge; import org.simantics.graphviz.Graph; import org.simantics.graphviz.Node; import org.simantics.graphviz.Record; import org.simantics.graphviz.ui.GraphvizComponent; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.structural2.Functions; import org.simantics.structural2.procedural.Component; import org.simantics.structural2.procedural.Connection; import org.simantics.structural2.procedural.ConnectionPoint; import org.simantics.structural2.procedural.Interface; import org.simantics.structural2.procedural.Property; import org.simantics.structural2.procedural.SubstructureElement; import org.simantics.structural2.procedural.Terminal; import org.simantics.ui.workbench.ResourceEditorPart; import org.simantics.utils.datastructures.Pair; public class ProceduralComponentInstanceViewer extends ResourceEditorPart { GraphvizComponent graphviz; @Override public void createPartControl(Composite parent) { graphviz = new GraphvizComponent(parent, SWT.NONE); Simantics.getSession().asyncRequest(new Read() { @Override public Graph perform(ReadGraph graph) throws DatabaseException { Resource inputResource = getInputResource(); Variable context = Variables.getPossibleVariable(graph, inputResource); if(context == null) return createErrorGraph(Messages.ProceduralComponentInstanceViewer_CouldnotCreateVariableForResource); try { List proceduralDesc = Functions.getProceduralDesc(graph, context); if(proceduralDesc == null) return createErrorGraph(Messages.ProceduralComponentInstanceViewer_NoProceduralSubstructure); return createGraph(graph, proceduralDesc); } catch(DatabaseException e) { e.printStackTrace(); return createErrorGraph(e.getMessage()); } } }, new Listener() { @Override public void execute(final Graph graph) { if(!graphviz.isDisposed()) graphviz.getDisplay().asyncExec(new Runnable() { @Override public void run() { if(graphviz.isDisposed()) return; if(graph != null) graphviz.setGraph(graph); } }); } @Override public void exception(Throwable t) { t.printStackTrace(); } @Override public boolean isDisposed() { return graphviz.isDisposed(); } }); } @Override public void setFocus() { graphviz.setFocus(); } private static Graph createErrorGraph(String description) { Graph graph = new Graph(); new Node(graph, description).setShape("rectangle"); //$NON-NLS-1$ return graph; } private static String nameOf(ReadGraph g, Resource r) throws DatabaseException { return g.getRelatedValue(r, Layer0.getInstance(g).HasName); } private static Pair getCp(ReadGraph g, Graph graph, THashMap components, THashMap connectionPoints, ConnectionPoint cp) throws DatabaseException { if(cp instanceof Terminal) { Terminal terminal = (Terminal)cp; return Pair.make(components.get(terminal.component), nameOf(g, terminal.relation)); } else { Interface interface_ = (Interface)cp; Node node = connectionPoints.get(interface_.relation); if(node == null) { node = new Node(graph); node.setShape("diamond"); //$NON-NLS-1$ node.setLabel(nameOf(g, interface_.relation)); connectionPoints.put(interface_.relation, node); } return Pair.make(node, null); } } private static Graph createGraph(ReadGraph g, List proceduralDesc) throws DatabaseException { Graph graph = new Graph(); graph.setRankdir("LR"); //$NON-NLS-1$ THashMap components = new THashMap(); for(SubstructureElement element : proceduralDesc) if(element instanceof Component) { Component component = (Component)element; Record record = new Record(); record.add(component.name + " : " + nameOf(g, component.type)); //$NON-NLS-1$ StringBuilder b = new StringBuilder(); boolean first = true; for(Property property : component.properties) { if(first) first = false; else b.append("\\n"); //$NON-NLS-1$ b.append(nameOf(g, property.relation) + " = " + property.value); //$NON-NLS-1$ } record.add(b.toString()); components.put(component.name, record.toNode(graph)); } THashMap connectionPoints = new THashMap(); for(SubstructureElement element : proceduralDesc) if(element instanceof Connection) { Connection connection = (Connection)element; List cps = connection.connectionPoints; if(cps.size() == 2) { Pair cp1 = getCp(g, graph, components, connectionPoints, cps.get(0)); Pair cp2 = getCp(g, graph, components, connectionPoints, cps.get(1)); Edge edge = new Edge(cp1.first, cp2.first); if(cp1.second != null) { if(cp2.second != null) edge.setLabel(cp1.second + "-" + cp2.second); //$NON-NLS-1$ else edge.setLabel(cp1.second); } else { if(cp2.second != null) edge.setLabel(cp2.second); } } else { Node p = new Node(graph); p.setShape("point"); //$NON-NLS-1$ boolean first = true; for(ConnectionPoint cp : cps) { Pair cp1 = getCp(g, graph, components, connectionPoints, cp); if(first) { Edge edge = new Edge(cp1.first, p); edge.setLabel(cp1.second); first = false; } else { Edge edge = new Edge(p, cp1.first); edge.setLabel(cp1.second); } } } } return graph; } }