Mercurial > projects > dwt-addons
diff dwtx/draw2d/ConnectionEndpointLocator.d @ 98:95307ad235d9
Added Draw2d code, still work in progress
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 03 Aug 2008 00:52:14 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/draw2d/ConnectionEndpointLocator.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,282 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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 + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.draw2d.ConnectionEndpointLocator; + +import dwt.dwthelper.utils; +import dwtx.draw2d.geometry.Dimension; +import dwtx.draw2d.geometry.Point; +import dwtx.draw2d.geometry.Rectangle; +import dwtx.draw2d.geometry.Transposer; +import dwtx.draw2d.Locator; +import dwtx.draw2d.Connection; +import dwtx.draw2d.IFigure; + +/** + * 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 + : Locator +{ + +private bool 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; + +/** + * 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 this(Connection c, bool isEnd) { + transposer = new Transposer(); + 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 is Top + * 2 is Right + * 3 is Bottom + * 4 is Left + * + * @param loc The point that is to be located + */ +private int calculateConnectionLocation(Point loc, Point topLeft, Point center) { + double m1, m2 = 0; + m1 = cast(double)(topLeft.y - center.y) / cast(double)(topLeft.x - center.x); + + if (loc.x - center.x !is 0) + m2 = cast(double)(loc.y - center.y) / cast(double)(loc.x - center.x); + + if (loc.x is 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 is Top + * 2 is Right + * 3 is Bottom + * 4 is 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 is startPoint.x) + tan = 1.0; + else + tan = cast(double)(endPoint.y - startPoint.y) + / cast(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 is 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 bool isEnd() { + return end; +} + +/** + * Relocates the given IFigure at either the source or target end of the Connection, + * based on the <code>bool</code> given in the constructor + * {@link #ConnectionEndpointLocator(Connection, bool)}. + * + * @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 !is 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 is 1 || quadrant is 3) + transposer.setEnabled(true); + + if (quadrant is 3 || quadrant is 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), + cast(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; +} + +}