/*******************************************************************************\r
- * Copyright (c) 2012 Association for Decentralized Information Management\r
+ * Copyright (c) 2012, 2016 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
*\r
* Contributors:\r
* VTT Technical Research Centre of Finland - initial API and implementation\r
+ * Semantum Oy - refactoring\r
*******************************************************************************/\r
package org.simantics.diagram.adapter;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\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.Rectangle2D;\r
import java.util.Collection;\r
import org.simantics.databoard.Bindings;\r
import org.simantics.db.ReadGraph;\r
import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
import org.simantics.db.Statement;\r
import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.request.ResourceRead2;\r
import org.simantics.db.common.request.UnaryRead;\r
import org.simantics.db.common.utils.NameUtils;\r
import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.diagram.adapter.RouteGraphConnectionClassFactory.BackendConnection;\r
+import org.simantics.diagram.connection.ConnectionVisuals;\r
import org.simantics.diagram.connection.RouteGraph;\r
import org.simantics.diagram.connection.RouteGraphConnectionClass;\r
import org.simantics.diagram.connection.RouteLine;\r
import org.simantics.diagram.connection.RouteNode;\r
import org.simantics.diagram.connection.RouteTerminal;\r
+import org.simantics.diagram.connection.rendering.BasicConnectionStyle;\r
+import org.simantics.diagram.connection.rendering.ConnectionStyle;\r
+import org.simantics.diagram.connection.rendering.StyledRouteGraphRenderer;\r
import org.simantics.diagram.connection.rendering.arrows.ArrowLineEndStyle;\r
import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;\r
import org.simantics.diagram.connection.rendering.arrows.PlainLineEndStyle;\r
import org.simantics.diagram.content.TerminalMap;\r
import org.simantics.diagram.query.DiagramRequests;\r
import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
import org.simantics.diagram.synchronization.graph.RouteGraphConnection;\r
import org.simantics.g2d.canvas.ICanvasContext;\r
import org.simantics.g2d.canvas.impl.CanvasContext;\r
import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.Topology.Connection;\r
import org.simantics.g2d.diagram.impl.ElementDiagram;\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.elementclass.FlagClass.Type;\r
import org.simantics.layer0.Layer0;\r
+import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphChangeEvent;\r
import org.simantics.scenegraph.utils.GeometryUtils;\r
import org.simantics.structural.stubs.StructuralResource2;\r
import org.simantics.structural2.modelingRules.CPTerminal;\r
import org.simantics.structural2.modelingRules.IModelingRules;\r
import org.simantics.utils.threads.CurrentThread;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public class RouteGraphUtils {\r
- \r
- public static boolean DEBUG = false;\r
- \r
+\r
+ public static boolean DEBUG = false;\r
+\r
public static final ILineEndStyle HEAD = new ArrowLineEndStyle("fill 2 1 0");\r
public static final ILineEndStyle TAIL = PlainLineEndStyle.INSTANCE;\r
\r
- private static EdgeEnd toEdgeEnd(ReadGraph graph, Resource attachmentRelation, EdgeEnd defaultValue)\r
- throws DatabaseException {\r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- if (graph.isSubrelationOf(attachmentRelation, DIA.HasTailConnector))\r
- return EdgeEnd.Begin;\r
- if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector))\r
- return EdgeEnd.End;\r
- return defaultValue;\r
- }\r
- \r
- private static Resource resolveFlagAttachment(ReadGraph graph, Resource connection, Resource flag, IModelingRules modelingRules) throws DatabaseException {\r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- Type type = resolveFlagType(graph, connection, flag, modelingRules);\r
- if (type != null) {\r
- switch (type) {\r
- case In: return DIA.HasPlainConnector;\r
- case Out: return DIA.HasArrowConnector;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private static Type resolveFlagType(ReadGraph graph, Resource connection, Resource flag, IModelingRules modelingRules) throws DatabaseException {\r
- return readFlagType(graph, flag);\r
+ public static RouteGraph load(ReadGraph graph, Resource diagramRuntime, Resource connection) throws DatabaseException {\r
+ ICanvasContext canvas = new CanvasContext(CurrentThread.getThreadAccess());\r
+ IDiagram diagram = new ElementDiagram(canvas);\r
+ return load(graph, diagramRuntime, connection, canvas, diagram);\r
}\r
\r
- private static Type readFlagType(ReadGraph graph, Resource flag) throws DatabaseException {\r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- Resource flagType = graph.getPossibleObject(flag, DIA.HasFlagType);\r
- Type type = DiagramGraphUtil.toFlagType(DIA, flagType);\r
- return type;\r
+ public static RouteGraph load(ReadGraph graph, Resource diagramRuntime, Resource connection, ICanvasContext canvas, IDiagram diagram) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ Resource diagramResource = graph.getPossibleObject(connection, L0.PartOf);\r
+ IModelingRules modelingRules = graph.syncRequest(DiagramRequests.getModelingRules(diagramResource, null), TransientCacheListener.<IModelingRules>instance());\r
+ return load(graph, diagramRuntime, connection, canvas, diagram, modelingRules, null);\r
}\r
\r
-// public static ILineEndStyle loadLineEndStyle(ReadGraph graph, Resource attachmentRelation, ILineEndStyle defaultValue)\r
-// throws DatabaseException {\r
-// ILineEndStyle style = graph.syncRequest(new LineEndStyle(attachmentRelation),\r
-// TransientCacheListener.<ILineEndStyle>instance());\r
-// return style != null ? style : defaultValue;\r
-// }\r
+ public static RouteGraph load(ReadGraph graph, Resource diagramRuntime, Resource connection, ICanvasContext canvas, IDiagram diagram, IModelingRules modelingRules, Set<BackendConnection> backendConnections) throws DatabaseException {\r
\r
- /**\r
- * A request for caching ILineEndStyle results.\r
- */\r
- public static class LineEndStyle extends UnaryRead<Resource, ILineEndStyle> {\r
- public LineEndStyle(Resource attachmentRelation) {\r
- super(attachmentRelation);\r
- }\r
- @Override\r
- public ILineEndStyle perform(ReadGraph graph) throws DatabaseException {\r
- return loadLineEndStyle0(graph, parameter);\r
- }\r
- }\r
-\r
- public static ILineEndStyle loadLineEndStyle0(ReadGraph graph, Resource attachmentRelation)\r
- throws DatabaseException {\r
- ILineEndStyle style = graph.getPossibleAdapter(attachmentRelation, ILineEndStyle.class);\r
- if (style != null)\r
- return style;\r
DiagramResource DIA = DiagramResource.getInstance(graph);\r
- if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector))\r
- return HEAD;\r
- if (graph.isSubrelationOf(attachmentRelation, DIA.HasTailConnector))\r
- return TAIL;\r
- return null;\r
- }\r
- \r
- private static Statement findTerminalStatement(ReadGraph graph, Resource connection, Resource connector)\r
- throws DatabaseException {\r
- \r
- StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
- \r
- for (Statement stm : graph.getStatements(connector, STR.Connects)) {\r
- if (connection.equals(stm.getObject()))\r
- continue;\r
- return stm;\r
- }\r
- return null;\r
- \r
- }\r
-\r
- private static Resource getInverseAttachment(ReadGraph graph, Resource attachmentRelation)\r
- throws DatabaseException {\r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- Resource inverse = graph.getPossibleObject(attachmentRelation, DIA.HasInverseAttachment);\r
- if (inverse != null)\r
- return inverse;\r
- if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector))\r
- return DIA.HasPlainConnector;\r
- if (graph.isSubrelationOf(attachmentRelation, DIA.HasTailConnector))\r
- return DIA.HasArrowConnector;\r
- return null;\r
- }\r
-\r
- public static RouteGraph load(ReadGraph graph, Resource diagramRuntime, Resource connection) throws DatabaseException {\r
-\r
- ICanvasContext canvas = new CanvasContext(CurrentThread.getThreadAccess());\r
- IDiagram diagram = new ElementDiagram(canvas);\r
- return load(graph, diagramRuntime, connection, canvas, diagram);\r
-\r
- }\r
-\r
- public static RouteGraph load(ReadGraph graph, Resource diagramRuntime, Resource connection, ICanvasContext canvas, IDiagram diagram) throws DatabaseException {\r
- \r
- Layer0 L0 = Layer0.getInstance(graph);\r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
- \r
- Resource diagramResource = graph.getPossibleObject(connection, L0.PartOf);\r
- \r
- IModelingRules modelingRules = graph.syncRequest(DiagramRequests.getModelingRules(diagramResource, null), TransientCacheListener.<IModelingRules>instance());\r
-\r
-// IModelingRules modelingRules = diagram.getHint(DiagramModelHints.KEY_MODELING_RULES);\r
-// Resource diagramRuntime = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
\r
RouteGraph rg = new RouteGraph();\r
\r
for (Statement toConnector : toConnectorStatements) {\r
Resource connector = toConnector.getObject();\r
\r
- Statement terminalStm = findTerminalStatement(graph, connection, connector);\r
+ Statement terminalStm = findTerminalStatement(graph, connection, connector, STR);\r
if (terminalStm == null)\r
// Ignore broken connector: attached to the connection but not to any terminal.\r
continue;\r
System.out.println("modeling rules decided attachment: " + NameUtils.getSafeName(graph, attachment, true) + " for (" + NameUtils.toString(graph, toConnector, true) + ") & (" + NameUtils.toString(graph, terminalStm, true) + ")");\r
} else if (graph.isInstanceOf(terminalElement, DIA.Flag)) {\r
// Secondary: believe flag type\r
- attachment = resolveFlagAttachment(graph, connection, terminalElement, modelingRules);\r
+ attachment = resolveFlagAttachment(graph, connection, terminalElement, modelingRules, DIA);\r
if (attachment != null) {\r
if (connectorToModeledAttachment == null)\r
connectorToModeledAttachment = new THashMap<Resource, Resource>(toConnectorStatements.size());\r
\r
Resource forcedAttachmentRelation = null;\r
if (terminalCount == 2 && connectorToModeledAttachment.size() == 1) {\r
- forcedAttachmentRelation = getInverseAttachment(graph, connectorToModeledAttachment.values().iterator().next());\r
+ forcedAttachmentRelation = getInverseAttachment(graph, connectorToModeledAttachment.values().iterator().next(), DIA);\r
if (DEBUG)\r
System.out.println("set forced attachment: " + NameUtils.getSafeLabel(graph, forcedAttachmentRelation));\r
}\r
\r
Resource connectionType = graph.getPossibleObject(connection, STR.HasConnectionType); \r
\r
- // Needed to support ConnectionEntity#getTerminalConnections\r
- Set<BackendConnection> backendConnections = new THashSet<BackendConnection>(toConnectorStatements.size(), 0.75f);\r
-\r
// Load all node terminal connections as RouteTerminals\r
for (Statement toConnector : toConnectorStatements) {\r
Resource connector = toConnector.getObject();\r
if (DEBUG)\r
System.out.println("original attachment relation: " + NameUtils.getSafeLabel(graph, attachmentRelation));\r
\r
- Statement terminalStm = findTerminalStatement(graph, connection, connector);\r
+ Statement terminalStm = findTerminalStatement(graph, connection, connector, STR);\r
if (terminalStm == null)\r
// Ignore broken connector: attached to the connection but not to any terminal.\r
continue;\r
System.out.println("terminal: " + graph.getURI(terminalStm.getPredicate()));\r
}\r
AffineTransform terminalElementTr = diagramRuntime != null ?\r
- DiagramGraphUtil.getDynamicWorldTransform(graph, diagramRuntime, terminalElement) : \r
- DiagramGraphUtil.getWorldTransform(graph, terminalElement);\r
- \r
+ DiagramGraphUtil.getDynamicWorldTransform(graph, diagramRuntime, terminalElement) : \r
+ DiagramGraphUtil.getWorldTransform(graph, terminalElement);\r
+\r
if (DEBUG)\r
System.out.println("terminalElementTr: " + terminalElementTr);\r
\r
if (DEBUG)\r
System.out.println("decided attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation));\r
\r
-// // Get element bounds to decide allowed terminal direction(s)\r
+ // Get element bounds to decide allowed terminal direction(s)\r
IElement te = graph.syncRequest(DiagramRequests.getElement(canvas, diagram, terminalElement, null));\r
ElementUtils.getElementBounds(te, bounds);\r
{\r
}\r
//System.out.println("DIR(" + x + ", " + y + ", " + bounds + "): " + Integer.toHexString(direction));\r
\r
- backendConnections.add(\r
- new BackendConnection(\r
- toEdgeEnd(graph, attachmentRelation, EdgeEnd.Begin),\r
- terminalElement,\r
- terminal)\r
- );\r
+ if (backendConnections != null) {\r
+ backendConnections.add(\r
+ new BackendConnection(\r
+ toEdgeEnd(graph, attachmentRelation, EdgeEnd.Begin, DIA),\r
+ terminalElement,\r
+ terminal)\r
+ );\r
+ }\r
\r
if (direction == 0)\r
// Accept any horizontal/vertical direction if nothing is defined\r
\r
if (DEBUG)\r
System.out.println("load line style: " + NameUtils.getSafeLabel(graph, attachmentRelation));\r
- ILineEndStyle endStyle = RouteGraphConnectionClassFactory.loadLineEndStyle(graph, attachmentRelation, connectionType, RouteGraphConnectionClassFactory.TAIL);\r
+ ILineEndStyle endStyle = loadLineEndStyle(graph, attachmentRelation, connectionType, TAIL);\r
\r
RouteTerminal routeTerminal = rg.addTerminal(x, y, minx, miny, maxx, maxy, direction, endStyle);\r
routeTerminal.setData( RouteGraphConnection.serialize(graph, connector) );\r
rg.link(n1, n2);\r
}\r
\r
-// // Load connection line style.\r
-// ConnectionStyle style = readConnectionStyle(graph, canvas, modelingRules, connection);\r
-// StyledRouteGraphRenderer renderer = getRenderer(graph, canvas, style);\r
-//\r
-// // Finish element load\r
-// element.setHint(RouteGraphConnectionClass.KEY_ROUTEGRAPH, rg);\r
-// element.setHint(RouteGraphConnectionClass.KEY_RENDERER, renderer);\r
-// element.setHint(RouteGraphConnectionClass.KEY_PICK_TOLERANCE, 0.5);\r
-//\r
-// // Initialize ConnectionEntity in element\r
-// element.setHint(ElementHints.KEY_CONNECTION_ENTITY, new CE(diagram, connection, element, backendConnections));\r
-//\r
-// // Setup graph writeback support for route graph modifications\r
-// final Session session = graph.getSession();\r
-// element.setHint(RouteGraphConnectionClass.KEY_RG_LISTENER, new IRouteGraphListener() {\r
-// @Override\r
-// public void routeGraphChanged(RouteGraphChangeEvent event) {\r
-// scheduleSynchronize(session, connection, event);\r
-// }\r
-// });\r
- \r
return rg;\r
\r
- }\r
+ }\r
+\r
+ private static EdgeEnd toEdgeEnd(ReadGraph graph, Resource attachmentRelation, EdgeEnd defaultValue, DiagramResource DIA)\r
+ throws DatabaseException {\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasTailConnector))\r
+ return EdgeEnd.Begin;\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector))\r
+ return EdgeEnd.End;\r
+ return defaultValue;\r
+ }\r
+\r
+ private static Resource resolveFlagAttachment(ReadGraph graph, Resource connection, Resource flag, IModelingRules modelingRules, DiagramResource DIA) throws DatabaseException {\r
+ Type type = resolveFlagType(graph, connection, flag, modelingRules, DIA);\r
+ if (type != null) {\r
+ switch (type) {\r
+ case In: return DIA.HasPlainConnector;\r
+ case Out: return DIA.HasArrowConnector;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private static Type resolveFlagType(ReadGraph graph, Resource connection, Resource flag, IModelingRules modelingRules, DiagramResource DIA) throws DatabaseException {\r
+ return readFlagType(graph, flag, DIA);\r
+ }\r
+\r
+ private static Type readFlagType(ReadGraph graph, Resource flag, DiagramResource DIA) throws DatabaseException {\r
+ Resource flagType = graph.getPossibleObject(flag, DIA.HasFlagType);\r
+ Type type = DiagramGraphUtil.toFlagType(DIA, flagType);\r
+ return type;\r
+ }\r
+\r
+ private static Statement findTerminalStatement(ReadGraph graph, Resource connection, Resource connector, StructuralResource2 STR)\r
+ throws DatabaseException {\r
+ for (Statement stm : graph.getStatements(connector, STR.Connects)) {\r
+ if (connection.equals(stm.getObject()))\r
+ continue;\r
+ return stm;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private static Resource getInverseAttachment(ReadGraph graph, Resource attachmentRelation, DiagramResource DIA)\r
+ throws DatabaseException {\r
+ Resource inverse = graph.getPossibleObject(attachmentRelation, DIA.HasInverseAttachment);\r
+ if (inverse != null)\r
+ return inverse;\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector))\r
+ return DIA.HasPlainConnector;\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasTailConnector))\r
+ return DIA.HasArrowConnector;\r
+ return null;\r
+ }\r
+\r
+ public static ILineEndStyle loadLineEndStyle(ReadGraph graph, Resource attachmentRelation, ILineEndStyle defaultValue)\r
+ throws DatabaseException {\r
+ ILineEndStyle style = graph.syncRequest(new LineEndStyle(attachmentRelation),\r
+ TransientCacheListener.<ILineEndStyle>instance());\r
+ return style != null ? style : defaultValue;\r
+ }\r
+\r
+ public static ILineEndStyle loadLineEndStyle(ReadGraph graph, Resource attachmentRelation, Resource connectionType, ILineEndStyle defaultValue)\r
+ throws DatabaseException {\r
+ if(connectionType != null) {\r
+ ILineEndStyle style = graph.syncRequest(new LineEndStyleWithType(attachmentRelation, connectionType),\r
+ TransientCacheListener.<ILineEndStyle>instance());\r
+ return style != null ? style : defaultValue;\r
+ } else {\r
+ ILineEndStyle style = graph.syncRequest(new LineEndStyle(attachmentRelation),\r
+ TransientCacheListener.<ILineEndStyle>instance());\r
+ return style != null ? style : defaultValue;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * A request for caching ILineEndStyle results.\r
+ */\r
+ public static class LineEndStyle extends UnaryRead<Resource, ILineEndStyle> {\r
+ public LineEndStyle(Resource attachmentRelation) {\r
+ super(attachmentRelation);\r
+ }\r
+ @Override\r
+ public ILineEndStyle perform(ReadGraph graph) throws DatabaseException {\r
+ return loadLineEndStyle0(graph, parameter);\r
+ }\r
+ }\r
+\r
+ public static class LineEndStyleWithType extends ResourceRead2<ILineEndStyle> {\r
+ public LineEndStyleWithType(Resource attachmentRelation, Resource connectionType) {\r
+ super(attachmentRelation, connectionType);\r
+ }\r
+ @Override\r
+ public ILineEndStyle perform(ReadGraph graph) throws DatabaseException {\r
+ return loadLineEndStyle0(graph, resource, resource2);\r
+ }\r
+ }\r
+ \r
+ private static ILineEndStyle loadLineEndStyle0(ReadGraph graph, Resource attachmentRelation)\r
+ throws DatabaseException {\r
+ ILineEndStyle style = graph.getPossibleAdapter(attachmentRelation, ILineEndStyle.class);\r
+ if (style != null)\r
+ return style;\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector))\r
+ return HEAD;\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasTailConnector))\r
+ return TAIL;\r
+ return null;\r
+ }\r
+\r
+ private static ILineEndStyle loadLineEndStyle0(ReadGraph graph, Resource attachmentRelation, Resource connectionType)\r
+ throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector)) {\r
+ if(connectionType != null) {\r
+ G2DResource G2D = G2DResource.getInstance(graph);\r
+ Resource end = graph.getPossibleObject(connectionType, G2D.HasEndArrow);\r
+ if(end != null) {\r
+ Double size = graph.getPossibleRelatedValue(end, G2D.HasSize, Bindings.DOUBLE);\r
+ if(size == null) size = 0.0;\r
+ Double widthRatio = graph.getPossibleRelatedValue(end, G2D.HasWidthRatio, Bindings.DOUBLE);\r
+ if(widthRatio == null) widthRatio = 1.0;\r
+ Double space = graph.getPossibleRelatedValue(end, G2D.HasSpace, Bindings.DOUBLE);\r
+ if(space == null) space = 0.0;\r
+\r
+ Resource c = graph.getPossibleObject(end, G2D.HasColor);\r
+ Color color = null;\r
+ if (c != null) {\r
+ float[] col = graph.getPossibleValue(c, Bindings.FLOAT_ARRAY);\r
+ if (col != null && col.length >= 3) {\r
+ color = new Color(col[0], col[1], col[2]);\r
+ }\r
+ }\r
+\r
+ return new ArrowLineEndStyle(size, widthRatio*size, space, color);\r
+ }\r
+ }\r
+ }\r
+ return loadLineEndStyle0(graph, attachmentRelation);\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param canvas\r
+ * @param style\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ protected static StyledRouteGraphRenderer getRenderer(ReadGraph graph, ConnectionStyle style)\r
+ throws DatabaseException {\r
+ return graph.syncRequest(new Renderer(style),\r
+ TransientCacheListener.<StyledRouteGraphRenderer>instance());\r
+ }\r
+\r
+ /**\r
+ * A request for caching StyledRouteGraphRenderer results.\r
+ */\r
+ public static class Renderer extends UnaryRead<ConnectionStyle, StyledRouteGraphRenderer> {\r
+ public Renderer(ConnectionStyle style) {\r
+ super(style);\r
+ }\r
+ @Override\r
+ public StyledRouteGraphRenderer perform(ReadGraph graph) throws DatabaseException {\r
+ return new StyledRouteGraphRenderer(parameter);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param canvas\r
+ * @param modelingRules\r
+ * @param connection\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ protected static ConnectionStyle readConnectionStyle(ReadGraph graph, IModelingRules modelingRules, Resource connection, StructuralResource2 STR) throws DatabaseException {\r
+ Resource connectionType = null;\r
+ if (modelingRules != null)\r
+ connectionType = modelingRules.getConnectionType(graph, connection);\r
+ if (connectionType == null)\r
+ connectionType = graph.getPossibleObject(connection, STR.HasConnectionType);\r
+ return readConnectionStyleFromConnectionType(graph, connectionType);\r
+ }\r
+\r
+ protected static ConnectionStyle readConnectionStyleFromConnectionType(ReadGraph graph, Resource connectionType) throws DatabaseException {\r
+ return graph.syncRequest(new ReadConnectionStyleFromConnectionType(connectionType),\r
+ TransientCacheListener.<ConnectionStyle>instance());\r
+ }\r
+\r
+ /**\r
+ * A request for caching ConnectionStyle results.\r
+ */\r
+ public static class ReadConnectionStyleFromConnectionType extends UnaryRead<Resource, ConnectionStyle> {\r
+ public ReadConnectionStyleFromConnectionType(Resource connectionType) {\r
+ super(connectionType);\r
+ }\r
+ @Override\r
+ public ConnectionStyle perform(ReadGraph graph) throws DatabaseException {\r
+ return readConnectionStyleFromConnectionType0(graph, parameter);\r
+ }\r
+ }\r
+\r
+ protected static ConnectionStyle readConnectionStyleFromConnectionType0(ReadGraph graph, Resource connectionType) throws DatabaseException {\r
+ ConnectionVisuals cv = null;\r
+ if (connectionType != null)\r
+ cv = graph.syncRequest(DiagramRequests.getConnectionVisuals(connectionType),\r
+ TransientCacheListener.<ConnectionVisuals>instance());\r
+\r
+ // Fixed style settings\r
+ Color branchPointColor = Color.BLACK;\r
+ double branchPointRadius = 0.5;\r
+ double degenerateLineLength = 0.8;\r
+\r
+ Color lineColor = cv != null ? cv.toColor() : null;\r
+ if (lineColor == null)\r
+ lineColor = Color.DARK_GRAY;\r
+ Stroke lineStroke = cv != null ? cv.stroke : null;\r
+ if (lineStroke == null)\r
+ lineStroke = new BasicStroke(0.1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, null, 0);\r
+ Stroke routeLineStroke = GeometryUtils.scaleStrokeWidth(lineStroke, 2);\r
+\r
+ return new BasicConnectionStyle(\r
+ lineColor,\r
+ branchPointColor,\r
+ branchPointRadius,\r
+ lineStroke,\r
+ routeLineStroke,\r
+ degenerateLineLength);\r
+ }\r
+\r
+ public static void scheduleSynchronize(Session session, Resource connection, RouteGraphChangeEvent event) {\r
+ session.asyncRequest(RouteGraphConnection.synchronizer(connection, event));\r
+ }\r
\r
// ------------------------------------------------------------------------\r
// RouteGraph RouteTerminal allowed direction rotation support\r
private static final double DEG_45 = Math.PI/4.;\r
private static final double DEG_135 = Math.PI*3./4.;\r
\r
+ static class BackendConnection {\r
+ public final Resource node;\r
+ public final Resource terminal;\r
+ public final EdgeEnd end;\r
+ public final int hash;\r
+ public BackendConnection(EdgeEnd end, Resource node, Resource terminal) {\r
+ assert end != null;\r
+ assert node != null;\r
+ assert terminal != null;\r
+ this.end = end;\r
+ this.node = node;\r
+ this.terminal = terminal;\r
+ this.hash = makeHash();\r
+ }\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (!(obj instanceof Connection))\r
+ return false;\r
+ Connection other = (Connection) obj;\r
+ return other.terminal == terminal\r
+ && other.node == node\r
+ && other.end == end;\r
+ }\r
+ private int makeHash() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + end.hashCode();\r
+ result = prime * result + ((node == null) ? 0 : node.hashCode());\r
+ result = prime * result + ((terminal == null) ? 0 : terminal.hashCode());\r
+ return result;\r
+ }\r
+ @Override\r
+ public int hashCode() {\r
+ return hash;\r
+ }\r
+ @Override\r
+ public String toString() {\r
+ return "BackendConnection[node=" + node + ", terminal=" + terminal + ", end=" + end + "]";\r
+ }\r
+ }\r
+\r
}\r