| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.draw2d; |
| |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.draw2d.geometry.Transposer; |
| |
| /** |
| * Used to place IFigures along the endpoint or starting point of a |
| * {@link Connection}. <code>uDistance</code> represents the distance from the |
| * Connection's owner to the IFigure. <code>vDistance</code> represents the |
| * distance from the IFigure to the Connection itself. |
| */ |
| public class ConnectionEndpointLocator implements Locator { |
| |
| private boolean end; |
| private Connection conn; |
| private int uDistance; |
| private int vDistance; |
| private static Rectangle figureBounds; |
| |
| /** |
| * Transposes the location if the connection point is along the top or |
| * bottom of its owner figure. |
| */ |
| protected Transposer transposer = new Transposer(); |
| |
| /** |
| * Constructs a ConnectionEndpointLocator using the given {@link Connection} |
| * . If <i>isEnd</i> is <code>true</code>, the location is relative to the |
| * Connection's end (or target) point. If <i>isEnd</i> is <code>false</code> |
| * , the location is relative to the Connection's start (or source) point. |
| * |
| * @param c |
| * The Connection |
| * @param isEnd |
| * <code>true</code> is location is relative to end point |
| * @since 2.0 |
| */ |
| public ConnectionEndpointLocator(Connection c, boolean isEnd) { |
| end = isEnd; |
| conn = c; |
| uDistance = 14; |
| vDistance = 4; |
| figureBounds = new Rectangle(); |
| } |
| |
| /* |
| * Returns an integer representing the side of the passed Rectangle that a |
| * point lies on. 1 == Top 2 == Right 3 == Bottom 4 == Left |
| * |
| * @param loc The point that is to be located |
| */ |
| private int calculateConnectionLocation(Point loc, Point topLeft, |
| Point center) { |
| double m1, m2 = 0; |
| m1 = (double) (topLeft.y - center.y) / (double) (topLeft.x - center.x); |
| |
| if (loc.x - center.x != 0) |
| m2 = (double) (loc.y - center.y) / (double) (loc.x - center.x); |
| |
| if (loc.x == center.x) { |
| // Case where m2 is vertical |
| if (loc.y < center.y) |
| return 3; |
| else |
| return 1; |
| } else if (Math.abs(m2) <= Math.abs(m1)) { |
| // Connection start point along left or right side |
| if (loc.x < center.x) |
| return 4; |
| else |
| return 2; |
| } else { |
| // Connection start point along top or bottom |
| if (loc.y < center.y) |
| return 3; |
| else |
| return 1; |
| } |
| } |
| |
| /* |
| * This method is used to calculate the "quadrant" value of a connection |
| * that does not have an owner on its starting point. |
| * |
| * 1 == Top 2 == Right 3 == Bottom 4 == Left |
| * |
| * @param startPoint The starting point of the connection. |
| * |
| * @param endPoint The end point of the connection. |
| */ |
| private int calculateConnectionLocation(Point startPoint, Point endPoint) { |
| if (Math.abs(endPoint.x - startPoint.x) > Math.abs(endPoint.y |
| - startPoint.y)) { |
| if (endPoint.x > startPoint.x) |
| return 2; |
| else |
| return 4; |
| } else { |
| if (endPoint.y > startPoint.y) |
| return 1; |
| else |
| return 3; |
| } |
| } |
| |
| /* |
| * Calculates 'tan' which is used as a factor for y adjustment when placing |
| * the connection label. 'tan' is capped at 1.0 in the positive direction |
| * and -1.0 in the negative direction. |
| * |
| * @param startPoint The starting point of the connection. |
| * |
| * @param endPoint The end point of the connection. |
| * |
| * @since 2.0 |
| */ |
| private double calculateTan(Point startPoint, Point endPoint) { |
| double tan = 0; |
| if (endPoint.x == startPoint.x) |
| tan = 1.0; |
| else |
| tan = (double) (endPoint.y - startPoint.y) |
| / (double) (endPoint.x - startPoint.x); |
| if (tan > 1) |
| tan = 1.0; |
| else if (tan < -1) |
| tan = -1.0; |
| |
| return tan; |
| } |
| |
| private int calculateYShift(int figureWidth, int figureHeight) { |
| int yShift = 0; |
| if (vDistance < 0) |
| yShift = -figureHeight; |
| else if (vDistance == 0) |
| yShift = -figureHeight / 2; |
| return yShift; |
| } |
| |
| private Connection getConnection() { |
| return conn; |
| } |
| |
| private IFigure getConnectionOwner() { |
| IFigure connOwner; |
| if (isEnd()) |
| connOwner = conn.getTargetAnchor().getOwner(); |
| else |
| connOwner = conn.getSourceAnchor().getOwner(); |
| |
| return connOwner; |
| } |
| |
| /** |
| * Returns the distance in pixels from the anchor's owner. |
| * |
| * @return the offset distance from the endpoint figure |
| */ |
| public int getUDistance() { |
| return uDistance; |
| } |
| |
| /** |
| * Returns the distance in pixels from the connection |
| * |
| * @return the offset from the connection itself |
| */ |
| public int getVDistance() { |
| return vDistance; |
| } |
| |
| private boolean isEnd() { |
| return end; |
| } |
| |
| /** |
| * Relocates the given IFigure at either the source or target end of the |
| * Connection, based on the <code>boolean</code> given in the constructor |
| * {@link #ConnectionEndpointLocator(Connection, boolean)}. |
| * |
| * @param figure |
| * The figure to relocate |
| */ |
| public void relocate(IFigure figure) { |
| Connection conn = getConnection(); |
| Point startPoint = Point.SINGLETON; |
| Point endPoint = new Point(); |
| |
| int startPointPosition = 0; |
| int endPointPosition = 1; |
| if (isEnd()) { |
| startPointPosition = conn.getPoints().size() - 1; |
| endPointPosition = startPointPosition - 1; |
| } |
| |
| conn.getPoints().getPoint(startPoint, startPointPosition); |
| conn.getPoints().getPoint(endPoint, endPointPosition); |
| |
| IFigure connOwner = getConnectionOwner(); |
| |
| int quadrant; |
| if (connOwner != null) { |
| Rectangle connOwnerBounds = connOwner.getBounds(); |
| Point connOwnerCenter = connOwnerBounds.getCenter(); |
| Point connOwnerTL = connOwnerBounds.getTopLeft(); |
| quadrant = calculateConnectionLocation(startPoint, connOwnerTL, |
| connOwnerCenter); |
| } else |
| quadrant = calculateConnectionLocation(startPoint, endPoint); |
| |
| int cos = 1; |
| transposer.setEnabled(false); |
| |
| /* |
| * Label placement calculations are done as if the connection point is |
| * along the left or right side of the figure. If the connection point |
| * is along the top or bottom, values are transposed. |
| */ |
| if (quadrant == 1 || quadrant == 3) |
| transposer.setEnabled(true); |
| |
| if (quadrant == 3 || quadrant == 4) |
| cos = -1; |
| |
| Dimension figureSize = transposer.t(figure.getPreferredSize()); |
| startPoint = transposer.t(startPoint); |
| endPoint = transposer.t(endPoint); |
| |
| double tan = calculateTan(startPoint, endPoint); |
| |
| int figureWidth = figureSize.width; |
| int figureHeight = figureSize.height; |
| int yShift = calculateYShift(figureWidth, figureHeight); |
| |
| Point figurePoint = new Point(startPoint.x + (uDistance * cos) |
| + figureWidth * ((cos - 1) / 2), (int) (startPoint.y + cos |
| * uDistance * tan + vDistance + yShift)); |
| |
| figureBounds.setSize(transposer.t(figureSize)); |
| figureBounds.setLocation(transposer.t(figurePoint)); |
| figure.setBounds(figureBounds); |
| } |
| |
| /** |
| * Sets the distance in pixels from the Connection's owner. |
| * |
| * @param distance |
| * Number of pixels to place the ConnectionEndpointLocator from |
| * its owner. |
| * @since 2.0 |
| */ |
| public void setUDistance(int distance) { |
| uDistance = distance; |
| } |
| |
| /** |
| * Sets the distance in pixels from the Connection. |
| * |
| * @param distance |
| * Number of pixels to place the ConnectionEndpointLocator from |
| * its Connection. |
| * @since 2.0 |
| */ |
| public void setVDistance(int distance) { |
| vDistance = distance; |
| } |
| |
| } |