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;
+}
+
+}