X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fg2d%2Fnodes%2Fconnection%2FRouteGraphNode.java;h=3c7b9bad85be182d92cca5637f2fddfcd390169f;hp=687731f4c2f9d8528ab40cc0c6189151672828f4;hb=e3f46ffc9d4a6930adc83ebb8e6730f19708cc94;hpb=5f0ad7a26810df602600c5eddad317588fce0ac4 diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java index 687731f4c..3c7b9bad8 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java @@ -24,6 +24,7 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.lang.reflect.Constructor; import java.util.Collection; +import java.util.List; import java.util.Map; import org.simantics.diagram.connection.RouteGraph; @@ -45,6 +46,7 @@ import org.simantics.scenegraph.INode; import org.simantics.scenegraph.ISelectionPainterNode; import org.simantics.scenegraph.g2d.G2DNode; import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.G2DSceneGraph; import org.simantics.scenegraph.g2d.IG2DNode; import org.simantics.scenegraph.g2d.events.EventTypes; import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent; @@ -59,12 +61,17 @@ import org.simantics.scenegraph.g2d.events.command.CommandEvent; import org.simantics.scenegraph.g2d.events.command.Commands; import org.simantics.scenegraph.g2d.nodes.GridNode; import org.simantics.scenegraph.g2d.nodes.LinkNode; +import org.simantics.scenegraph.g2d.nodes.NavigationNode; +import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment; import org.simantics.scenegraph.g2d.nodes.connection.HighlightActionPointsAction.Action; import org.simantics.scenegraph.g2d.nodes.connection.HighlightActionPointsAction.Pick; import org.simantics.scenegraph.g2d.snap.ISnapAdvisor; +import org.simantics.scenegraph.utils.ColorUtil; import org.simantics.scenegraph.utils.GeometryUtils; import org.simantics.scenegraph.utils.InitValueSupport; import org.simantics.scenegraph.utils.NodeUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import gnu.trove.map.hash.THashMap; @@ -73,7 +80,9 @@ import gnu.trove.map.hash.THashMap; */ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, InitValueSupport { - private static final long serialVersionUID = -917194130412280965L; + private static final Logger LOGGER = LoggerFactory.getLogger(RouteGraphNode.class); + + private static final long serialVersionUID = -917194130412280965L; private static final double TOLERANCE = IAction.TOLERANCE; private static final Stroke SELECTION_STROKE = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); @@ -123,7 +132,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In protected transient Map dynamicStyles = null; - + private transient boolean ignoreSelection = false; @Override @@ -132,6 +141,74 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In wrapRenderer(); } + private static float tryParseFloat(String s, float def) { + try { + return Float.parseFloat(s); + } catch (NumberFormatException e) { + LOGGER.error("Could not parse '" + s + "' into float."); + return def; + } + } + + /* + * 1.0 BUTT MITER 1.0 0.0 + */ + private static Stroke parseStroke(String definition) { + + float width = 1.0f; + int cap = BasicStroke.CAP_BUTT; + int join = BasicStroke.JOIN_MITER; + float miterLimit = 1.0f; + float[] dash = { 1, 0}; + float dash_phase = 0; + + String[] parts = definition.split(" "); + + if(parts.length > 0) { + width = tryParseFloat(parts[0], width); + } + if(parts.length > 1) { + if("BUTT".equals(parts[1])) cap = BasicStroke.CAP_BUTT; + else if("ROUND".equals(parts[1])) cap = BasicStroke.CAP_ROUND; + else if("SQUARE".equals(parts[1])) cap = BasicStroke.CAP_SQUARE; + } + if(parts.length > 2) { + if("BEVEL".equals(parts[2])) cap = BasicStroke.JOIN_BEVEL; + else if("MITER".equals(parts[2])) cap = BasicStroke.JOIN_MITER; + else if("ROUND".equals(parts[2])) cap = BasicStroke.JOIN_ROUND; + } + if(parts.length > 3) { + miterLimit = tryParseFloat(parts[3], miterLimit); + } + if(parts.length > 4) { + dash_phase = tryParseFloat(parts[4], dash_phase); + } + if(parts.length > 6) { + dash = new float[parts.length - 5]; + for(int i=5;i assignments) { + for(SVGNodeAssignment ass : assignments) { + if("dynamicColor".equals(ass.elementId)) { + setDynamicColor(ColorUtil.hexColor(ass.value)); + } else if("dynamicStroke".equals(ass.elementId)) { + setDynamicStroke(parseStroke(ass.value)); + } + } + } + public void setIgnoreSelection(boolean value) { ignoreSelection = value; } @@ -211,6 +288,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In selectionStroke = new BasicStroke(width, BasicStroke.CAP_BUTT, stroke.getLineJoin()); } } else { + // TODO: support AggregateConnectionStyle selectionStroke = SELECTION_STROKE; } } @@ -224,24 +302,28 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In if(dynamicColor != null || dynamicStroke != null) { BasicConnectionStyle baseStyle = (BasicConnectionStyle)tryGetStyle(baseRenderer); - try { - Constructor c = baseStyle.getClass().getConstructor(Color.class, Color.class, double.class, Stroke.class, Stroke.class, double.class, double.class); - renderer = new StyledRouteGraphRenderer(c.newInstance( - dynamicColor != null ? dynamicColor : baseStyle.getLineColor(), - baseStyle.getBranchPointColor(), baseStyle.getBranchPointRadius(), - dynamicStroke != null ? dynamicStroke : baseStyle.getLineStroke(), - dynamicStroke != null ? dynamicStroke : baseStyle.getRouteLineStroke(), - baseStyle.getDegeneratedLineLength(), baseStyle.getRounding())); - } catch (Exception e) { - renderer = new StyledRouteGraphRenderer(new BasicConnectionStyle( - dynamicColor != null ? dynamicColor : baseStyle.getLineColor(), - baseStyle.getBranchPointColor(), baseStyle.getBranchPointRadius(), - dynamicStroke != null ? dynamicStroke : baseStyle.getLineStroke(), - dynamicStroke != null ? dynamicStroke : baseStyle.getRouteLineStroke(), - baseStyle.getDegeneratedLineLength(), baseStyle.getRounding())); + if (baseStyle != null) { + try { + Constructor c = baseStyle.getClass().getConstructor(Color.class, Color.class, double.class, Stroke.class, Stroke.class, double.class, double.class, double.class); + renderer = new StyledRouteGraphRenderer(c.newInstance( + dynamicColor != null ? dynamicColor : baseStyle.getLineColor(), + baseStyle.getBranchPointColor(), baseStyle.getBranchPointRadius(), + dynamicStroke != null ? dynamicStroke : baseStyle.getLineStroke(), + dynamicStroke != null ? dynamicStroke : baseStyle.getRouteLineStroke(), + baseStyle.getDegeneratedLineLength(), baseStyle.getRounding(), baseStyle.getOffset())); + } catch (Exception e) { + renderer = new StyledRouteGraphRenderer(new BasicConnectionStyle( + dynamicColor != null ? dynamicColor : baseStyle.getLineColor(), + baseStyle.getBranchPointColor(), baseStyle.getBranchPointRadius(), + dynamicStroke != null ? dynamicStroke : baseStyle.getLineStroke(), + dynamicStroke != null ? dynamicStroke : baseStyle.getRouteLineStroke(), + baseStyle.getDegeneratedLineLength(), baseStyle.getRounding(), baseStyle.getOffset())); + } + } else { + // TODO: support AggregateConnectionStyle + renderer = baseRenderer; } - } else { renderer = baseRenderer; } @@ -302,7 +384,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In * @param after * @return true if changes were fired */ - private boolean setRouteGraphAndFireChanges(RouteGraph before, RouteGraph after) { + public boolean setRouteGraphAndFireChanges(RouteGraph before, RouteGraph after) { RouteGraphDelta delta = new RouteGraphDelta(before, after); if (!delta.isEmpty()) { setRouteGraph(after); @@ -410,7 +492,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In return null; } - private double getSelectionStrokeWidth() { + public double getSelectionStrokeWidth() { if (selectionStroke instanceof BasicStroke) { BasicStroke bs = (BasicStroke) selectionStroke; return bs.getLineWidth(); @@ -454,6 +536,12 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In @Override protected boolean mouseDragged(MouseDragBegin e) { + // Consume event if drag is possible. + // PointerInteractor will call handleDrag with the MouseDragBegin event for the route line that is closest to the cursor. + return currentAction != null; + } + + public boolean handleDrag(MouseDragBegin e) { if (dragAction != null && !e.hasAnyModifier(MouseEvent.ALL_MODIFIERS_MASK) && e.button == MouseEvent.LEFT_BUTTON) { currentAction = dragAction; dragAction = null; @@ -473,7 +561,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In } } if (newBranchPointPosition != null) { - RouteLine line = rg.pickLine(mouseX, mouseY, pickTolerance); + RouteLine line = rg.pickLine(mouseX, mouseY, scaledPickTolerance()); if (line != null) { newBranchPointPosition.setLocation(mouseX, mouseY); SplittedRouteGraph.snapToLine(newBranchPointPosition, line); @@ -584,7 +672,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In return false; } //System.out.println("move action"); - dragAction = SnappingMoveAction.create(rg, mouseX, mouseY, pickTolerance, moveFilter, getSnapAdvisor()); + dragAction = SnappingMoveAction.create(rg, mouseX, mouseY, scaledPickTolerance(), moveFilter, getSnapAdvisor()); //System.out.println("DRAG ACTION: " + dragAction); } @@ -595,6 +683,20 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In return false; } + private double scaledPickTolerance() { + NavigationNode nn = NodeUtil.findNearestParentNode(this, NavigationNode.class); + double scale = 1.0; + if (nn != null) { + scale = GeometryUtils.getScale(nn.getTransform()); + } + double pickDistance = 0; + G2DSceneGraph sg = NodeUtil.getRootNode(nn != null ? nn : this); + if (sg != null) { + pickDistance = sg.getGlobalProperty(G2DSceneGraph.PICK_DISTANCE, pickDistance); + } + return Math.max(getSelectionStrokeWidth() / 2.0, pickDistance / scale); + } + /** * Checks the selections data node in the scene graph for any links * @return @@ -679,11 +781,11 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In return false; if (!e.hasAnyModifier(MouseEvent.ALL_MODIFIERS_MASK) && e.keyCode == KeyEvent.VK_S) { - Object target = rg.pick(mouseX, mouseY, pickTolerance, RouteGraph.PICK_PERSISTENT_LINES | RouteGraph.PICK_TRANSIENT_LINES); + Object target = rg.pick(mouseX, mouseY, scaledPickTolerance(), RouteGraph.PICK_PERSISTENT_LINES | RouteGraph.PICK_TRANSIENT_LINES); return splitTarget(target); } else if (!e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK | MouseEvent.CTRL_MASK) && (e.keyCode == KeyEvent.VK_R || e.keyCode == KeyEvent.VK_D)) { - Object target = rg.pick(mouseX, mouseY, pickTolerance, RouteGraph.PICK_PERSISTENT_LINES); + Object target = rg.pick(mouseX, mouseY, scaledPickTolerance(), RouteGraph.PICK_PERSISTENT_LINES); return deleteTarget(target); } else if (e.keyCode == KeyEvent.VK_ESCAPE) { @@ -707,7 +809,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In } else if (e.keyCode == KeyEvent.VK_ALT) { // Begin connection branching visualization. - RouteLine line = rg.pickLine(mouseX, mouseY, pickTolerance); + RouteLine line = rg.pickLine(mouseX, mouseY, scaledPickTolerance()); if (branchable && line != null) { newBranchPointPosition = new Point2D.Double(mouseX, mouseY); SplittedRouteGraph.snapToLine(newBranchPointPosition, line);