<graph />\r
<this />\r
</type>\r
- </target>\r \r <target\r interface="org.simantics.sysdyn.ui.browser.nodes.AbstractNode">\r <type\r uri="http://www.simantics.org/Sysdyn-1.0/SysdynModel"\r class="org.simantics.sysdyn.ui.browser.nodes.ModelNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Sysdyn-1.0/IndependentVariable"\r class="org.simantics.sysdyn.ui.browser.nodes.VariableNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Simulation-1.0/Types/Experiment"\r class="org.simantics.sysdyn.ui.browser.nodes.ExperimentNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Sysdyn-1.0/Result"\r class="org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode">\r <this />\r </type>\r </target>\r\r <!-- Inject default connection routing algorithm for sysdyn diagrams -->\r <target interface="org.simantics.g2d.diagram.DiagramClass">\r <adapter uri="http://www.simantics.org/Sysdyn-1.0/ConfigurationDiagram"\r adapterClass="org.simantics.sysdyn.ui.elements2.ConfigurationDiagramClassAdapter" />\r </target>\r\r <!-- Sysdyn symbols -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <resource uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r\r <type uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <type uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <type uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <type uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r </target>\r \r <!-- Sysdyn connections -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <!-- Edges -->\r <resource uri="http://www.simantics.org/Sysdyn-1.0/Connection"\r class="org.simantics.sysdyn.ui.elements2.SysdynConnectionEdgeFactory" />\r <!-- : SYSDYN.Connection-->\r <type uri="http://www.simantics.org/Sysdyn-1.0/Connection"\r class="org.simantics.sysdyn.ui.elements2.SysdynConnectionFactory" />\r </target>\r \r \r
+ </target>\r \r <target\r interface="org.simantics.sysdyn.ui.browser.nodes.AbstractNode">\r <type\r uri="http://www.simantics.org/Sysdyn-1.0/SysdynModel"\r class="org.simantics.sysdyn.ui.browser.nodes.ModelNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Sysdyn-1.0/IndependentVariable"\r class="org.simantics.sysdyn.ui.browser.nodes.VariableNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Simulation-1.0/Types/Experiment"\r class="org.simantics.sysdyn.ui.browser.nodes.ExperimentNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Sysdyn-1.0/Result"\r class="org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode">\r <this />\r </type>\r </target>\r\r <!-- Inject default connection routing algorithm for sysdyn diagrams -->\r <target interface="org.simantics.g2d.diagram.DiagramClass">\r <adapter uri="http://www.simantics.org/Sysdyn-1.0/ConfigurationDiagram"\r adapterClass="org.simantics.sysdyn.ui.elements2.ConfigurationDiagramClassAdapter" />\r </target>\r\r <!-- Sysdyn symbols -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <resource uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r\r <type uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <type uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <type uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <type uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r </target>\r \r <!-- Sysdyn connections -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <!-- Edges -->\r <resource uri="http://www.simantics.org/Sysdyn-1.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.FlowEdgeFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-1.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.DependencyEdgeFactory" />\r <!-- : SYSDYN.Connection-->\r <type uri="http://www.simantics.org/Sysdyn-1.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.FlowConnectionFactory" />\r <type uri="http://www.simantics.org/Sysdyn-1.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.DependencyConnectionFactory" />\r </target>\r \r \r
</adapters>
\ No newline at end of file
import org.simantics.db.Resource;\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
import org.simantics.sysdyn.ui.browser.nodes.AbstractNode;\r
\r
/**\r
ArrayList<AbstractNode> result = new ArrayList<AbstractNode>();\r
for (Resource r : graph.syncRequest(getChildRequest(graph, lib))) {\r
try {\r
+ System.out.println("Is Flow? " + graph.isInstanceOf(r, SysdynResource.getInstance(graph).Flow));\r
AbstractNode n = graph.adapt(r, AbstractNode.class);\r
result.add(n);\r
} catch (DatabaseException e) {\r
import org.simantics.layer0.utils.binaryPredicates.InversePredicate;\r
import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;\r
import org.simantics.mapping.constraint.instructions.IInstruction;\r
+import org.simantics.mapping.constraint.instructions.PrintStateInstruction;\r
import org.simantics.mapping.constraint.instructions.TypedBracketInstruction.CreationInstruction;\r
import org.simantics.mapping.rule.instructions.IRuleInstruction;\r
-import org.simantics.modeling.mapping.NamingCreationInstruction;\r
import org.simantics.sysdyn.SysdynResource;\r
\r
public class DiagramToCompositeMapping3 extends org.simantics.modeling.mapping.DiagramToCompositeMapping3 {\r
\r
- private SysdynResource sdr;\r
+ private SysdynResource sdr;\r
\r
- public DiagramToCompositeMapping3(ReadGraph g, Resource mapping)\r
- throws DatabaseException {\r
- super(g, mapping);\r
- }\r
+ public DiagramToCompositeMapping3(ReadGraph g, Resource mapping)\r
+ throws DatabaseException {\r
+ super(g, mapping);\r
+ }\r
\r
- @Override\r
- protected void setup(ReadGraph graph) {\r
- sdr = SysdynResource.getInstance(graph);\r
- }\r
+ @Override\r
+ protected void setup(ReadGraph graph) {\r
+ sdr = SysdynResource.getInstance(graph);\r
+ }\r
\r
- @Override\r
- protected Resource getConfigurationConnectionType() {\r
- return sdr.Flow;\r
- }\r
+ @Override\r
+ protected Resource getConfigurationConnectionType() {\r
+ return sdr.DependencyConnection;\r
+ }\r
\r
- public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) {\r
- return new SysdynCreationInstruction(project, configurationRoot, component, componentType, configuration);\r
- }\r
- \r
- @Override\r
- protected IRuleInstruction destructiveRule() {\r
- return\r
- if_(and(bf(b.ConsistsOf, Configuration, Component),\r
+ @Override\r
+ public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) {\r
+ return new SysdynCreationInstruction(project, configurationRoot, component, componentType, configuration);\r
+ }\r
+\r
+ @Override\r
+ protected IRuleInstruction additiveRule() {\r
+ return \r
+ \r
+ if_(bf(OrderedSetElementsPredicate.INSTANCE, Diagram, Element),\r
+ query(\r
+ if_(and(bf(b.InstanceOf, Element, ElementType),\r
+ bf(mr.SymbolToComponentType, ElementType, ComponentType)\r
+ ),\r
+ // If element type of the element has a corresponding component type\r
+ createComponentRule(),\r
+ \r
+ if_(and(b(dr.Connection, Element), bf(b.InstanceOf, Element, ElementType), bf(mr.DiagramConnectionTypeToConnectionType, ElementType, ComponentType)),\r
+ createNormalConnectionRule(),\r
+\r
+ if_(b(dr.Flag, Element),\r
+ createFlagRule()\r
+ )\r
+ )\r
+ )\r
+ )\r
+ );\r
+ }\r
+\r
+ @Override\r
+ protected IRuleInstruction destructiveRule() {\r
+ return\r
+ if_(and(bf(b.ConsistsOf, Configuration, Component),\r
b(mapped, Component) // handle only mapped components\r
- ),\r
- query(\r
+ ),\r
+ query(\r
if_(and(bf(mr.ComponentToElement, Component, Element),\r
bf(new InversePredicate(OrderedSetElementsPredicate.INSTANCE), Element, Diagram)\r
- ),\r
- // If component has a corresponding element in the diagram\r
- if_(and(statement_bff(Component, ConnectionRelation, Connection, sr.IsConnectedTo),\r
- b(mapped, Connection)\r
- ),\r
- // If component has a mapped connection\r
- unless(\r
- bf(mr.ConnectionToDiagramConnection, Connection, DiagramConnectionRelation),\r
- // If the configuration connection does not have a correspondence in the diagram remove it\r
- and(deny(exists(Connection)))\r
- )\r
- ),\r
+ ),\r
+ // If component has a corresponding element in the diagram\r
+ if_(and(statement_bff(Component, ConnectionRelation, Connection, sr.IsConnectedTo),\r
+ b(mapped, Connection)\r
+ ),\r
+ // If component has a mapped connection\r
+ unless(\r
+ bf(mr.ConnectionToDiagramConnection, Connection, DiagramConnectionRelation),\r
+ // If the configuration connection does not have a correspondence in the diagram remove it\r
+ and(deny(exists(Connection)))\r
+ )\r
+ ),\r
+\r
+ unless(\r
+ bf(mr.ConnectionToDiagramConnection, Component, Element),\r
+ // If the configuration connection does not have a correspondence in the diagram remove it\r
+ and(deny(exists(Component)))\r
+ )\r
\r
- unless(\r
- bf(mr.ConnectionToDiagramConnection, Component, Element),\r
- // If the configuration connection does not have a correspondence in the diagram remove it\r
- and(deny(exists(Component)))\r
- )\r
- \r
)\r
- )\r
+ )\r
);\r
- }\r
- \r
- protected IInstruction claimBasicConnection() {\r
- return and(exists(\r
+ }\r
+\r
+ @Override\r
+ protected IInstruction claimBasicConnection() {\r
+ return and(exists(\r
bf(mr.DiagramConnectionToConnection, Element, Connection),\r
Connection\r
- ),\r
- bb(b.InstanceOf, Connection, ConnectionType),\r
- bb(b.PartOf, Connection, Configuration)\r
- );\r
- }\r
+ ),\r
+ bb(b.InstanceOf, Connection, ComponentType),\r
+ b(mapped, Connection)\r
\r
+ );\r
+ }\r
+ \r
+// @Override\r
+// protected IInstruction claimBasicConnection() {\r
+// return and(exists(\r
+// bf(mr.DiagramConnectionToConnection, Element, Connection),\r
+// Connection\r
+// ),\r
+// bb(b.InstanceOf, Connection, ComponentType),\r
+// b(mapped, Connection),\r
+// bb(b.PartOf, Connection, Configuration)\r
+// );\r
+// }\r
}\r
import org.simantics.g2d.canvas.impl.CanvasContext;\r
import org.simantics.g2d.diagram.DiagramHints;\r
import org.simantics.g2d.diagram.participant.DeleteHandler;\r
+import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
import org.simantics.g2d.element.ElementClassProviders;\r
import org.simantics.g2d.element.ElementClasses;\r
import org.simantics.g2d.element.IElementClassProvider;\r
import org.simantics.g2d.elementclass.connection.ConnectionClass;\r
import org.simantics.modeling.ui.diagramEditor.handlers.WorkbenchStructuralSelectionProvider2;\r
import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.elements2.ConnectionClasses;\r
+import org.simantics.sysdyn.ui.elements2.SysdynConnectionClass;\r
import org.simantics.sysdyn.ui.properties.SysdynPropertyPage;\r
\r
/**\r
protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
DiagramResource dr = DiagramResource.getInstance(graph);\r
SysdynResource sr = SysdynResource.getInstance(graph);\r
+\r
return ElementClassProviders.mappedProvider(\r
- ElementClasses.CONNECTION, ConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.Connection)),\r
- ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag)\r
+ ElementClasses.CONNECTION, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
+ ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag),\r
+ ConnectionClasses.FLOW, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
+ ConnectionClasses.DEPENDENCY, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection))\r
);\r
+ \r
+ \r
}\r
\r
@Override\r
ctx.add(new WorkbenchStructuralSelectionProvider2(swt, getSite(), structuralPath));\r
}\r
\r
+ @Override\r
+ protected void addOtherParticipants(CanvasContext ctx) {\r
+ }\r
+ \r
+ @Override \r
+ protected PointerInteractor getPointerInteractor() {\r
+ return new org.simantics.sysdyn.ui.editor.participant.PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider());\r
+ }\r
+\r
}\r
--- /dev/null
+package org.simantics.sysdyn.ui.editor.participant;\r
+\r
+import java.awt.AlphaComposite;\r
+import java.awt.Composite;\r
+import java.awt.geom.Point2D;\r
+import java.util.ArrayDeque;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Deque;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.diagram.content.ResourceTerminal;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;\r
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
+import org.simantics.g2d.command.CommandEvent;\r
+import org.simantics.g2d.command.Commands;\r
+import org.simantics.g2d.connection.IConnectionAdvisor;\r
+import org.simantics.g2d.connection.handler.ConnectionHandler;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.DiagramMutator;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.PickContext;\r
+import org.simantics.g2d.diagram.handler.Topology;\r
+import org.simantics.g2d.diagram.handler.Topology.Connection;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
+import org.simantics.g2d.diagram.handler.TransactionContext.TransactionType;\r
+import org.simantics.g2d.diagram.impl.Diagram;\r
+import org.simantics.g2d.diagram.impl.MutatedDiagram;\r
+import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;\r
+import org.simantics.g2d.diagram.participant.ElementPainter;\r
+import org.simantics.g2d.diagram.participant.TerminalPainter;\r
+import org.simantics.g2d.diagram.participant.TerminalPainter.TerminalHoverStrategy;\r
+import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
+import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.IElementClassProvider;\r
+import org.simantics.g2d.element.SceneGraphNodeKey;\r
+import org.simantics.g2d.element.handler.Parent;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.elementclass.BranchPoint;\r
+import org.simantics.g2d.elementclass.FlagClass;\r
+import org.simantics.g2d.elementclass.FlagHandler;\r
+import org.simantics.g2d.event.Event;\r
+import org.simantics.g2d.event.KeyEvent;\r
+import org.simantics.g2d.event.MouseEvent;\r
+import org.simantics.g2d.event.EventHandlerReflection.EventHandler;\r
+import org.simantics.g2d.event.KeyEvent.KeyPressedEvent;\r
+import org.simantics.g2d.event.MouseEvent.MouseButtonEvent;\r
+import org.simantics.g2d.event.MouseEvent.MouseButtonPressedEvent;\r
+import org.simantics.g2d.event.MouseEvent.MouseMovedEvent;\r
+import org.simantics.g2d.participant.KeyUtil;\r
+import org.simantics.g2d.participant.MouseUtil;\r
+import org.simantics.g2d.participant.TransformUtil;\r
+import org.simantics.g2d.snap.ISnapAdvisor;\r
+import org.simantics.scenegraph.Node;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.sysdyn.ui.elements2.ConnectionClasses;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+\r
+public class ConnectTool extends AbstractDiagramParticipant {\r
+\r
+\r
+ public static final Key KEY_SG_NODE = new SceneGraphNodeKey(Node.class, "CONNECT_SG_NODE");\r
+\r
+ @Dependency TransformUtil util;\r
+ @Dependency ElementPainter diagramPainter;\r
+ @Dependency PickContext pickContext;\r
+ @Dependency PointerInteractor pi;\r
+ @Dependency MouseUtil mouseUtil;\r
+ @Dependency KeyUtil keys;\r
+\r
+ boolean createFlags;\r
+ Point2D startPos;\r
+\r
+ IElement startElement;\r
+ Terminal startTerminal;\r
+\r
+ IElement endElement;\r
+ Terminal endTerminal;\r
+\r
+ IDiagram inputDiagram;\r
+ MutatedDiagram ghostDiagram;\r
+ Topology topology;\r
+\r
+ ElementClass connectionClass;\r
+\r
+ ConnectionHandler connectionHandler;\r
+ IElement connection;\r
+ Deque<IElement> edges = new ArrayDeque<IElement>();\r
+ Deque<IElement> controlPoints = new ArrayDeque<IElement>();\r
+ int mouseId;\r
+\r
+ Collection<Terminal> terminals = new ArrayList<Terminal>();\r
+\r
+ TerminalHoverStrategy originalStrategy = null;\r
+ TerminalHoverStrategy terminalHoverStrategy = new TerminalHoverStrategy() {\r
+ @Override\r
+ public boolean highlightEnabled() {\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public boolean highlight(TerminalInfo ti) {\r
+ IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
+ return canConnect(advisor, ti.e, ti.t) != null;\r
+ }\r
+ };\r
+\r
+ public ConnectTool(IDiagram diagram, ElementClass connectionClass, IElement startElement, Terminal startTerminal, int mouseId, Point2D mouseDiagramPos)\r
+ {\r
+ this.inputDiagram = diagram;\r
+ this.connectionClass = connectionClass;\r
+ this.mouseId = mouseId;\r
+ this.startPos = mouseDiagramPos;\r
+ this.startElement = startElement;\r
+ this.startTerminal = startTerminal;\r
+ }\r
+\r
+ @Override\r
+ public void addedToContext(ICanvasContext ctx) {\r
+\r
+ super.addedToContext(ctx);\r
+\r
+ // Force terminals to always be highlighted.\r
+ originalStrategy = getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY);\r
+ setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, terminalHoverStrategy);\r
+\r
+ // See if flags should be created or not\r
+ this.createFlags = Boolean.TRUE.equals(inputDiagram.getHint(DiagramHints.KEY_USE_CONNECTION_FLAGS));\r
+\r
+ // Mutate current diagram and add the connection to the mutated copy.\r
+ ghostDiagram = Diagram.mutate(inputDiagram);\r
+ topology = ghostDiagram.getDiagramClass().getSingleItem(Topology.class);\r
+\r
+ IElement firstElement = null;\r
+ Terminal firstTerminal = null;\r
+\r
+ // Where is start terminal?\r
+ if (startElement != null && startTerminal != null) {\r
+ // Whoomp, there it is. Is it already a part of an existing connection?\r
+ assert ElementUtils.peekDiagram(startElement) == inputDiagram;\r
+ IElement possibleConnection = getConnectionFromPart(startElement);\r
+ if (possibleConnection != null) {\r
+ // TODO: broken.\r
+ connection = ghostDiagram.getMutatedCorrespondence(possibleConnection);\r
+ } else {\r
+ connection = createConnection(connectionClass);\r
+ ghostDiagram.addElement(connection);\r
+ }\r
+\r
+ connectionHandler = connection.getElementClass().getSingleItem(ConnectionHandler.class);\r
+ assert connectionHandler != null;\r
+\r
+ firstElement = ghostDiagram.getMutatedCorrespondence(startElement);\r
+ firstTerminal = startTerminal;\r
+ } else {\r
+ connection = createConnection(connectionClass);\r
+ connectionHandler = connection.getElementClass().getSingleItem(ConnectionHandler.class);\r
+ assert connectionHandler != null;\r
+ ghostDiagram.addElement(connection);\r
+\r
+ firstElement = createBranchPointOrFlag(startPos, EdgeEnd.Begin);\r
+ firstTerminal = ElementUtils.getSingleTerminal(firstElement);\r
+ startElement = firstElement;\r
+ startTerminal = firstTerminal;\r
+ }\r
+\r
+ IElement secondElement = connectionHandler.newBranchPoint(connection);\r
+ controlPoints.add(secondElement);\r
+// ghostDiagram.addElement(secondElement);\r
+ ElementUtils.setPos(secondElement, startPos);\r
+ Terminal secondTerminal = ElementUtils.getSingleTerminal(secondElement);\r
+\r
+ IElement edge = connectionHandler.newEdge(connection);\r
+ edges.add(edge);\r
+// ghostDiagram.addElement(edge);\r
+\r
+ topology.connect(edge, EdgeEnd.Begin, firstElement, firstTerminal);\r
+ topology.connect(edge, EdgeEnd.End, secondElement, secondTerminal);\r
+\r
+ }\r
+\r
+ @Override\r
+ public void removedFromContext(ICanvasContext ctx) {\r
+\r
+ if (getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY) == terminalHoverStrategy) {\r
+ if (originalStrategy != null)\r
+ setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, originalStrategy);\r
+ else\r
+ removeHint(TerminalPainter.TERMINAL_HOVER_STRATEGY);\r
+ }\r
+\r
+ ghostDiagram.destroy();\r
+\r
+ super.removedFromContext(ctx);\r
+ }\r
+\r
+ final static Composite ALPHA_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.75f);\r
+ public static final int PAINT_PRIORITY = ElementPainter.ELEMENT_PAINT_PRIORITY + 5;\r
+\r
+ protected G2DParentNode node = null;\r
+\r
+ @SGInit\r
+ public void initSG(G2DParentNode parent) {\r
+ node = parent.addNode(G2DParentNode.class);\r
+ node.setZIndex(PAINT_PRIORITY);\r
+ update();\r
+ }\r
+\r
+ public void update() {\r
+ if (ghostDiagram != null) {\r
+ diagramPainter.paintDiagram(node, ghostDiagram, ghostDiagram.getDifferences(), KEY_SG_NODE);\r
+ }\r
+ }\r
+\r
+ @SGCleanup\r
+ public void cleanupSG() {\r
+ node.remove();\r
+ node = null;\r
+ }\r
+\r
+ boolean cancelPreviousBend() {\r
+ if (!routePointsAllowed())\r
+ return false;\r
+\r
+ // If not at the first branch point, remove the last branch\r
+ // point and edge. Otherwise, cancel action\r
+ if (controlPoints.size() < 2) {\r
+ DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
+ mutator.clear();\r
+ update();\r
+ remove();\r
+ return true;\r
+ }\r
+ // Cancel prev bend\r
+ IElement lastControlPoint = controlPoints.removeLast();\r
+ IElement prevControlPoint = controlPoints.peekLast();\r
+ IElement lastEdge = edges.removeLast();\r
+ for (Terminal t : ElementUtils.getTerminals(lastControlPoint, terminals, true))\r
+ topology.disconnect(lastEdge, EdgeEnd.End, lastControlPoint, t);\r
+ for (Terminal t : ElementUtils.getTerminals(prevControlPoint, terminals, true))\r
+ topology.disconnect(lastEdge, EdgeEnd.Begin, prevControlPoint, t);\r
+ connectionHandler.removeBranchPoint(connection, lastControlPoint);\r
+ connectionHandler.removeEdge(connection, lastEdge);\r
+ Point2D mousePos = mouseUtil.getMouseInfo(mouseId).canvasPosition;\r
+ ElementUtils.setPos(controlPoints.peekLast(), mousePos);\r
+ DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
+ update();\r
+ setDirty();\r
+ return true;\r
+ }\r
+\r
+ @EventHandler(priority = 20)\r
+ public boolean handleEvent(Event e) {\r
+ // Back-space, cancel prev bend\r
+ if (e instanceof KeyPressedEvent) {\r
+ KeyEvent ke = (KeyEvent) e;\r
+ if (ke.keyCode == java.awt.event.KeyEvent.VK_BACK_SPACE) {\r
+ return cancelPreviousBend();\r
+ }\r
+ }\r
+ if (e instanceof CommandEvent) {\r
+ CommandEvent ce = (CommandEvent) e;\r
+ if (ce.command.equals(Commands.CANCEL))\r
+ {\r
+ DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
+ mutator.clear();\r
+ update();\r
+ remove();\r
+ return true;\r
+ }\r
+ }\r
+ if (e instanceof MouseMovedEvent) {\r
+ MouseMovedEvent me = (MouseMovedEvent) e;\r
+ Point2D mouseControlPos = me.controlPosition;\r
+ Point2D mouseCanvasPos = util.controlToCanvas(mouseControlPos, new Point2D.Double());\r
+\r
+ ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR);\r
+ if (snapAdvisor != null)\r
+ snapAdvisor.snap(mouseCanvasPos);\r
+\r
+ List<TerminalInfo> tiList = ((org.simantics.sysdyn.ui.editor.participant.PointerInteractor)pi).pickTerminals(me.controlPosition);\r
+ TerminalInfo ti = null;\r
+\r
+ IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
+ for(TerminalInfo info : tiList) {\r
+ if(advisor == null || info.e == null || info.t == null)\r
+ continue;\r
+ Object canConnect = canConnect(advisor, info.e, info.t);\r
+ if (canConnect != null) {\r
+ connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
+ ti = info;\r
+ }\r
+ }\r
+\r
+ if (ti != null && !(ti.e == startElement && ti.t == startTerminal)) {\r
+ if (endElement == null) {\r
+ endElement = ti.e;\r
+ endTerminal = ti.t;\r
+\r
+ IElement lastControlPoint = controlPoints.pollLast();\r
+ topology.disconnect(edges.peekLast(), EdgeEnd.End, lastControlPoint, ElementUtils.getSingleTerminal(lastControlPoint));\r
+ connectionHandler.removeBranchPoint(connection, lastControlPoint);\r
+\r
+ topology.connect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
+ DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
+ } else if (!ti.e.equals(endElement) || !ti.t.equals(endTerminal)) {\r
+ topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
+\r
+ endElement = ti.e;\r
+ endTerminal = ti.t;\r
+\r
+ topology.connect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
+ DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
+ }\r
+\r
+ update();\r
+ setDirty();\r
+ return false;\r
+ }\r
+\r
+ {\r
+ connection.removeHint(ElementHints.KEY_CONNECTION_TYPE);\r
+ if (endElement != null) {\r
+ topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
+\r
+ endElement = null;\r
+ endTerminal = null;\r
+\r
+ IElement bp = connectionHandler.newBranchPoint(connection);\r
+ controlPoints.add(bp);\r
+// ghostDiagram.addElement(bp);\r
+ ElementUtils.setPos(controlPoints.peekLast(), mouseCanvasPos);\r
+\r
+ topology.connect(edges.peekLast(), EdgeEnd.End, bp, ElementUtils.getSingleTerminal(bp));\r
+ } else {\r
+ ElementUtils.setPos(controlPoints.peekLast(), mouseCanvasPos);\r
+ }\r
+ DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
+\r
+ update();\r
+ setDirty();\r
+ }\r
+\r
+ }\r
+\r
+ if (e instanceof MouseButtonPressedEvent) {\r
+ MouseButtonEvent me = (MouseButtonEvent) e;\r
+ if (me.button==MouseEvent.LEFT_BUTTON && me.mouseId==mouseId) {\r
+ Point2D mouseControlPos = me.controlPosition;\r
+ Point2D mouseCanvasPos = util.getInverseTransform().transform(mouseControlPos, new Point2D.Double());\r
+\r
+ ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR);\r
+ if (snapAdvisor != null)\r
+ snapAdvisor.snap(mouseCanvasPos);\r
+\r
+ // Clicked on a terminal .. End connection, End mode\r
+ if (endElement != null) {\r
+ attachToBranchPoint();\r
+ commitDiagram();\r
+ update();\r
+ remove(); // Remove ConnectTool participant\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+\r
+ // Don't let any events slip to creator participant\r
+ if (e instanceof MouseEvent) {\r
+ MouseEvent me = (MouseEvent) e;\r
+ return me.mouseId == mouseId;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ private void attachToBranchPoint() {\r
+ DiagramUtils.inDiagramTransaction(diagram, TransactionType.WRITE, new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+\r
+ // We are attaching to a branch point - some reordering is needed!\r
+ if (endElement.getElementClass().containsClass(BranchPoint.class)) {\r
+\r
+ // Scrap everything we have and reconstruct\r
+ DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
+ mutator.clear();\r
+\r
+ HashMap<IElement, IElement> bps = new HashMap<IElement, IElement>();\r
+ for(IElement bp : controlPoints) {\r
+ IElement nbp = mutator.newBranchPoint(endElement);\r
+ Point2D pos = ElementUtils.getPos(bp);\r
+ ElementUtils.setPos(nbp, pos);\r
+ bps.put(bp, nbp);\r
+ }\r
+\r
+ for(IElement edge : edges) {\r
+ IElement newEdge = mutator.newEdge(endElement);\r
+\r
+ // Disconnect and remove old edge\r
+ Connection b = mutator.getConnection(edge, EdgeEnd.Begin);\r
+ Connection e = mutator.getConnection(edge, EdgeEnd.End);\r
+\r
+ IElement mappedB = bps.get(b.node) != null ? bps.get(b.node) : b.node;\r
+ IElement mappedE = bps.get(e.node) != null ? bps.get(e.node) : e.node;\r
+\r
+ mutator.connect(newEdge, b.end, mappedB, b.terminal);\r
+ mutator.connect(newEdge, e.end, mappedE, e.terminal);\r
+ }\r
+ }\r
+ }\r
+ });\r
+ }\r
+\r
+ private void commitDiagram() {\r
+ DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
+ mutator.commit();\r
+ }\r
+\r
+ FlagClass.Type endToFlagType(EdgeEnd end) {\r
+ switch (end) {\r
+ case Begin: return FlagClass.Type.In;\r
+ case End: return FlagClass.Type.Out;\r
+ default: throw new IllegalArgumentException("unrecognized edge end: " + end);\r
+ }\r
+ }\r
+\r
+ IElement createConnection(ElementClass element) {\r
+ DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
+ return mutator.newConnection(element);\r
+ }\r
+\r
+ IElement createFlag(Point2D pos, EdgeEnd connectionEnd) {\r
+\r
+ DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
+ IElement e = mutator.newFlag();\r
+\r
+ FlagHandler fh = e.getElementClass().getSingleItem(FlagHandler.class);\r
+ fh.setType(e, endToFlagType(connectionEnd));\r
+ //fh.setMode(e, FlagClass.Mode.Internal);\r
+ ElementUtils.setPos(e, pos);\r
+\r
+ ghostDiagram.addElement(e);\r
+\r
+ return e;\r
+\r
+ }\r
+\r
+ /**\r
+ * Try to get a connection element from a connection part element.\r
+ *\r
+ * @param e a potential connection part\r
+ * @return <code>null</code> if e is not part a part of a connection.\r
+ */\r
+ IElement getConnectionFromPart(IElement e) {\r
+ Parent parent = e.getElementClass().getAtMostOneItemOfClass(Parent.class);\r
+ if (parent == null)\r
+ return null;\r
+ IElement p = parent.getParent(e);\r
+ if (!p.getElementClass().containsClass(ConnectionHandler.class))\r
+ return null;\r
+ return p;\r
+ }\r
+\r
+ IElement createBranchPointOrFlag(Point2D pos, EdgeEnd connectionEnd) {\r
+ IElement e = null;\r
+ if (createFlags) {\r
+ e = createFlag(pos, connectionEnd);\r
+ } else {\r
+ e = connectionHandler.newBranchPoint(connection);\r
+ ElementUtils.setPos(e, pos);\r
+ }\r
+ return e;\r
+ }\r
+\r
+ boolean routePointsAllowed() {\r
+ return Boolean.TRUE.equals(diagram.getHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS));\r
+ }\r
+\r
+ Object canConnect(IConnectionAdvisor advisor, IElement endElement, Terminal endTerminal) {\r
+ // Making sure that tail (head) terminal doesn't connect to another tail (head) terminal\r
+ Resource t1 = ((ResourceTerminal) startTerminal).getResource();\r
+ Resource t2 = ((ResourceTerminal) endTerminal).getResource();\r
+ if (startElement.equals(endElement) || t1.equals(t2))\r
+ return null;\r
+ \r
+ if (advisor == null)\r
+ return Boolean.TRUE; \r
+ return advisor.canBeConnected(null, startElement, startTerminal, endElement, endTerminal);\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.editor.participant;\r
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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
+\r
+import java.awt.Shape;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.List;\r
+\r
+import org.simantics.g2d.canvas.Hints;\r
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
+import org.simantics.g2d.canvas.impl.DependencyReflection.Reference;\r
+import org.simantics.g2d.connection.IConnectionAdvisor;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.handler.PickContext;\r
+import org.simantics.g2d.diagram.participant.Selection;\r
+import org.simantics.g2d.diagram.participant.TerminalPainter;\r
+import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;\r
+import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.IElementClassProvider;\r
+import org.simantics.g2d.event.MouseEvent;\r
+import org.simantics.g2d.event.EventHandlerReflection.EventHandler;\r
+import org.simantics.g2d.event.MouseEvent.MouseButtonPressedEvent;\r
+import org.simantics.g2d.participant.KeyUtil;\r
+import org.simantics.g2d.participant.MouseUtil;\r
+import org.simantics.g2d.participant.TransformUtil;\r
+import org.simantics.g2d.routing.RouterFactory;\r
+import org.simantics.g2d.snap.ISnapAdvisor;\r
+import org.simantics.g2d.utils.GeometryUtils;\r
+import org.simantics.sysdyn.ui.elements2.ConnectionClasses;\r
+\r
+/**\r
+ * Pointer tool does the following operations with mouse:\r
+ * - Selections\r
+ * - Scale\r
+ * - Rotate\r
+ * - Translate\r
+ * - Draws connections\r
+ *\r
+ *\r
+ * Pointer tool is active only when KEY_TOOLMODE is PointerToolMode\r
+ *\r
+ * TODO Pick rectangle not a point\r
+ *\r
+ * @author Toni Kalajainen\r
+ */\r
+public class PointerInteractor extends org.simantics.g2d.diagram.participant.pointertool.PointerInteractor {\r
+\r
+ @Dependency Selection selection;\r
+ @Dependency KeyUtil keys;\r
+ @Dependency TransformUtil util;\r
+ @Dependency PickContext pickContext;\r
+ @Dependency MouseUtil mice;\r
+ @Reference TerminalPainter terminalPainter;\r
+\r
+ public PointerInteractor(boolean clickSelect, boolean boxSelect, boolean dragElement, boolean dndDragElement, boolean connect, boolean doubleClickEdit, IElementClassProvider newConnectionClassProvider) {\r
+ super(clickSelect, boxSelect, dragElement, dndDragElement, connect, doubleClickEdit, newConnectionClassProvider);\r
+ }\r
+\r
+ @EventHandler(priority = TOOL_PRIORITY)\r
+ public boolean handlePress(MouseButtonPressedEvent me) {\r
+ if (!connects()) return false;\r
+// if (me.button != MouseEvent.LEFT_BUTTON) return false;\r
+ if (getHint(Hints.KEY_TOOL) != Hints.POINTERTOOL) return false;\r
+ assertDependencies();\r
+ Point2D curCanvasPos = util.controlToCanvas(me.controlPosition, null);\r
+ \r
+ // Pick Terminal\r
+ TerminalInfo ti = pickTerminal(me.controlPosition);\r
+ \r
+ if(elementClassProvider != null) {\r
+ \r
+ ElementClass connectionClass = null;\r
+ \r
+ if( me.button == MouseEvent.LEFT_BUTTON && (me.stateMask & MouseEvent.ALT_MASK) != 0) {\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
+ connectionClass = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+ \r
+ } else if (me.button == MouseEvent.RIGHT_BUTTON && (me.stateMask & MouseEvent.ALT_MASK) != 0) {\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
+ connectionClass = elementClassProvider.get(ConnectionClasses.FLOW);\r
+ } else {\r
+ return false;\r
+ }\r
+ \r
+ ConnectTool bsi = null;\r
+ if (ti != null) {\r
+ IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
+ if (advisor == null || (advisor != null && advisor.canBeginConnection(null, ti.e, ti.t))) {\r
+ bsi = new ConnectTool(diagram, connectionClass, ti.e, ti.t, me.mouseId, curCanvasPos);\r
+ }\r
+ } else {\r
+ ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR);\r
+ if(snapAdvisor != null) \r
+ snapAdvisor.snap(curCanvasPos);\r
+\r
+ // Start connection out of thin air, without a terminal.\r
+ bsi = new ConnectTool(diagram, elementClassProvider.get(ConnectionClasses.DEPENDENCY), null, null, me.mouseId, curCanvasPos);\r
+ }\r
+ if (bsi != null) {\r
+ getContext().add(bsi);\r
+ return true;\r
+ }\r
+ \r
+ }\r
+ return false;\r
+ }\r
+ \r
+ public List<TerminalInfo> pickTerminals(Point2D controlPos)\r
+ {\r
+ Rectangle2D controlPickRect = new Rectangle2D.Double(controlPos.getX()-PointerInteractor.PICK_DIST, controlPos.getY()-PointerInteractor.PICK_DIST, PointerInteractor.PICK_DIST*2+1, PointerInteractor.PICK_DIST*2+1);\r
+ Shape canvasPickRect = GeometryUtils.transformShape(controlPickRect, util.getInverseTransform());\r
+ List<TerminalInfo> ti = TerminalUtil.pickTerminals(diagram, canvasPickRect, false, true);\r
+ return ti;\r
+ }\r
+\r
+ /**\r
+ * Paint bend handles. Handle is a selectable and draggable object.\r
+ *\r
+ * @param gc\r
+ */\r
+// @Painter(priority = TerminalPainter.PAINT_PRIORITY + 10)\r
+// public void paintBendHandles(GraphicsContext gc) {\r
+// if (!connects()) return;\r
+// double controlScale = GeometryUtils.getScale(gc.getGraphics2D().getTransform());\r
+// // TODO: use another key for setting the bend point stroke color\r
+// //Color bgColor = getHint(Hints.KEY_BACKGROUND_COLOR);\r
+// Color bgColor = null;\r
+// if (bgColor==null) bgColor = Color.GRAY;\r
+// Graphics2D g = gc.createClone();\r
+// util.controlToCanvas(g);\r
+// if (!connects()) return;\r
+// ArrayList<Bend> bends = new ArrayList<Bend>();\r
+// AffineTransform _at = g.getTransform();\r
+// Point2D bendPos = new Point2D.Double();\r
+// for (IElement e : selection.getAllSelections())\r
+// {\r
+// BendsHandler bh = e.getElementClass().getAtMostOneItemOfClass(BendsHandler.class);\r
+// if (bh==null) continue;\r
+// bends.clear(); bh.getBends(e, bends);\r
+// if (bends.isEmpty()) continue;\r
+// g.setTransform(_at);\r
+// g.transform( ElementUtils.getTransform(e) );\r
+// double scale = GeometryUtils.getScale( g.getTransform() );\r
+// for (Bend b : bends) {\r
+// bh.getBendPosition(e, b, bendPos);\r
+// g.translate(bendPos.getX(), bendPos.getY());\r
+// g.setColor(Color.WHITE);\r
+// g.scale(controlScale / scale, controlScale / scale);\r
+// g.fill(BENDS);\r
+// g.setColor(bgColor);\r
+// g.draw(BENDS);\r
+// g.scale(scale / controlScale, scale / controlScale);\r
+// g.translate(-bendPos.getX(), -bendPos.getY());\r
+// }\r
+// }\r
+// }\r
+// static final Shape BENDS = new Rectangle2D.Double(-5, -5, 11, 11);\r
+\r
+\r
+\r
+ // <SCALING>\r
+ /*\r
+ @EventHandler(priority = -1)\r
+ public boolean scaleKey(KeyEvent ke) {\r
+ boolean alt = (ke.stateMask & java.awt.event.MouseEvent.ALT_DOWN_MASK) != 0;\r
+ if (alt && ke.keyCode == java.awt.event.KeyEvent.VK_S) {\r
+ //ScaleMode sm = new ScaleMode(me.startCanvasPos, curCanvasPos, me.mouseId, elementsToScale);\r
+ //getContext().add(sm);\r
+ }\r
+ return false;\r
+ }\r
+ // </SCALING>\r
+ */\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+public class ConnectionClasses {\r
+\r
+ public static final Object CONNECTION = new Object() {\r
+ public String toString() { return "CONNECTION"; }\r
+ };\r
+\r
+ public static final Object FLAG = new Object() {\r
+ public String toString() { return "FLAG"; }\r
+ };\r
+\r
+ public static final Object FLOW = new Object() {\r
+ public String toString() { return "CONNECTION"; }\r
+ };\r
+\r
+ public static final Object DEPENDENCY = new Object() {\r
+ public String toString() { return "DEPENDENCY"; }\r
+ };\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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.sysdyn.ui.elements2;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.adapter.ElementFactoryAdapter;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+import org.simantics.g2d.elementclass.connection.ConnectionClass;\r
+import org.simantics.g2d.routing.RouterFactory;\r
+\r
+/**\r
+ * An element class for single connection entity elements. A connection entity\r
+ * consists of connection edge segments and branch points as its children.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class DependencyConnectionFactory extends ElementFactoryAdapter {\r
+\r
+ public static final ElementClass CLASS = SysdynConnectionClass.CLASS;\r
+\r
+ @Override\r
+ public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, final AsyncProcedure<ElementClass> procedure) {\r
+ DiagramResource dr = graph.getService(DiagramResource.class);\r
+ graph.forSingleType(elementType, dr.Connection, new AsyncProcedure<Resource>() {\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+ procedure.exception(graph, throwable);\r
+ }\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, Resource connectionType) {\r
+ procedure.execute(graph, ConnectionClass.CLASS.newClassWith(false, new StaticObjectAdapter(connectionType)));\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void load(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource,\r
+ final IElement element, final AsyncProcedure<IElement> procedure) {\r
+ element.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
+ procedure.execute(graph, element);\r
+ }\r
+\r
+}\r
import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;\r
import org.simantics.g2d.utils.PathUtils;\r
import org.simantics.scenegraph.g2d.G2DParentNode;\r
-import org.simantics.scenegraph.g2d.nodes.EdgeNode;\r
import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
\r
/**\r
* @author Toni Kalajainen\r
*/\r
-public class SysdynEdgeClass {\r
+public class DependencyEdgeClass {\r
\r
// TODO scale, rotate, move, transform\r
public static final ElementClass CLASS =\r
\r
public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);\r
\r
- public static final Key KEY_SG_NODE = new SceneGraphNodeKey(EdgeNode.class, "EDGE_NODE");\r
+ public static final Key KEY_SG_NODE = new SceneGraphNodeKey(DependencyNode.class, "EDGE_NODE");\r
\r
@Override\r
public void init(IElement e, G2DParentNode parent) {\r
- ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), EdgeNode.class);\r
+ ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), DependencyNode.class);\r
update(e);\r
}\r
\r
}\r
\r
public void update(final IElement e) {\r
- EdgeNode node = e.getHint(KEY_SG_NODE);\r
+ DependencyNode node = e.getHint(KEY_SG_NODE);\r
if(node == null) return;\r
\r
EdgeVisuals vh = e.getElementClass().getSingleItem(EdgeVisuals.class);\r
// Read bends\r
BendsHandler bh = e.getElementClass().getSingleItem(BendsHandler.class);\r
Path2D line = bh.getPath(e);\r
-\r
+ \r
boolean drawArrows = at1 != ArrowType.None || at2 != ArrowType.None;\r
//line = clipLineEnds(line, beginTerminalShape, endTerminalShape);\r
\r
PathIterator pi = line.getPathIterator(null);\r
drawArrows &= PathUtils.getPathArrows(pi, first, dir1, last, dir2);\r
\r
- EdgeNode.ArrowType pat1 = convert(at1);\r
- EdgeNode.ArrowType pat2 = convert(at2);\r
+ DependencyNode.ArrowType pat1 = convert(at1);\r
+ DependencyNode.ArrowType pat2 = convert(at2);\r
\r
node.init(new GeneralPath(line), stroke, c, dir1, dir2, first, last, as1, as2, pat1, pat2, null, null);\r
}\r
\r
- private static EdgeNode.ArrowType convert(ArrowType at) {\r
+ private static DependencyNode.ArrowType convert(ArrowType at) {\r
switch (at) {\r
- case None: return EdgeNode.ArrowType.None;\r
- case Stroke: return EdgeNode.ArrowType.Stroke;\r
- case Fill: return EdgeNode.ArrowType.Fill;\r
+ case None: return DependencyNode.ArrowType.None;\r
+ case Stroke: return DependencyNode.ArrowType.Stroke;\r
+ case Fill: return DependencyNode.ArrowType.Fill;\r
default:\r
throw new IllegalArgumentException("unsupported arrow type: " + at);\r
}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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.sysdyn.ui.elements2;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.adapter.ElementFactoryAdapter;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+\r
+/**\r
+ * An element class factory for sysdyn dependency connection edge segments.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class DependencyEdgeFactory extends ElementFactoryAdapter {\r
+\r
+ private static final ElementClass CLASS = DependencyEdgeClass.CLASS;\r
+\r
+ @Override\r
+ public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType,\r
+ AsyncProcedure<ElementClass> procedure) {\r
+ procedure.execute(graph, CLASS);\r
+ }\r
+\r
+ @Override\r
+ public void getClass(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource,\r
+ AsyncProcedure<ElementClass> procedure) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+import java.awt.AlphaComposite;\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Composite;\r
+import java.awt.Graphics2D;\r
+import java.awt.RenderingHints;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import org.simantics.scenegraph.g2d.G2DNode;\r
+\r
+public class DependencyNode extends G2DNode {\r
+\r
+ private static final long serialVersionUID = 1294351381209071074L;\r
+\r
+ public static enum ArrowType { None, Stroke, Fill, Both }\r
+\r
+ protected Color color = null;\r
+ protected Stroke stroke = null;\r
+ protected Shape shape = null;\r
+ protected Point2D firstdir = null;\r
+ protected Point2D lastdir = null;\r
+ protected Point2D first = null;\r
+ protected Point2D last = null;\r
+ protected double firstsize = 0;\r
+ protected double lastsize = 0;\r
+ protected ArrowType first_at = null;\r
+ protected ArrowType last_at = null;\r
+ protected Shape firstShape = null;\r
+ protected Shape lastShape = null;\r
+\r
+ private transient Rectangle2D bounds;\r
+\r
+ @SyncField({"color", "stroke", "shape", "firstdir", "lastdir", "first", "last", "firstsize", "lastsize", "first_at", "last_at"})\r
+ public void init(Shape shape, Stroke stroke, Color color, Point2D firstdir, Point2D lastdir, Point2D first, Point2D last, double firstsize, double lastsize, ArrowType first_at, ArrowType last_at, Shape firstShape, Shape lastShape) {\r
+ this.color = color;\r
+ this.stroke = stroke;\r
+ this.shape = shape;\r
+ this.firstdir = firstdir;\r
+ this.lastdir = lastdir;\r
+ this.first = first;\r
+ this.last = last;\r
+ this.firstsize = firstsize;\r
+ this.lastsize = lastsize;\r
+ this.first_at = first_at;\r
+ this.last_at = last_at;\r
+ this.firstShape = firstShape;\r
+ this.lastShape = lastShape;\r
+\r
+ if (shape != null) {\r
+ this.bounds = shape.getBounds2D();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void render(Graphics2D g) {\r
+ if(color != null) g.setColor(color);\r
+ if(stroke == null || shape == null) return;\r
+\r
+ if(alphaComposite != null) {\r
+ g.setComposite(alphaComposite);\r
+ }\r
+ \r
+ Stroke effectiveStroke = stroke;\r
+ if(dynamicStroke != null) {\r
+ effectiveStroke = dynamicStroke;\r
+ }\r
+\r
+ Color effectiveColor = color;\r
+ if(dynamicColor != null) {\r
+ effectiveColor = dynamicColor;\r
+ }\r
+\r
+ g.setStroke(effectiveStroke);\r
+\r
+ // NICENESS\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+\r
+ //g.draw(shape);\r
+\r
+ // Draw line "halo"\r
+ float f = 0.1f * 3f;\r
+ Color background = Color.WHITE; // FIXME\r
+ g.setColor(background);\r
+ g.setStroke(new BasicStroke(f));\r
+ g.draw(shape);\r
+\r
+ // Draw line\r
+ g.setColor(effectiveColor);\r
+ g.setStroke(effectiveStroke);\r
+ g.draw(shape);\r
+\r
+ // Draw line ends if necessary.\r
+ boolean drawArrows = first_at != ArrowType.None || last_at != ArrowType.None;\r
+ if (!drawArrows)\r
+ return;\r
+\r
+ g.setStroke(ARROW_STROKE);\r
+ AffineTransform at = g.getTransform();\r
+\r
+ double theta = Math.atan2(firstdir.getY(), firstdir.getX()) - Math.PI/2;\r
+ g.translate(first.getX(), first.getY());\r
+ g.rotate(theta);\r
+ g.scale(firstsize, firstsize);\r
+\r
+ if (first_at == ArrowType.Fill)\r
+ g.fill(FILLED_ARROW);\r
+ else if (first_at == ArrowType.Stroke)\r
+ g.draw(NORMAL_ARROW);\r
+\r
+ g.setTransform(at);\r
+\r
+ theta = Math.atan2(lastdir.getY(), lastdir.getX()) - Math.PI/2;\r
+\r
+ g.translate(last.getX(), last.getY());\r
+ g.rotate(theta);\r
+ g.scale(lastsize, lastsize);\r
+\r
+ if (last_at == ArrowType.Fill)\r
+ g.fill(FILLED_ARROW);\r
+ else if (last_at == ArrowType.Stroke)\r
+ g.draw(NORMAL_ARROW);\r
+ }\r
+\r
+\r
+ public transient final static GeneralPath NORMAL_ARROW;\r
+ public transient final static GeneralPath FILLED_ARROW;\r
+ public transient static final Stroke ARROW_STROKE = new BasicStroke(1.0f);\r
+\r
+ static {\r
+ FILLED_ARROW = new GeneralPath();\r
+ FILLED_ARROW.moveTo(-0.5f, 1f);\r
+ FILLED_ARROW.lineTo( 0f, 0f);\r
+ FILLED_ARROW.lineTo( 0.5f, 1f);\r
+ FILLED_ARROW.closePath();\r
+\r
+ NORMAL_ARROW = new GeneralPath();\r
+ NORMAL_ARROW.moveTo(-0.5f, 1f);\r
+ NORMAL_ARROW.lineTo( 0f, 0f);\r
+ NORMAL_ARROW.lineTo( 0.5f, 1f);\r
+ }\r
+\r
+ @Override\r
+ public Rectangle2D getBoundsInLocal() {\r
+ return bounds;\r
+ }\r
+\r
+ protected Composite alphaComposite = null;\r
+ protected Stroke dynamicStroke = null;\r
+ protected Color dynamicColor = null;\r
+\r
+ @Override\r
+ public void setValue(String key, Object value) {\r
+\r
+ if ("alpha".equals(key)) {\r
+ Float val = Float.parseFloat((String)value);\r
+ alphaComposite = AlphaComposite.getInstance(AlphaComposite. SRC_OVER, val);\r
+ } else if ("width".equals(key)) {\r
+ dynamicStroke = new BasicStroke(((Double)value).floatValue());\r
+ } else if ("color".equals(key)) {\r
+ try {\r
+ dynamicColor = new Color(Integer.parseInt(value.toString(), 16));\r
+ } catch (Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void initValues() {\r
+ dynamicStroke = null;\r
+ dynamicColor = null;\r
+ alphaComposite = null;\r
+ }\r
+\r
+\r
+}\r
import org.simantics.diagram.adapter.ElementFactoryAdapter;\r
import org.simantics.diagram.stubs.DiagramResource;\r
import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
import org.simantics.g2d.diagram.IDiagram;\r
import org.simantics.g2d.element.ElementClass;\r
import org.simantics.g2d.element.IElement;\r
import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
import org.simantics.g2d.elementclass.connection.ConnectionClass;\r
+import org.simantics.g2d.routing.RouterFactory;\r
\r
/**\r
* An element class for single connection entity elements. A connection entity\r
* \r
* @author Tuukka Lehtonen\r
*/\r
-public class SysdynConnectionFactory extends ElementFactoryAdapter {\r
+public class FlowConnectionFactory extends ElementFactoryAdapter {\r
\r
public static final ElementClass CLASS = SysdynConnectionClass.CLASS;\r
\r
@Override\r
public void load(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource,\r
final IElement element, final AsyncProcedure<IElement> procedure) {\r
+ element.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
procedure.execute(graph, element);\r
}\r
\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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.sysdyn.ui.elements2;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.PathIterator;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.Topology;\r
+import org.simantics.g2d.diagram.handler.Topology.Connection;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.SceneGraphNodeKey;\r
+import org.simantics.g2d.element.handler.BendsHandler;\r
+import org.simantics.g2d.element.handler.EdgeVisuals;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.ArrowType;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.handler.Rotate;\r
+import org.simantics.g2d.element.handler.SceneGraph;\r
+import org.simantics.g2d.element.handler.TerminalLayout;\r
+import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals;\r
+import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;\r
+import org.simantics.g2d.element.handler.impl.FillColorImpl;\r
+import org.simantics.g2d.element.handler.impl.ParentImpl;\r
+import org.simantics.g2d.element.handler.impl.ShapePick;\r
+import org.simantics.g2d.element.handler.impl.SimpleElementLayers;\r
+import org.simantics.g2d.elementclass.BranchPoint;\r
+import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler;\r
+import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;\r
+import org.simantics.g2d.utils.PathUtils;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+\r
+/**\r
+ * @author Toni Kalajainen\r
+ */\r
+public class FlowEdgeClass {\r
+\r
+ // TODO scale, rotate, move, transform\r
+ public static final ElementClass CLASS =\r
+ ElementClass.compile(\r
+ SysdynEdgeSceneGraph.INSTANCE,\r
+ EdgeHandler.INSTANCE,\r
+ ConfigurableEdgeVisuals.DEFAULT,\r
+ FillColorImpl.BLACK,\r
+ FixedTransform.INSTANCE,\r
+ ShapePick.INSTANCE,\r
+ ConnectionSelectionOutline.INSTANCE,\r
+ SimpleElementLayers.INSTANCE,\r
+ ParentImpl.INSTANCE\r
+ ).setId("EdgeClass.STRAIGHT");\r
+\r
+ public static class SysdynEdgeSceneGraph implements SceneGraph {\r
+\r
+ private static final long serialVersionUID = 2914383071126238996L;\r
+\r
+ public static final SysdynEdgeSceneGraph INSTANCE = new SysdynEdgeSceneGraph();\r
+\r
+ public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);\r
+\r
+ public static final Key KEY_SG_NODE = new SceneGraphNodeKey(FlowNode.class, "EDGE_NODE");\r
+\r
+ @Override\r
+ public void init(IElement e, G2DParentNode parent) {\r
+ ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), FlowNode.class);\r
+ update(e);\r
+ }\r
+\r
+ @Override\r
+ public void cleanup(IElement e) {\r
+ ElementUtils.removePossibleNode(e, KEY_SG_NODE);\r
+ }\r
+\r
+ public void update(final IElement e) {\r
+ FlowNode node = e.getHint(KEY_SG_NODE);\r
+ if(node == null) return;\r
+\r
+ EdgeVisuals vh = e.getElementClass().getSingleItem(EdgeVisuals.class);\r
+ ArrowType at1 = vh.getArrowType(e, EdgeEnd.Begin);\r
+ ArrowType at2 = vh.getArrowType(e, EdgeEnd.End);\r
+ Stroke stroke = new FlowStroke(\r
+ new BasicStroke(0.4f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER), \r
+ new BasicStroke(0.1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));\r
+// Stroke stroke = vh.getStroke(e);\r
+ //StrokeType strokeType = vh.getStrokeType(e);\r
+ double as1 = vh.getArrowSize(e, EdgeEnd.Begin);\r
+ double as2 = vh.getArrowSize(e, EdgeEnd.End);\r
+\r
+ Color c = ElementUtils.getFillColor(e, Color.BLACK);\r
+\r
+ // Get terminal shape for clipping the painted edge to its bounds.\r
+ IDiagram diagram = ElementUtils.peekDiagram(e);\r
+ Shape beginTerminalShape = null;\r
+ Shape endTerminalShape = null;\r
+ if (diagram != null) {\r
+ Topology topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class);\r
+ if (topology != null) {\r
+ Connection beginConnection = topology.getConnection(e, EdgeEnd.Begin);\r
+ Connection endConnection = topology.getConnection(e, EdgeEnd.End);\r
+ beginTerminalShape = getTerminalShape(beginConnection);\r
+ endTerminalShape = getTerminalShape(endConnection);\r
+ int beginBranchDegree = getBranchPointDegree(beginConnection, topology);\r
+ int endBranchDegree = getBranchPointDegree(endConnection, topology);\r
+ if (beginBranchDegree > 0 && beginBranchDegree < 3) {\r
+ at1 = ArrowType.None;\r
+ }\r
+ if (endBranchDegree > 0 && endBranchDegree < 3) {\r
+ at2 = ArrowType.None;\r
+ }\r
+ }\r
+ }\r
+\r
+ // Read bends\r
+ BendsHandler bh = e.getElementClass().getSingleItem(BendsHandler.class);\r
+ Path2D line = bh.getPath(e);\r
+ \r
+ boolean drawArrows = at1 != ArrowType.None || at2 != ArrowType.None;\r
+ //line = clipLineEnds(line, beginTerminalShape, endTerminalShape);\r
+\r
+ Point2D first = new Point2D.Double();\r
+ Point2D dir1 = new Point2D.Double();\r
+ Point2D last = new Point2D.Double();\r
+ Point2D dir2 = new Point2D.Double();\r
+ PathIterator pi = line.getPathIterator(null);\r
+ drawArrows &= PathUtils.getPathArrows(pi, first, dir1, last, dir2);\r
+\r
+ FlowNode.ArrowType pat1 = convert(at1);\r
+ FlowNode.ArrowType pat2 = convert(at2);\r
+\r
+ node.init(new GeneralPath(line), stroke, c, dir1, dir2, first, last, as1, as2, pat1, pat2, null, null);\r
+ }\r
+\r
+ private static FlowNode.ArrowType convert(ArrowType at) {\r
+ switch (at) {\r
+ case None: return FlowNode.ArrowType.None;\r
+ case Stroke: return FlowNode.ArrowType.Stroke;\r
+ case Fill: return FlowNode.ArrowType.Fill;\r
+ default:\r
+ throw new IllegalArgumentException("unsupported arrow type: " + at);\r
+ }\r
+ }\r
+\r
+ private static final Rectangle2D EMPTY = new Rectangle2D.Double();\r
+\r
+ private static Shape getTerminalShape(Connection connection) {\r
+ if (connection != null && connection.node != null && connection.terminal != null) {\r
+ TerminalLayout layout = connection.node.getElementClass().getAtMostOneItemOfClass(TerminalLayout.class);\r
+ if (layout != null) {\r
+ //return layout.getTerminalShape(connection.node, connection.terminal);\r
+ Shape shp = layout.getTerminalShape(connection.node, connection.terminal);\r
+ Rotate rotate = connection.node.getElementClass().getAtMostOneItemOfClass(Rotate.class);\r
+ if (rotate == null)\r
+ return shp;\r
+\r
+ double theta = rotate.getAngle(connection.node);\r
+ return AffineTransform.getRotateInstance(theta).createTransformedShape(shp);\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private final Collection<Connection> connectionsTemp = new ArrayList<Connection>();\r
+ private int getBranchPointDegree(Connection connection, Topology topology) {\r
+ if (connection != null && connection.node != null) {\r
+ if (connection.node.getElementClass().containsClass(BranchPoint.class)) {\r
+ connectionsTemp.clear();\r
+ topology.getConnections(connection.node, connection.terminal, connectionsTemp);\r
+ int degree = connectionsTemp.size();\r
+ connectionsTemp.clear();\r
+ return degree;\r
+ }\r
+ }\r
+ return -1;\r
+ }\r
+\r
+ }\r
+\r
+}\r
import org.simantics.g2d.element.ElementClass;\r
\r
/**\r
- * An element class factory for sysdyn connection edge segments.\r
+ * An element class factory for sysdyn flow connection edge segments.\r
* \r
* @author Tuukka Lehtonen\r
*/\r
-public class SysdynConnectionEdgeFactory extends ElementFactoryAdapter {\r
+public class FlowEdgeFactory extends ElementFactoryAdapter {\r
\r
- private static final ElementClass CLASS = SysdynEdgeClass.CLASS;\r
+ private static final ElementClass CLASS = FlowEdgeClass.CLASS;\r
\r
@Override\r
public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType,\r
--- /dev/null
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+import java.awt.AlphaComposite;\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Composite;\r
+import java.awt.Graphics2D;\r
+import java.awt.RenderingHints;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import org.simantics.scenegraph.g2d.G2DNode;\r
+\r
+public class FlowNode extends G2DNode {\r
+\r
+ private static final long serialVersionUID = 1294351381209071074L;\r
+\r
+ public static enum ArrowType { None, Stroke, Fill, Both }\r
+\r
+ protected Color color = null;\r
+ protected Stroke stroke = null;\r
+ protected Shape shape = null;\r
+ protected Point2D firstdir = null;\r
+ protected Point2D lastdir = null;\r
+ protected Point2D first = null;\r
+ protected Point2D last = null;\r
+ protected double firstsize = 0;\r
+ protected double lastsize = 0;\r
+ protected ArrowType first_at = null;\r
+ protected ArrowType last_at = null;\r
+ protected Shape firstShape = null;\r
+ protected Shape lastShape = null;\r
+\r
+ private transient Rectangle2D bounds;\r
+\r
+ @SyncField({"color", "stroke", "shape", "firstdir", "lastdir", "first", "last", "firstsize", "lastsize", "first_at", "last_at"})\r
+ public void init(Shape shape, Stroke stroke, Color color, Point2D firstdir, Point2D lastdir, Point2D first, Point2D last, double firstsize, double lastsize, ArrowType first_at, ArrowType last_at, Shape firstShape, Shape lastShape) {\r
+ this.color = color;\r
+ this.stroke = stroke;\r
+ this.shape = shape;\r
+ this.firstdir = firstdir;\r
+ this.lastdir = lastdir;\r
+ this.first = first;\r
+ this.last = last;\r
+ this.firstsize = firstsize;\r
+ this.lastsize = lastsize;\r
+ this.first_at = first_at;\r
+ this.last_at = last_at;\r
+ this.firstShape = firstShape;\r
+ this.lastShape = lastShape;\r
+\r
+ if (shape != null) {\r
+ this.bounds = shape.getBounds2D();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void render(Graphics2D g) {\r
+ if(color != null) g.setColor(color);\r
+ if(stroke == null || shape == null) return;\r
+\r
+ if(alphaComposite != null) {\r
+ g.setComposite(alphaComposite);\r
+ }\r
+ \r
+ Stroke effectiveStroke = stroke;\r
+ if(dynamicStroke != null) {\r
+ effectiveStroke = dynamicStroke;\r
+ }\r
+\r
+ Color effectiveColor = color;\r
+ if(dynamicColor != null) {\r
+ effectiveColor = dynamicColor;\r
+ }\r
+\r
+ g.setStroke(effectiveStroke);\r
+\r
+ // NICENESS\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+\r
+ //g.draw(shape);\r
+\r
+ // Draw line "halo"\r
+ float f = 0.1f * 3f;\r
+ Color background = Color.WHITE; // FIXME\r
+ g.setColor(background);\r
+ g.setStroke(new BasicStroke(f));\r
+ g.draw(shape);\r
+\r
+ // Draw line\r
+ g.setColor(effectiveColor);\r
+ g.setStroke(effectiveStroke);\r
+ g.draw(shape);\r
+\r
+ // Draw line ends if necessary.\r
+ boolean drawArrows = first_at != ArrowType.None || last_at != ArrowType.None;\r
+ if (!drawArrows)\r
+ return;\r
+\r
+ g.setStroke(ARROW_STROKE);\r
+ AffineTransform at = g.getTransform();\r
+\r
+ double theta = Math.atan2(firstdir.getY(), firstdir.getX()) - Math.PI/2;\r
+ g.translate(first.getX(), first.getY());\r
+ g.rotate(theta);\r
+ g.scale(firstsize, firstsize);\r
+\r
+ if (first_at == ArrowType.Fill)\r
+ g.fill(FILLED_ARROW);\r
+ else if (first_at == ArrowType.Stroke)\r
+ g.draw(NORMAL_ARROW);\r
+\r
+ g.setTransform(at);\r
+\r
+ theta = Math.atan2(lastdir.getY(), lastdir.getX()) - Math.PI/2;\r
+\r
+ g.translate(last.getX(), last.getY());\r
+ g.rotate(theta);\r
+ g.scale(lastsize, lastsize);\r
+\r
+ if (last_at == ArrowType.Fill)\r
+ g.fill(FILLED_ARROW);\r
+ else if (last_at == ArrowType.Stroke)\r
+ g.draw(NORMAL_ARROW);\r
+ }\r
+\r
+\r
+ public transient final static GeneralPath NORMAL_ARROW;\r
+ public transient final static GeneralPath FILLED_ARROW;\r
+ public transient static final Stroke ARROW_STROKE = new BasicStroke(1.0f);\r
+\r
+ static {\r
+ FILLED_ARROW = new GeneralPath();\r
+ FILLED_ARROW.moveTo(-0.5f, 1f);\r
+ FILLED_ARROW.lineTo( 0f, 0f);\r
+ FILLED_ARROW.lineTo( 0.5f, 1f);\r
+ FILLED_ARROW.closePath();\r
+\r
+ NORMAL_ARROW = new GeneralPath();\r
+ NORMAL_ARROW.moveTo(-0.5f, 1f);\r
+ NORMAL_ARROW.lineTo( 0f, 0f);\r
+ NORMAL_ARROW.lineTo( 0.5f, 1f);\r
+ }\r
+\r
+ @Override\r
+ public Rectangle2D getBoundsInLocal() {\r
+ return bounds;\r
+ }\r
+\r
+ protected Composite alphaComposite = null;\r
+ protected Stroke dynamicStroke = null;\r
+ protected Color dynamicColor = null;\r
+\r
+ @Override\r
+ public void setValue(String key, Object value) {\r
+\r
+ if ("alpha".equals(key)) {\r
+ Float val = Float.parseFloat((String)value);\r
+ alphaComposite = AlphaComposite.getInstance(AlphaComposite. SRC_OVER, val);\r
+ } else if ("width".equals(key)) {\r
+ dynamicStroke = new BasicStroke(((Double)value).floatValue());\r
+ } else if ("color".equals(key)) {\r
+ try {\r
+ dynamicColor = new Color(Integer.parseInt(value.toString(), 16));\r
+ } catch (Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void initValues() {\r
+ dynamicStroke = null;\r
+ dynamicColor = null;\r
+ alphaComposite = null;\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+\r
+public class FlowStroke implements Stroke {\r
+ private Stroke stroke1, stroke2;\r
+\r
+ public FlowStroke( Stroke stroke1, Stroke stroke2 ) {\r
+ this.stroke1 = stroke1;\r
+ this.stroke2 = stroke2;\r
+ }\r
+\r
+ public Shape createStrokedShape( Shape shape ) {\r
+ return stroke2.createStrokedShape( stroke1.createStrokedShape( shape ) );\r
+ }\r
+ \r
+}\r
public final Resource CloudSymbol;\r
public final Resource Configuration;\r
public final Resource ConfigurationDiagram;\r
- public final Resource Connection;\r
public final Resource ConstantExpression;\r
public final Resource DelayExpression;\r
public final Resource Dependency;\r
+ public final Resource DependencyConnection;\r
public final Resource DiagramToCompositeMapping;\r
public final Resource Experiment;\r
public final Resource Expression;\r
public final Resource Flow;\r
+ public final Resource FlowConnection;\r
public final Resource GameExperiment;\r
public final Resource HasAngle;\r
public final Resource HasEquation;\r
public static final String CloudSymbol = "http://www.simantics.org/Sysdyn-1.0/CloudSymbol";\r
public static final String Configuration = "http://www.simantics.org/Sysdyn-1.0/Configuration";\r
public static final String ConfigurationDiagram = "http://www.simantics.org/Sysdyn-1.0/ConfigurationDiagram";\r
- public static final String Connection = "http://www.simantics.org/Sysdyn-1.0/Connection";\r
public static final String ConstantExpression = "http://www.simantics.org/Sysdyn-1.0/ConstantExpression";\r
public static final String DelayExpression = "http://www.simantics.org/Sysdyn-1.0/DelayExpression";\r
public static final String Dependency = "http://www.simantics.org/Sysdyn-1.0/Dependency";\r
+ public static final String DependencyConnection = "http://www.simantics.org/Sysdyn-1.0/DependencyConnection";\r
public static final String DiagramToCompositeMapping = "http://www.simantics.org/Sysdyn-1.0/DiagramToCompositeMapping";\r
public static final String Experiment = "http://www.simantics.org/Sysdyn-1.0/Experiment";\r
public static final String Expression = "http://www.simantics.org/Sysdyn-1.0/Expression";\r
public static final String Flow = "http://www.simantics.org/Sysdyn-1.0/Flow";\r
+ public static final String FlowConnection = "http://www.simantics.org/Sysdyn-1.0/FlowConnection";\r
public static final String GameExperiment = "http://www.simantics.org/Sysdyn-1.0/GameExperiment";\r
public static final String HasAngle = "http://www.simantics.org/Sysdyn-1.0/HasAngle";\r
public static final String HasEquation = "http://www.simantics.org/Sysdyn-1.0/HasEquation";\r
CloudSymbol = getResourceOrNull(graph, URIs.CloudSymbol);\r
Configuration = getResourceOrNull(graph, URIs.Configuration);\r
ConfigurationDiagram = getResourceOrNull(graph, URIs.ConfigurationDiagram);\r
- Connection = getResourceOrNull(graph, URIs.Connection);\r
ConstantExpression = getResourceOrNull(graph, URIs.ConstantExpression);\r
DelayExpression = getResourceOrNull(graph, URIs.DelayExpression);\r
Dependency = getResourceOrNull(graph, URIs.Dependency);\r
+ DependencyConnection = getResourceOrNull(graph, URIs.DependencyConnection);\r
DiagramToCompositeMapping = getResourceOrNull(graph, URIs.DiagramToCompositeMapping);\r
Experiment = getResourceOrNull(graph, URIs.Experiment);\r
Expression = getResourceOrNull(graph, URIs.Expression);\r
Flow = getResourceOrNull(graph, URIs.Flow);\r
+ FlowConnection = getResourceOrNull(graph, URIs.FlowConnection);\r
GameExperiment = getResourceOrNull(graph, URIs.GameExperiment);\r
HasAngle = getResourceOrNull(graph, URIs.HasAngle);\r
HasEquation = getResourceOrNull(graph, URIs.HasEquation);\r
# Connections and Relations\r
######################################################################\r
\r
-HasAngle <R L0.HasProperty\r
- L0.HasRange L0.Double\r
IsTailOf <R ST.IsConnectedTo\r
L0.HasDomain Variable\r
L0.HasRange Dependency\r
# Diagram connection types\r
######################################################################\r
\r
-Connection <T DIA.Connection\r
+HasAngle <R L0.HasProperty\r
+ L0.HasRange L0.Double\r
+\r
+FlowConnection <T DIA.Connection\r
+ MOD.DiagramConnectionTypeToConnectionType\r
+ Flow \r
+ \r
+DependencyConnection <T DIA.Connection\r
+ [HasAngle card "1"] \r
+ MOD.DiagramConnectionTypeToConnectionType\r
+ Dependency\r
+ \r