Mercurial > projects > dwt-addons
view 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 source
/******************************************************************************* * 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; } }