import org.simantics.g2d.diagram.participant.DeleteHandler;\r
import org.simantics.g2d.diagram.participant.ElementPainter;\r
import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
-import org.simantics.g2d.element.ElementClassProviders;\r
+import org.simantics.g2d.element.ElementClass;\r
import org.simantics.g2d.element.ElementClasses;\r
import org.simantics.g2d.element.ElementHints;\r
import org.simantics.g2d.element.IElement;\r
import org.simantics.sysdyn.SysdynResource;\r
import org.simantics.sysdyn.ui.editor.participant.CreateVariablesShortcutParticipant;\r
import org.simantics.sysdyn.ui.editor.participant.SysdynComponentCopyAdvisor;\r
+import org.simantics.sysdyn.ui.editor.participant.SysdynElementClassProviders;\r
import org.simantics.sysdyn.ui.editor.participant.SysdynPopulateElementDropParticipant;\r
import org.simantics.sysdyn.ui.elements2.CloudFactory;\r
+import org.simantics.sysdyn.ui.elements2.SysdynElementClasses;\r
import org.simantics.sysdyn.ui.elements2.SysdynElementFactory;\r
import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
import org.simantics.sysdyn.ui.elements2.connections.SysdynConnectionClass;\r
@Override\r
protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
SysdynResource sr = SysdynResource.getInstance(graph);\r
- return ElementClassProviders.mappedProvider(\r
- ElementClasses.CONNECTION, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
+ ElementClass dependencyClass = SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection));\r
+ return SysdynElementClassProviders.mappedProvider(\r
+ ElementClasses.CONNECTION, dependencyClass,\r
ElementClasses.FLAG, CloudFactory.createElementClass(sr.CloudSymbol, SysdynElementFactory.createTerminals(graph, sr.CloudSymbol)),\r
ConnectionClasses.FLOW, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
- ConnectionClasses.DEPENDENCY, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection))\r
+ ConnectionClasses.DEPENDENCY, dependencyClass,\r
+ SysdynElementClasses.VALVE, CloudFactory.createElementClass(sr.ValveSymbol, SysdynElementFactory.createTerminals(graph, sr.ValveSymbol))\r
);\r
\r
\r
import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
import org.simantics.g2d.element.ElementUtils;\r
import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
import org.simantics.structural.stubs.StructuralResource2;\r
import org.simantics.structural2.modelingRules.CPIgnore;\r
import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
@Override\r
public Object perform(ReadGraph g) throws DatabaseException {\r
if(element1 != null && term1 != null && element2 != null && term2 != null) {\r
- SysdynResource sr = SysdynResource.getInstance(g);\r
+ StaticObjectAdapter soa = element1.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+ Resource startElementResource = soa.adapt(Resource.class);\r
+ soa = element2.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+ Resource endElementResource = soa.adapt(Resource.class);\r
+ \r
DiagramResource dr = DiagramResource.getInstance(g);\r
StructuralResource2 str2 = StructuralResource2.getInstance(g);\r
Resource terminal2 = ((ResourceTerminal) term2).getResource();\r
+ SysdynResource sr = SysdynResource.getInstance(g);\r
+\r
Resource connectionVariable = g.getPossibleObject(terminal2, dr.HasConnectionVariable);\r
if(!g.hasStatement(connectionVariable, str2.Binds, sr.IsHeadOfTerminal)) {\r
return null;\r
}\r
-\r
- // Only one incoming dependency allowed in inputs. That dependency must be from a module\r
- Object obj1 = ElementUtils.getObject(element1);\r
- Object obj2 = ElementUtils.getObject(element2);\r
- if(obj1 instanceof Resource && obj2 instanceof Resource) {\r
- Resource startElementResource = (Resource)obj1;\r
- Resource endElementResource = (Resource)obj2;\r
- if(g.isInstanceOf(endElementResource, sr.InputSymbol)) {\r
- if(g.isInheritedFrom(startElementResource, sr.ModuleSymbol)) return null;\r
- if(g.getObjects(endElementResource, sr.IsHeadOfTerminal).size() > 0) return null;\r
- }\r
+ \r
+ if(g.isInstanceOf(endElementResource, sr.InputSymbol)) {\r
+ if(g.isInheritedFrom(startElementResource, sr.ModuleSymbol)) return null;\r
+ if(g.getObjects(endElementResource, sr.IsHeadOfTerminal).size() > 0) return null;\r
}\r
+ \r
}\r
\r
ArrayList<IConnectionPoint> cps = new ArrayList<IConnectionPoint>();\r
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2010 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.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.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.request.Queries;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.diagram.query.DiagramRequests;\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.SceneGraphNodeKey;\r
-import org.simantics.g2d.element.handler.Parent;\r
-import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
-import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
-import org.simantics.g2d.elementclass.BranchPoint;\r
-import org.simantics.g2d.elementclass.FlagClass;\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.SysdynResource;\r
-import org.simantics.sysdyn.ui.elements2.ValveFactory;\r
-import org.simantics.ui.SimanticsUI;\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
- ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
- ElementUtils.getTerminals(firstElement, terminals, false);\r
- firstTerminal = terminals.get(1);\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
-\r
-\r
- private void createValveIfNecessary(Point2D point) {\r
- if (!isCurrentConnectionFlow()) return;\r
- \r
- if(startElement != null && startElement.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
- return;\r
- } else if(endElement != null && endElement.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
- return;\r
- }\r
-\r
- ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
-\r
- if(endElement != null) {\r
- // Disconnect from end element\r
- topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
- } else {\r
- IElement lastBp = controlPoints.pollLast();\r
- ElementUtils.getTerminals(lastBp, terminals, true);\r
- topology.disconnect(edges.peekLast(), EdgeEnd.End, lastBp, terminals.get(0));\r
- connectionHandler.removeBranchPoint(connection, lastBp);\r
- }\r
-\r
-\r
- // Set the position in the middle of the route\r
- double startX = startPos.getX();\r
- double startY = startPos.getY();\r
- double x = point.getX();\r
- double y = point.getY();\r
- Point2D pos = new Point2D.Double((startX + x) / 2, (startY + y) / 2);\r
- \r
- // Create the valve\r
- IElement end = createValve(pos);\r
-\r
- ElementUtils.getTerminals(end, terminals, true);\r
- topology.connect(edges.peekLast(), EdgeEnd.End, end, terminals.get(0));\r
- DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-\r
-\r
- IElement firstElement = end;\r
- Terminal firstTerminal = terminals.get(1);\r
-\r
-\r
- IElement possibleConnection = getConnectionFromPart(firstElement);\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
-\r
-\r
-\r
-\r
- IElement edge = connectionHandler.newEdge(connection);\r
- edges.add(edge);\r
-\r
- topology.connect(edge, EdgeEnd.Begin, firstElement, firstTerminal);\r
- \r
- if (endElement != null) {\r
- IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
- Object canConnect = canConnect(advisor, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
- if(canConnect != null) {\r
- connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
- }\r
- topology.connect(edge, EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
- } else {\r
- IElement secondElement = connectionHandler.newBranchPoint(connection);\r
- controlPoints.add(secondElement);\r
- ElementUtils.setPos(secondElement, pos);\r
- Terminal secondTerminal = ElementUtils.getSingleTerminal(secondElement);\r
- IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
- Object canConnect = canConnect(advisor, null, null);\r
- if(canConnect != null) {\r
- connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
- }\r
- \r
- topology.connect(edge, EdgeEnd.End, secondElement, secondTerminal);\r
- }\r
- DiagramUtils.validateAndFix(ghostDiagram, getContext());\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
- final 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
- createValveIfNecessary(mouseCanvasPos);\r
- commitDiagram();\r
- update();\r
- remove(); // Remove ConnectTool participant\r
- return true;\r
- } else {\r
- if (isCurrentConnectionFlow() && startElement != null && startTerminal != null) {\r
- \r
- IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
- Object canConnect = canConnect(advisor, null, null);\r
- if (canConnect != null)\r
- connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
- \r
- createValveIfNecessary(mouseCanvasPos);\r
-\r
- // Finish connection in thin air only if the\r
- // connection was started from a valid terminal.\r
- if (createFlags) {\r
- // Replace the last branch point with a flag.\r
- IElement lastBp = controlPoints.pollLast();\r
- topology.disconnect(edges.peekLast(), EdgeEnd.End, lastBp, ElementUtils.getSingleTerminal(lastBp));\r
- connectionHandler.removeBranchPoint(connection, lastBp);\r
-\r
- IElement end = createFlag(mouseCanvasPos, EdgeEnd.End);\r
- ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
- ElementUtils.getTerminals(end, terminals, false);\r
- Terminal endTerminal = terminals.get(0);\r
- topology.connect(edges.peekLast(), EdgeEnd.End, end, endTerminal);\r
- }\r
-\r
- DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
- commitDiagram();\r
- update();\r
- remove(); // Remove ConnectTool participant\r
- return true;\r
- } \r
- }\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
-\r
-\r
-\r
- private boolean isCurrentConnectionFlow() {\r
- // Could this check be done better?\r
- Boolean isFlow = false;\r
- try {\r
- isFlow = SimanticsUI.getSession().syncRequest(new Read<Boolean>() {\r
-\r
- @Override\r
- public Boolean perform(ReadGraph graph)\r
- throws DatabaseException {\r
- SysdynResource sr = SysdynResource.getInstance(graph);\r
- StaticObjectAdapter soa = connectionClass.getSingleItem(StaticObjectAdapter.class);\r
- Resource conntype = soa.adapt(Resource.class);\r
- return conntype.equals(sr.FlowConnection);\r
- }\r
-\r
- });\r
- } catch (DatabaseException e1) {\r
- e1.printStackTrace();\r
- }\r
- return isFlow;\r
- }\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
- IElement createValve(Point2D pos) {\r
- DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-\r
- ElementClass ec = null;\r
- try {\r
- Resource r = SimanticsUI\r
- .getSession()\r
- .syncRequest(\r
- Queries\r
- .resource(SysdynResource.URIs.ValveSymbol));\r
- ec = SimanticsUI.getSession().syncRequest(\r
- DiagramRequests.getElementClass(r, diagram));\r
-\r
- } catch (DatabaseException e1) {\r
- e1.printStackTrace();\r
- }\r
-\r
- if(ec == null) return null;\r
-\r
- IElement e = mutator.newElement(ec);\r
-\r
- ElementUtils.setPos(e, pos);\r
-\r
- ghostDiagram.addElement(e);\r
-\r
- return e;\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(final IConnectionAdvisor advisor, final IElement endElement, final Terminal endTerminal) {\r
- if(startElement.equals(endElement)) return null;\r
-\r
- if(endElement == null && endTerminal == null)\r
- return advisor.canBeConnected(null, startElement, startTerminal, endElement, endTerminal);\r
-\r
- try {\r
- return SimanticsUI.getSession().syncRequest(new Read<Object>() {\r
-\r
- @Override\r
- public Object perform(ReadGraph g) throws DatabaseException {\r
-\r
- // Checking if connection type can be connected to the intended endElement\r
- SysdynResource sr = SysdynResource.getInstance(g);\r
- if(connection != null) {\r
- StaticObjectAdapter soa = connectionClass.getSingleItem(StaticObjectAdapter.class);\r
- Resource conntype = soa.adapt(Resource.class);\r
- soa = endElement.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
- Resource end = soa.adapt(Resource.class);\r
- if(conntype.equals(sr.DependencyConnection)) {\r
- if(end.equals(sr.CloudSymbol)) return null;\r
- soa = startElement.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
- Resource start = soa.adapt(Resource.class);\r
- if(g.isInheritedFrom(start, sr.ModuleSymbol) && !end.equals(sr.InputSymbol)) return null;\r
- } else if (conntype.equals(sr.FlowConnection)) {\r
- if(!(end.equals(sr.StockSymbol) || end.equals(sr.ValveSymbol) || end.equals(sr.CloudSymbol))) return null;\r
- } else {\r
- return null;\r
- }\r
- }\r
-\r
-\r
- if (advisor == null)\r
- return Boolean.TRUE; \r
- return advisor.canBeConnected(g, startElement, startTerminal, endElement, endTerminal);\r
- }\r
-\r
- });\r
- } catch(DatabaseException e) {\r
- e.printStackTrace();\r
- return null;\r
- }\r
-\r
- }\r
-\r
-\r
-}\r
import java.awt.geom.Rectangle2D;\r
import java.util.List;\r
\r
+import org.simantics.diagram.participant.ConnectTool2;\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.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.ElementClasses;\r
import org.simantics.g2d.element.IElement;\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;\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.utils.GeometryUtils;\r
+import org.simantics.sysdyn.ui.editor.participant.SysdynElementClassProviders.ISysdynElementClassProvider;\r
+import org.simantics.sysdyn.ui.editor.routing.DependencyRouter;\r
import org.simantics.sysdyn.ui.elements2.AuxiliaryFactory;\r
import org.simantics.sysdyn.ui.elements2.CloudFactory;\r
import org.simantics.sysdyn.ui.elements2.InputFactory;\r
@Dependency PickContext pickContext;\r
@Dependency MouseUtil mice;\r
@Reference TerminalPainter terminalPainter;\r
-\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
if((me.stateMask & MouseEvent.ALT_MASK) == 0) return false;\r
\r
if(elementClassProvider != null) {\r
- ConnectTool bsi = null;\r
+ ConnectTool2 bsi = null;\r
if (ti != null) {\r
\r
IElement terminalElement = ti.e;\r
\r
- ElementClass connectionClass = null;\r
+// ElementClass connectionClass = null;\r
if( me.button == MouseEvent.LEFT_BUTTON) {\r
if(terminalElement.getElementClass().getId().equals(CloudFactory.class.getSimpleName())) return false;\r
- diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
- connectionClass = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+// diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new DependencyRouter());\r
+// connectionClass = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+ ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
+ secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.DEPENDENCY));\r
\r
} else if (me.button == MouseEvent.RIGHT_BUTTON) {\r
String id = terminalElement.getElementClass().getId();\r
if(id.equals(AuxiliaryFactory.class.getSimpleName())\r
|| id.equals(InputFactory.class.getSimpleName())\r
|| id.equals(ModuleFactory.class.getSimpleName())) return false;\r
- diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
- connectionClass = elementClassProvider.get(ConnectionClasses.FLOW);\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, false));\r
+// connectionClass = elementClassProvider.get(ConnectionClasses.FLOW);\r
+ ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
+ secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.FLOW));\r
+ \r
}\r
\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
+// bsi = new ConnectTool(diagram, connectionClass, ti.e, ti.t, me.mouseId, curCanvasPos);\r
+ bsi = new SysdynConnectTool(ti, me.mouseId, curCanvasPos);\r
}\r
} \r
else if (me.button == MouseEvent.RIGHT_BUTTON) {\r
*/\r
// Start connection out of thin air, without a terminal.\r
diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
- bsi = new ConnectTool(diagram, elementClassProvider.get(ConnectionClasses.FLOW), null, null, me.mouseId, curCanvasPos);\r
+// bsi = new ConnectTool(diagram, elementClassProvider.get(ConnectionClasses.FLOW), null, null, me.mouseId, curCanvasPos);\r
+ ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
+ secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.FLOW));\r
+ bsi = new SysdynConnectTool(null, me.mouseId, curCanvasPos); // FIXME\r
}\r
\r
if (bsi != null) {\r
--- /dev/null
+package org.simantics.sysdyn.ui.editor.participant;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.Point2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Deque;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.UndoContext;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.UndoWriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.diagram.participant.ConnectTool2;\r
+import org.simantics.diagram.participant.ConnectionBuilder;\r
+import org.simantics.diagram.participant.ControlPoint;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
+import org.simantics.g2d.connection.IConnectionAdvisor;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\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.ElementClasses;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+import org.simantics.g2d.element.impl.Element;\r
+import org.simantics.g2d.elementclass.BranchPoint;\r
+import org.simantics.g2d.elementclass.BranchPointClass;\r
+import org.simantics.g2d.elementclass.FlagClass;\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.routing.ConnectionDirectionUtil;\r
+import org.simantics.g2d.routing.Constants;\r
+import org.simantics.g2d.routing.IConnection;\r
+import org.simantics.g2d.routing.IRouter2;\r
+import org.simantics.g2d.routing.TrivialRouter2;\r
+import org.simantics.g2d.snap.ISnapAdvisor;\r
+import org.simantics.g2d.utils.GeometryUtils;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.scenegraph.g2d.nodes.ShapeNode;\r
+import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+public class SysdynConnectTool extends ConnectTool2 {\r
+ \r
+ public SysdynConnectTool(TerminalInfo startTerminal, int mouseId,\r
+ Point2D startCanvasPos) {\r
+ super(startTerminal, mouseId, startCanvasPos);\r
+ }\r
+\r
+\r
+ @SGInit\r
+ public void initSG(G2DParentNode parent) {\r
+ ghostNode = parent.addNode(G2DParentNode.class);\r
+ ghostNode.setZIndex(PAINT_PRIORITY);\r
+\r
+ ShapeNode pathNode = ghostNode.getOrCreateNode("path", ShapeNode.class);\r
+ pathNode.setColor(Color.BLACK);\r
+ pathNode.setStroke(new BasicStroke(1f));\r
+ pathNode.setScaleStroke(true);\r
+ pathNode.setZIndex(0);\r
+\r
+ G2DParentNode points = ghostNode.getOrCreateNode("points", G2DParentNode.class);\r
+ points.setZIndex(1);\r
+\r
+ updateSG();\r
+ }\r
+\r
+ \r
+ protected TerminalInfo createFlag(EdgeEnd connectionEnd) {\r
+ ElementClass flagClass = elementClassProvider.get(ElementClasses.FLAG);\r
+ IElement e = Element.spawnNew(flagClass);\r
+\r
+ e.setHint(FlagClass.KEY_FLAG_TYPE, endToFlagType(connectionEnd));\r
+ e.setHint(FlagClass.KEY_FLAG_MODE, FlagClass.Mode.Internal);\r
+\r
+ TerminalInfo ti = new TerminalInfo();\r
+ ti.e = e;\r
+ \r
+ // start: this part changed to support overlapping terminals\r
+ ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
+ ElementUtils.getTerminals(e, terminals, false);\r
+ ti.t = terminals.get(0);\r
+ // end\r
+ \r
+ ti.posElem = TerminalUtil.getTerminalPosOnElement(e, ti.t);\r
+ ti.posDia = TerminalUtil.getTerminalPosOnDiagram(e, ti.t);\r
+\r
+ return ti;\r
+ }\r
+ \r
+ static class Segment {\r
+ public final ControlPoint begin;\r
+ public final ControlPoint end;\r
+ public Path2D path;\r
+\r
+ public Segment(ControlPoint begin, ControlPoint end) {\r
+ this.begin = begin;\r
+ this.end = end;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "Segment[begin=" + begin + ", end=" + end + ", path=" + path + "]";\r
+ }\r
+ }\r
+ \r
+ private List<Segment> toSegments(Deque<ControlPoint> points) {\r
+ if (points.isEmpty())\r
+ return Collections.emptyList();\r
+\r
+ List<Segment> segments = new ArrayList<Segment>();\r
+\r
+ Iterator<ControlPoint> it = points.iterator();\r
+ ControlPoint prev = it.next();\r
+ while (it.hasNext()) {\r
+ ControlPoint next = it.next();\r
+ segments.add(new Segment(prev, next));\r
+ prev = next;\r
+ }\r
+\r
+ return segments;\r
+ }\r
+ \r
+ protected void updateSG() {\r
+ if (controlPoints.isEmpty())\r
+ return;\r
+\r
+ // Route connection segments separately\r
+ IRouter2 router = ElementUtils.getHintOrDefault(diagram, DiagramHints.ROUTE_ALGORITHM, TrivialRouter2.INSTANCE);\r
+ final List<Segment> segments = toSegments(controlPoints);\r
+ //System.out.println("controlpoints: " + controlPoints);\r
+ //System.out.println("segments: " + segments);\r
+ router.route(new IConnection() {\r
+ @Override\r
+ public Collection<? extends Object> getSegments() {\r
+ return segments;\r
+ }\r
+\r
+ @Override\r
+ public Connector getBegin(Object seg) {\r
+ return getConnector(((Segment) seg).begin);\r
+ }\r
+\r
+ @Override\r
+ public Connector getEnd(Object seg) {\r
+ return getConnector(((Segment) seg).end);\r
+ }\r
+\r
+ private Connector getConnector(ControlPoint cp) {\r
+ Connector c = new Connector();\r
+ c.x = cp.getPosition().getX();\r
+ c.y = cp.getPosition().getY();\r
+\r
+ TerminalInfo ti = cp.getAttachedTerminal();\r
+ if (ti != null && (ti == startFlag || ti != endFlag)) {\r
+ //System.out.println("CP1: " + cp);\r
+ c.parentObstacle = DiagramUtils.getObstacleShape(ti.e);\r
+ ConnectionDirectionUtil.determineAllowedDirections(c);\r
+ } else {\r
+ //System.out.println("CP2: " + cp);\r
+ c.parentObstacle = GeometryUtils.transformRectangle(AffineTransform.getTranslateInstance(c.x, c.y),\r
+ BranchPointClass.DEFAULT_IMAGE2.getBounds());\r
+ c.allowedDirections = toAllowedDirections(cp.getDirection());\r
+ }\r
+\r
+ return c;\r
+ }\r
+\r
+ @Override\r
+ public void setPath(Object seg, Path2D path) {\r
+ ((Segment) seg).path = (Path2D) path.clone();\r
+ }\r
+\r
+ private int toAllowedDirections(BranchPoint.Direction direction) {\r
+ switch (direction) {\r
+ case Any:\r
+ return 0xf;\r
+ case Horizontal:\r
+ return Constants.EAST_FLAG | Constants.WEST_FLAG;\r
+ case Vertical:\r
+ return Constants.NORTH_FLAG | Constants.SOUTH_FLAG;\r
+ default:\r
+ throw new IllegalArgumentException("unrecognized direction: " + direction);\r
+ }\r
+ }\r
+ });\r
+\r
+ // Combine the routed paths\r
+ Path2D path = new Path2D.Double();\r
+ for (Segment seg : segments) {\r
+ //System.out.println("SEG: " + seg);\r
+ if (seg.path != null)\r
+ path.append(seg.path.getPathIterator(null), true);\r
+ }\r
+ \r
+ // Create scene graph to visualize the connection.\r
+ ShapeNode pathNode = ghostNode.getOrCreateNode("path", ShapeNode.class);\r
+ pathNode.setShape(path);\r
+ \r
+ /*\r
+ * Removed Points\r
+ */\r
+ \r
+ setDirty();\r
+ }\r
+ \r
+ \r
+ @Override\r
+ protected Object canConnect(final IConnectionAdvisor advisor, final IElement endElement, final Terminal endTerminal) {\r
+ final IElement se = startTerminal != null ? startTerminal.e : startFlag.e;\r
+ final Terminal st = startTerminal != null ? startTerminal.t : null;\r
+\r
+ if(se.equals(endElement)) return null;\r
+\r
+ if(endElement == null && endTerminal == null)\r
+ return advisor.canBeConnected(null, se, st, endElement, endTerminal);\r
+\r
+ try {\r
+ return SimanticsUI.getSession().syncRequest(new Read<Object>() {\r
+\r
+ @Override\r
+ public Object perform(ReadGraph g) throws DatabaseException {\r
+\r
+ // Checking if connection type can be connected to the intended endElement\r
+ SysdynResource sr = SysdynResource.getInstance(g);\r
+ StaticObjectAdapter soa = endElement.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+ Resource end = soa.adapt(Resource.class);\r
+ ElementClass dependency = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+ ElementClass flow = elementClassProvider.get(ConnectionClasses.FLOW);\r
+ ElementClass currentConnection = elementClassProvider.get(ElementClasses.CONNECTION);\r
+ if(currentConnection.equals(dependency)) {\r
+ if(end.equals(sr.CloudSymbol)) return null;\r
+ soa = se.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+ Resource start = soa.adapt(Resource.class);\r
+ if(g.isInheritedFrom(start, sr.ModuleSymbol) && !end.equals(sr.InputSymbol)) return null;\r
+ if(end.equals(sr.StockSymbol)) return null;\r
+ } else if (currentConnection.equals(flow)) {\r
+ if(!(end.equals(sr.StockSymbol) || end.equals(sr.ValveSymbol) || end.equals(sr.CloudSymbol))) return null;\r
+ } else {\r
+ return null;\r
+ }\r
+\r
+\r
+ if (advisor == null)\r
+ return Boolean.TRUE; \r
+ return advisor.canBeConnected(g, se, st, endElement, endTerminal);\r
+ }\r
+\r
+ });\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ }\r
+\r
+ }\r
+ \r
+ protected boolean processMouseMove(MouseMovedEvent me) {\r
+ mouseHasMoved = true;\r
+\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
+ // Record last snapped canvas position of mouse.\r
+ this.lastMouseCanvasPos.setLocation(mouseCanvasPos);\r
+\r
+ if (isEndingInFlag()) {\r
+ endFlagNode.setTransform(AffineTransform.getTranslateInstance(mouseCanvasPos.getX(), mouseCanvasPos.getY()));\r
+ }\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
+ ti = info;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if (ti != null && !isStartTerminal(ti.e, ti.t)) {\r
+ Object canConnect = canConnect(ti.e, ti.t);\r
+ if (canConnect != null) {\r
+ connectionJudgment = (ConnectionJudgement) canConnect;\r
+\r
+ if (!isEndingInFlag() || !TerminalUtil.isSameTerminal(ti, endTerminal)) {\r
+ controlPoints.getLast()\r
+ .setPosition(ti.posDia)\r
+ .setAttachedToTerminal(ti);\r
+\r
+ endTerminal = ti;\r
+ System.out.println("ENDTERMINAL MOUSEMOVESTA: " + ti + ", " + ti.t);\r
+ }\r
+\r
+ // Make sure that we are ending with a flag if ALT is pressed\r
+ // and no end terminal is defined.\r
+ endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me));\r
+\r
+ updateSG();\r
+ return false;\r
+ }\r
+ }\r
+\r
+ connectionJudgment = null;\r
+ if (isEndTerminalDefined()) {\r
+ // CASE: Mouse was previously on top of a valid terminal to end\r
+ // the connection. Now the mouse has been moved where there is\r
+ // no longer a terminal to connect to.\r
+ //\r
+ // => Disconnect the last edge segment from the previous\r
+ // terminal, mark endElement/endTerminal non-existent\r
+ // and connect the disconnected edge to a new branch point.\r
+\r
+ controlPoints.getLast()\r
+ .setPosition(mouseCanvasPos)\r
+ .setDirection(calculateCurrentBranchPointDirection())\r
+ .setAttachedToTerminal(null);\r
+\r
+ endTerminal = null;\r
+ } else {\r
+ // CASE: Mouse was not previously on top of a valid ending\r
+ // element terminal.\r
+ //\r
+ // => Move and re-orient last branch point.\r
+\r
+ controlPoints.getLast()\r
+ .setPosition(mouseCanvasPos)\r
+ .setDirection(calculateCurrentBranchPointDirection());\r
+ }\r
+\r
+ // Make sure that we are ending with a flag if ALT is pressed and no end\r
+ // terminal is defined.\r
+ endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me));\r
+\r
+ updateSG();\r
+\r
+ return false;\r
+ }\r
+ \r
+ Point2D mousePosition;\r
+ \r
+ protected boolean processMouseButtonPress(MouseButtonPressedEvent e) {\r
+ MouseButtonEvent me = e;\r
+ mousePosition = me.controlPosition;\r
+ return super.processMouseButtonPress(e);\r
+ }\r
+\r
+ @Override\r
+ protected void createConnection() {\r
+ \r
+ final UndoContext uctx = diagram.getHint(DiagramModelHints.KEY_UNDO_CONTEXT);\r
+ final ConnectionJudgement judgment = this.connectionJudgment;\r
+ // ConnectionBuilder changed to SysdynconnectionBuilder to support overlapping terminals and valve creation\r
+ final ConnectionBuilder builder = new SysdynConnectionBuilder(this.diagram);\r
+ final Deque<ControlPoint> controlPoints = this.controlPoints;\r
+ final TerminalInfo startTerminal = this.startTerminal;\r
+ final TerminalInfo endTerminal = this.endTerminal;\r
+\r
+ SimanticsUI.getSession().asyncRequest(new UndoWriteRequest(uctx, true) {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ builder.create(graph, judgment, controlPoints, startTerminal, endTerminal);\r
+ }\r
+ }, new Callback<DatabaseException>() {\r
+ @Override\r
+ public void run(DatabaseException parameter) {\r
+ if (parameter != null)\r
+ ExceptionUtils.logAndShowError(parameter);\r
+ }\r
+ });\r
+ } \r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.editor.participant;\r
+\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Point2D;\r
+import java.util.ArrayList;\r
+import java.util.Deque;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.content.ConnectionUtil;\r
+import org.simantics.diagram.participant.ConnectionBuilder;\r
+import org.simantics.diagram.participant.ControlPoint;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\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.ElementClasses;\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.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.impl.Element;\r
+import org.simantics.g2d.elementclass.FlagClass;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
+import org.simantics.structural2.modelingRules.IModelingRules;\r
+import org.simantics.sysdyn.ui.elements2.SysdynElementClasses;\r
+import org.simantics.sysdyn.ui.elements2.ValveFactory;\r
+import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class SysdynConnectionBuilder extends ConnectionBuilder{\r
+\r
+ public SysdynConnectionBuilder(IDiagram diagram) {\r
+ super(diagram);\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param judgment\r
+ * @param controlPoints\r
+ * @param startTerminal\r
+ * @param endTerminal\r
+ * @throws DatabaseException\r
+ */\r
+ public void create(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
+ TerminalInfo startTerminal, TerminalInfo endTerminal) throws DatabaseException {\r
+ // If needs a valve, we will create two separate connections\r
+ if(needsValve(startTerminal, endTerminal)) {\r
+ createValveAndConnections(graph, judgment, controlPoints, startTerminal, endTerminal);\r
+ } \r
+ // If no need for valve, just call createConnection with false on createValve parameter\r
+ else {\r
+ createConnection(graph, judgment, controlPoints, startTerminal, endTerminal, false);\r
+ }\r
+ }\r
+ /**\r
+ * @param graph\r
+ * @param judgment\r
+ * @param controlPoints\r
+ * @param startTerminal\r
+ * @param endTerminal\r
+ * @throws DatabaseException\r
+ */\r
+ public TerminalInfo createConnection(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
+ TerminalInfo startTerminal, TerminalInfo endTerminal, boolean createValve) throws DatabaseException {\r
+ TerminalInfo newValve = null;\r
+\r
+ this.cu = new ConnectionUtil(graph);\r
+\r
+ // 1. Get diagram connection to construct.\r
+ Resource connection = getOrCreateConnection(graph, startTerminal, endTerminal);\r
+\r
+ // 2. Add branch points\r
+ List<Pair<ControlPoint, Resource>> bps = createBranchPoints(graph, connection, controlPoints);\r
+ \r
+ // 3. Create edges between branch points.\r
+ Resource firstBranchPoint = null;\r
+ Resource lastBranchPoint = null;\r
+ if (!bps.isEmpty()) {\r
+ Iterator<Pair<ControlPoint, Resource>> it = bps.iterator();\r
+ Pair<ControlPoint, Resource> prev = it.next();\r
+ firstBranchPoint = prev.second;\r
+ while (it.hasNext()) {\r
+ Pair<ControlPoint, Resource> next = it.next();\r
+ cu.connect(prev.second, next.second);\r
+ prev = next;\r
+ }\r
+ lastBranchPoint = prev.second;\r
+ }\r
+\r
+ // 4. Connect start/end terminals if those exist.\r
+ // If first/lastBranchPoint != null, connect to those.\r
+ // Otherwise connect the start/end terminals together.\r
+ Resource startConnector = null;\r
+ Resource endConnector = null;\r
+ IElement startFlag = null;\r
+ IElement endFlag = null;\r
+\r
+ if (startTerminal != null) {\r
+ startConnector = createConnectorForNode(graph, connection, startTerminal, EdgeEnd.Begin, judgment);\r
+ } else if (createFlags) {\r
+ startFlag = createFlag(graph, connection, EdgeEnd.Begin, controlPoints.getFirst(), FlagClass.Type.In);\r
+ ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
+ ElementUtils.getTerminals(startFlag, terminals, false);\r
+ Terminal st = terminals.get(1);\r
+ startConnector = createConnectorForNode(graph, connection, (Resource) ElementUtils.getObject(startFlag),\r
+ st, EdgeEnd.Begin, judgment);\r
+ }\r
+\r
+ if (endTerminal != null) {\r
+ endConnector = createConnectorForNode(graph, connection, endTerminal, EdgeEnd.End, judgment);\r
+ } else if (createFlags) {\r
+ if(createValve)\r
+ endFlag = createValveElement(graph, connection, EdgeEnd.End, controlPoints.getLast());\r
+ else\r
+ endFlag = createFlag(graph, connection, EdgeEnd.End, controlPoints.getLast(), FlagClass.Type.Out);\r
+ ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
+ ElementUtils.getTerminals(endFlag, terminals, false);\r
+ Terminal et = terminals.get(0);\r
+ endConnector = createConnectorForNode(graph, connection, (Resource) ElementUtils.getObject(endFlag),\r
+ et, EdgeEnd.End, judgment);\r
+ \r
+ if(createValve) {\r
+ newValve = new TerminalInfo();\r
+ newValve.e = endFlag;\r
+ newValve.t = terminals.get(1);\r
+ newValve.posElem = TerminalUtil.getTerminalPosOnElement(endFlag, newValve.t);\r
+ newValve.posDia = TerminalUtil.getTerminalPosOnDiagram(endFlag, newValve.t);\r
+ }\r
+ }\r
+\r
+ if (firstBranchPoint == null || lastBranchPoint == null) {\r
+ cu.connect(startConnector, endConnector);\r
+ } else {\r
+ cu.connect(startConnector, firstBranchPoint);\r
+ cu.connect(lastBranchPoint, endConnector);\r
+ }\r
+\r
+ // 5. Finally, set connection type according to modelling rules\r
+ IModelingRules modelingRules = diagram.getHint(DiagramModelHints.KEY_MODELING_RULES);\r
+ if (judgment.connectionType != null && modelingRules != null) {\r
+ modelingRules.setConnectionType(graph, connection, judgment.connectionType);\r
+ }\r
+\r
+ this.cu = null;\r
+ return newValve;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * @param graph\r
+ * @param connection\r
+ * @param end\r
+ * @param cp\r
+ * @param type\r
+ * @return an element describing the new created flag resource\r
+ * @throws DatabaseException\r
+ */\r
+ public IElement createValveElement(WriteGraph graph, Resource connection, EdgeEnd end, ControlPoint cp) throws DatabaseException {\r
+ ElementClass valveClass = elementClassProvider.get(SysdynElementClasses.VALVE);\r
+ IElement valveElement = Element.spawnNew(valveClass);\r
+ Resource valveClassResource = ElementUtils.checkedAdapt(valveClass, Resource.class);\r
+\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ G2DResource G2D = G2DResource.getInstance(graph);\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+\r
+ Resource valve = graph.newResource();\r
+ graph.claim(valve, L0.InstanceOf, null, valveClassResource);\r
+ valveElement.setHint(ElementHints.KEY_OBJECT, valve);\r
+\r
+ OrderedSetUtils.add(graph, diagramResource, valve);\r
+\r
+ AffineTransform at = AffineTransform.getTranslateInstance(cp.getPosition().getX(), cp.getPosition().getY());\r
+ valveElement.setHint(ElementHints.KEY_TRANSFORM, at);\r
+ double[] matrix = new double[6];\r
+ at.getMatrix(matrix);\r
+ graph.claimLiteral(valve, DIA.HasTransform, G2D.Transform, matrix);\r
+\r
+ // Put the element on all the currently active layers if possible.\r
+ if (layerManager != null) {\r
+ layerManager.removeFromAllLayers(graph, valve);\r
+ layerManager.putElementOnVisibleLayers(diagram, graph, valve);\r
+ }\r
+\r
+ return valveElement;\r
+ }\r
+ \r
+ private boolean needsValve(TerminalInfo startTerminal, TerminalInfo endTerminal) {\r
+ if (!elementClassProvider.get(ElementClasses.CONNECTION)\r
+ .equals(elementClassProvider.get(ConnectionClasses.FLOW))) \r
+ return false;\r
+ if(startTerminal != null && startTerminal.e != null && startTerminal.e.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
+ return false;\r
+ } else if(endTerminal != null && endTerminal.e != null && endTerminal.e.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ private void createValveAndConnections(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
+ TerminalInfo startTerminal, TerminalInfo endTerminal) throws DatabaseException {\r
+ \r
+ ControlPoint cpfirst = controlPoints.getFirst();\r
+ ControlPoint cplast = controlPoints.getLast();\r
+\r
+ // Set the position in the middle of the route\r
+ double startX = cpfirst.getPosition().getX();\r
+ double startY = cpfirst.getPosition().getY();\r
+ double x = cplast.getPosition().getX();\r
+ double y = cplast.getPosition().getY();\r
+ Point2D pos = new Point2D.Double(startX - (startX - x) / 2, startY - (startY - y) / 2);\r
+ \r
+ // Replace the last control point with the control point in the middle\r
+ controlPoints.getLast().setPosition(pos);\r
+\r
+ // Create a connection to a new valve and get the new valve\r
+ TerminalInfo newValve = createConnection(graph, judgment, controlPoints, startTerminal, null, true);\r
+ \r
+ // Replace the last control point with the original control point\r
+ controlPoints.getLast().setPosition(x, y);\r
+ \r
+ // Create a connection starting from the new valve\r
+ createConnection(graph, judgment, controlPoints, newValve, endTerminal, false);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.editor.participant;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementClassProviders;\r
+import org.simantics.g2d.element.IElementClassProvider;\r
+\r
+public class SysdynElementClassProviders extends ElementClassProviders {\r
+ \r
+ /**\r
+ * Create an element class provider that based on the specified map. The\r
+ * provider will directly access the map with the received keys. The\r
+ * argument map will be copied.\r
+ * \r
+ * @param map the map to use for element class provision\r
+ * @return <code>null</code> if there is no provider for the specified key\r
+ */\r
+ public static IElementClassProvider mappedProvider(Map<Object, ElementClass> map) {\r
+ // Copy the map as a safety measure\r
+ final Map<Object, ElementClass> copy = new HashMap<Object, ElementClass>(map);\r
+ return new ISysdynElementClassProvider() {\r
+ @Override\r
+ public ElementClass get(Object key) {\r
+ return copy.get(key);\r
+ }\r
+\r
+ @Override\r
+ public void put(Object key, ElementClass value) {\r
+ copy.put(key, value);\r
+ }\r
+\r
+ };\r
+ }\r
+ \r
+ /**\r
+ * Does the same as {@link #mappedProvider(Map)}, the map is simply provided\r
+ * differently. The specified array must contain\r
+ * <code>[key, ElementClass, key, ElementClass, ...]</code>.\r
+ * \r
+ * @param map the map to use for element class provision\r
+ * @return <code>null</code> if there is no provider for the specified key\r
+ */\r
+ public static IElementClassProvider mappedProvider(Object... keyClassPairs) {\r
+ if (keyClassPairs.length % 2 != 0)\r
+ throw new IllegalArgumentException();\r
+ Map<Object, ElementClass> map = new HashMap<Object, ElementClass>();\r
+ int n = keyClassPairs.length / 2;\r
+ for (int i = 0; i < n; ++i) {\r
+ Object key = keyClassPairs[i * 2];\r
+ Object elementClass = keyClassPairs[i*2+1];\r
+ if (!(elementClass instanceof ElementClass))\r
+ throw new IllegalArgumentException("not an ElementClass instance: " + elementClass);\r
+ map.put(key, (ElementClass) elementClass);\r
+ }\r
+ return mappedProvider(map);\r
+ }\r
+\r
+\r
+ public interface ISysdynElementClassProvider extends IElementClassProvider {\r
+ \r
+ /**\r
+ * Update a value in an IElementClassProvider\r
+ */\r
+ void put(Object key, ElementClass value);\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.editor.routing;\r
+\r
+import java.awt.geom.Arc2D;\r
+import java.awt.geom.Path2D;\r
+\r
+import org.simantics.g2d.routing.IConnection;\r
+import org.simantics.g2d.routing.IConnection.Connector;\r
+import org.simantics.g2d.routing.IRouter2;\r
+import org.simantics.sysdyn.ui.elements2.connections.Dependencies;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class DependencyRouter implements IRouter2 {\r
+\r
+ @Override\r
+ public void route(IConnection connection) {\r
+ if(connection.getSegments().isEmpty())\r
+ return;\r
+ Object seg = connection.getSegments().iterator().next();\r
+ Connector begin = connection.getBegin(seg);\r
+ Connector end = connection.getEnd(seg);\r
+ \r
+ Pair<Arc2D, Path2D> shapes = new Pair<Arc2D, Path2D>(new Arc2D.Double(), new Path2D.Double());\r
+ Dependencies.createArrowShape(shapes,\r
+ begin.parentObstacle,\r
+ end.parentObstacle,\r
+ 0.1);\r
+ \r
+ Path2D path = new Path2D.Double();\r
+ path.append(shapes.first, false);\r
+ path.append(shapes.second, false);\r
+ connection.setPath(seg, path);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+public class SysdynElementClasses {\r
+\r
+ public static final Object VALVE = new Object() {\r
+ public String toString() { return "VALVE"; }\r
+ };\r
+}\r
*/\r
static public void validateExpressionFields(final Resource variable, IExpression expression, Table variableTable) {\r
\r
- TableItem[] connectedVariables = variableTable.getItems();\r
-\r
-\r
Resource configuration = null;\r
try {\r
configuration = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
\r
// Check that the variables that exist have connections and the connected variables have references in the expressions\r
if(!(expression instanceof StockExpression)) { \r
- for(TableItem ti : connectedVariables) {\r
- if(!variables.contains(ti.getText())) {\r
- ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0));\r
- } else {\r
- ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0));\r
- variables.remove(ti.getText());\r
+ \r
+ if(variableTable != null && !variableTable.isDisposed()) {\r
+ TableItem[] connectedVariables = variableTable.getItems();\r
+ for(TableItem ti : connectedVariables) {\r
+ if(!variables.contains(ti.getText())) {\r
+ ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0));\r
+ } else {\r
+ ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0));\r
+ variables.remove(ti.getText());\r
+ }\r
}\r
}\r
\r