/* * @(#)ShortestDistanceConnector.java * * Project: JHotdraw - a GUI framework for technical drawings * http://www.jhotdraw.org * http://jhotdraw.sourceforge.net * Copyright: (c) by the original author(s) and all contributors * License: Lesser GNU Public License (LGPL) * http://www.opensource.org/licenses/lgpl-license.html */ package org.jhotdraw.figures; import org.jhotdraw.framework.*; import org.jhotdraw.standard.*; import org.jhotdraw.util.Geom; import java.awt.*; /** * A ShortestDistance locates connection points by * finding the shortest distance between the start and * end of the connection. * It doesn't connect to the areas defined by Figure.connectionInsets() * * @see Figure#connectionInsets * @see Connector * * @version <$CURRENT_VERSION$> */ public class ShortestDistanceConnector extends AbstractConnector { /* * Serialization support. */ private static final long serialVersionUID = -2273446020593433887L; public ShortestDistanceConnector() { // only used for Storable implementation super(); } public ShortestDistanceConnector(Figure owner) { super(owner); } public Point findStart(ConnectionFigure connection) { return findPoint(connection, true); } public Point findEnd(ConnectionFigure connection) { return findPoint(connection, false); } protected Point findPoint(ConnectionFigure connection, boolean getStart) { Figure startFigure = connection.getStartConnector().owner(); Figure endFigure = connection.getEndConnector().owner(); Rectangle r1 = startFigure.displayBox(); Rectangle r2 = endFigure.displayBox(); Insets i1 = startFigure.connectionInsets(); Insets i2 = endFigure.connectionInsets(); Point p1, p2; Point start = null, end = null, s = null, e = null; long len2 = Long.MAX_VALUE, l2; int x1, x2, y1, y2; // connection points int xmin, xmax, ymin, ymax; // X-dimension // constrain width connection insets int r1x, r1width, r2x, r2width, r1y, r1height, r2y, r2height; r1x = r1.x + i1.left; r1width = r1.width - i1.left - i1.right-1; r2x = r2.x + i2.left; r2width = r2.width - i2.left - i2.right-1; // find x connection point if (r1x + r1width < r2x) { x1 = r1x + r1width; x2 = r2x; } else if (r1x > r2x + r2width) { x1 = r1x; x2 = r2x + r2width; } else { xmax = Math.max(r1x, r2x); xmin = Math.min(r1x+r1width, r2x+r2width); x1 = x2 = (xmax + xmin) /2; } // Y-Dimension // constrain with connection insets r1y = r1.y + i1.top; r1height = r1.height - i1.top - i1.bottom-1; r2y = r2.y + i2.top; r2height = r2.height - i2.top - i2.bottom-1; // y connection point if (r1y + r1height < r2y) { y1 = r1y + r1height; y2 = r2y; } else if (r1y > r2y + r2height) { y1 = r1y; y2 = r2y + r2height; } else { ymax = Math.max(r1y, r2y); ymin = Math.min(r1y+r1height, r2y+r2height); y1 = y2 = (ymax + ymin) /2; } // find shortest connection for (int i = 0; i < 4; i++) { switch(i) { case 0: // EAST-WEST p1 = Geom.east(r1); p2 = Geom.west(r2); s = new Point(p1.x, y1); e = new Point(p2.x, y2); break; case 1: // WEST-EAST p1 = Geom.west(r1); p2 = Geom.east(r2); s = new Point(p1.x, y1); e = new Point(p2.x, y2); break; case 2: // NORTH-SOUTH p1 = Geom.north(r1); p2 = Geom.south(r2); s = new Point(x1, p1.y); e = new Point(x2, p2.y); break; case 3: // SOUTH-NORTH p1 = Geom.south(r1); p2 = Geom.north(r2); s = new Point(x1, p1.y); e = new Point(x2, p2.y); break; } l2 = Geom.length2(s.x, s.y, e.x, e.y); if (l2 < len2) { start = s; end = e; len2 = l2; } } if (getStart) { return start; } return end; } }