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=b0e9147f63134e5c2af5dee0c2436efbdbc016e3;hp=084c0d6582874a7f7cb64439a58e2495e4da12f8;hb=e353ca45b2ad3ce36ea48336feca56e86ad0b089;hpb=e8269f6cba002c702c25d80db5399b5b50b97ab9 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 084c0d658..b0e9147f6 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,6 +132,8 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In protected transient Map dynamicStyles = null; + + private transient boolean ignoreSelection = false; @Override public void initValues() { @@ -130,6 +141,82 @@ 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; + } + + public boolean getIgnoreSelection() { + return ignoreSelection; + } + @PropertySetter("color") @SyncField(value = {"dynamicColor"}) public void setDynamicColor(Color color) { @@ -292,7 +379,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); @@ -347,7 +434,9 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In Object aaHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - boolean selected = NodeUtil.isSelected(this, 1); + boolean selected = ignoreSelection ? false : NodeUtil.isSelected(this, 1); + + rg.updateTerminals(); if (currentAction != null) { currentAction.render(g, renderer, mouseX, mouseY); @@ -398,7 +487,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(); @@ -442,6 +531,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; @@ -461,7 +556,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); @@ -572,7 +667,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); } @@ -583,6 +678,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 @@ -667,11 +776,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) { @@ -695,7 +804,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);