From b1353a22cac9887a7c225195f8e621f0bf05ccfb Mon Sep 17 00:00:00 2001 From: miettinen Date: Wed, 5 Sep 2012 06:08:28 +0000 Subject: [PATCH] * Fix: only one dependency is dragged at a time (refs #753) * If multiple dependencies are within the range, the preference is 1) selected dependency 2) the nearest dependency * Changed the hitTest function tolerance to distance instead of the distance squared git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@25644 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../sysdyn/ui/elements/connections/Arcs.java | 60 ++++++++++++-- .../connections/DependencyEdgeClass.java | 2 +- .../elements/connections/DependencyNode.java | 81 +++++++++++++++++-- 3 files changed, 130 insertions(+), 13 deletions(-) diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/Arcs.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/Arcs.java index 51d4240f..d22b298e 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/Arcs.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/Arcs.java @@ -192,14 +192,15 @@ public class Arcs { double dy = y-cy; double dist = dx*dx + dy*dy; -// System.out.println("HitTest: x0=" + x0 + " y0=" + y0 + " y=" + y + " x=" + x + " dist=" + dist + " r2=" + r*r); + //System.out.println("HitTest: x0=" + x0 + " y0=" + y0 + " y=" + y + " x=" + x + " dist=" + dist + " r2=" + r*r); - if(dist < (r+tolerance)*(r+tolerance) && - dist > (r-tolerance)*(r-tolerance)) { + double tolerance2 = tolerance * tolerance; + if(dist < (r+tolerance2)*(r+tolerance2) && + dist > (r-tolerance2)*(r-tolerance2)) { double ang = Arcs.normalizeAngle(Math.atan2(-dy, dx)); -// System.out.println("test " + angle0 + " " + ang + " " + angle1); + //System.out.println("test " + angle0 + " " + ang + " " + angle1); if(Arcs.areClockwiseOrdered(angle0, ang, angle1) == clockWise) { -// System.out.println("hit"); + //System.out.println("hit"); return true; } } @@ -207,5 +208,54 @@ public class Arcs { return false; } + + /** + * Calculates the radial distance between an arc and a point + * @param beginBounds Begin coordinate of the arc + * @param endBounds End coordinate of the arc + * @param angle The central angle of the arc + * @param x x coordinate of the measured point + * @param y x coordinate of the measured point + * @return The radial distance between the the arc and (x,y); Double.NaN if the + * distance is not real. + */ + public static double getRadialDistance(Rectangle2D beginBounds, + Rectangle2D endBounds, double angle, double x, double y) { + + boolean clockWise = angle > 0; + + double x0 = beginBounds.getCenterX(); + double y0 = beginBounds.getCenterY(); + double x1 = endBounds.getCenterX(); + double y1 = endBounds.getCenterY(); + + double offset = + Math.abs(angle) < 1.0e-6 + ? 1e3 * Math.signum(angle) + : Math.tan(Math.PI*0.5-angle)*0.5; + double cx = 0.5*(x0+x1) + offset * (y1-y0); + double cy = 0.5*(y0+y1) + offset * (x0-x1); + double dx0 = x0 - cx; + double dy0 = y0 - cy; + double dx1 = x1 - cx; + double dy1 = y1 - cy; + double r = Math.sqrt(dx0*dx0 + dy0*dy0); + double angle0 = Arcs.nextIntersectingAngle(cx, cy, r, + Math.atan2(-dy0, dx0), beginBounds, angle < 0.0); + double angle1 = Arcs.nextIntersectingAngle(cx, cy, r, + Math.atan2(-dy1, dx1), endBounds, angle > 0.0); + + double dx = x-cx; + double dy = y-cy; + double dist2 = dx*dx + dy*dy; + + double ang = Arcs.normalizeAngle(Math.atan2(-dy, dx)); + if(!Arcs.areClockwiseOrdered(angle0, ang, angle1) == clockWise) { + return Double.NaN; + } + double radialDistance = Math.abs(Math.sqrt(dist2) - r); + System.out.println("radialDistance " + radialDistance); + return radialDistance; + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyEdgeClass.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyEdgeClass.java index 64d98631..7f39198a 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyEdgeClass.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyEdgeClass.java @@ -82,7 +82,7 @@ public class DependencyEdgeClass { System.out.println("pickTest no node!"); return false; } - return Arcs.hitTest(node.getBeginBounds(), node.getEndBounds(), node.getAngle(), pickRect.getCenterX(), pickRect.getCenterY(), 3.0); + return Arcs.hitTest(node.getBeginBounds(), node.getEndBounds(), node.getAngle(), pickRect.getCenterX(), pickRect.getCenterY(), 1.7); } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyNode.java index 3c00d95d..d98d89fb 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyNode.java @@ -22,15 +22,19 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Collection; import org.simantics.diagram.elements.TextNode; import org.simantics.g2d.utils.Alignment; import org.simantics.scenegraph.ISelectionPainterNode; +import org.simantics.scenegraph.g2d.IG2DNode; import org.simantics.scenegraph.g2d.events.EventTypes; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; +import org.simantics.scenegraph.g2d.nodes.ConnectionNode; +import org.simantics.scenegraph.g2d.nodes.SingleElementNode; import org.simantics.scenegraph.utils.NodeUtil; import org.simantics.sysdyn.ui.editor.routing.DependencyRouter; import org.simantics.utils.datastructures.Pair; @@ -45,6 +49,8 @@ public class DependencyNode extends TextNode implements ISelectionPainterNode { public static final String INSIDE = "Inside"; public static final String OUTSIDE = "Outside"; + public static final double HITMARGIN = 1.7; + private static final long serialVersionUID = 1294351381209071074L; private static final BasicStroke STROKE = new BasicStroke(1.0f); @@ -235,6 +241,12 @@ public class DependencyNode extends TextNode implements ISelectionPainterNode { Point2D localPos = NodeUtil.worldToLocal(this, event.controlPosition, new Point2D.Double()); return Arcs.hitTest(beginBounds, endBounds, angle, localPos.getX(), localPos.getY(), tolerance); } + + protected double getRadialDistanse(Point2D coord) { + if(beginBounds == null || endBounds == null) return Double.NaN; + Point2D localPos = NodeUtil.worldToLocal(this, coord, new Point2D.Double()); + return Arcs.getRadialDistance(beginBounds, endBounds, angle, localPos.getX(), localPos.getY()); + } @Override public Rectangle2D getBoundsInLocal() { @@ -251,7 +263,7 @@ public class DependencyNode extends TextNode implements ISelectionPainterNode { @Override protected boolean mouseMoved(MouseMovedEvent event) { - boolean hit = hitTest(event, 3.0); + boolean hit = hitTest(event, HITMARGIN); if(dragging) { Point2D localPos = NodeUtil.worldToLocal(this, event.controlPosition, new Point2D.Double()); @@ -269,14 +281,65 @@ public class DependencyNode extends TextNode implements ISelectionPainterNode { return false; } + private static boolean isEventDummy(MouseDragBegin e) { + if (e.controlPosition.distance(0, 0) == 0 + && e.screenPosition.distance(0, 0) == 0 + && e.buttons == 0) { + return true; + } else { + return false; + } + } + @Override protected boolean mouseDragged(MouseDragBegin e) { - if(!dragging && hitTest(e, 3.0)) { - dragging = true; - return true; // consume event - } else { - return false; - } + // Get rid of dummy events from dragGestureRecognized + if (isEventDummy(e)) { + return false; + } + //System.out.println(this.toString() + " event: " + e.toString()); + boolean selected = NodeUtil.isSelected(this, 2); + double myRadialDistance = this.getRadialDistanse(e.controlPosition); + Collection nodes = this.getParent().getParent().getParent().getNodes(); + if (!selected) { + for (Object temp1 : nodes) { + if (temp1 instanceof ConnectionNode) { + for ( IG2DNode temp2 : ((ConnectionNode)temp1).getNodes()) { + if (temp2 instanceof SingleElementNode) { + for ( IG2DNode temp3 : ((SingleElementNode)temp2).getNodes()) { + if (temp3 instanceof DependencyNode){ + DependencyNode otherDependencyNode = (DependencyNode)temp3; + System.out.println(otherDependencyNode.toString()); + if (otherDependencyNode == this) { + System.out.println("We have this!"); + continue; + } + double otherNodeDist = otherDependencyNode.getRadialDistanse(e.controlPosition); + if (Double.isNaN(otherNodeDist)) { + System.out.println("We have NaN!"); + continue; + } + if (otherDependencyNode.isDragging()) { + return true; + } + if (NodeUtil.isSelected(otherDependencyNode, 2) && (otherNodeDist < HITMARGIN)) { + return false; + } + if (otherNodeDist < myRadialDistance) { + return false; + } + } + } + } + } + } + } + } + if ( (myRadialDistance < HITMARGIN) && !dragging) { + dragging = true; + return true; + } + return false; } @Override @@ -291,4 +354,8 @@ public class DependencyNode extends TextNode implements ISelectionPainterNode { } return false; } + + protected boolean isDragging() { + return dragging; + } } -- 2.47.1