view dwtx/draw2d/graph/Edge.d @ 192:c3583c6ec027

Added missing default cases for switch statements
author Frank Benoit <benoit@tionex.de>
date Mon, 03 Nov 2008 22:52:26 +0100
parents 95307ad235d9
children
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2003, 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.graph.Edge;

import dwt.dwthelper.utils;

import dwtx.draw2d.geometry.Point;
import dwtx.draw2d.geometry.PointList;
import dwtx.draw2d.graph.NodeList;
import dwtx.draw2d.graph.Node;

/**
 * A directed Edge joining a source and target Node.  Edges indicate the dependencies
 * between nodes.  An Edge provides the information needed to perform a graph layout, and
 * it stores the result of the layout in its various field. Therefore, it functions
 * both as input and output.  The input data consists of:
 * <UL>
 *   <LI>{@link #source} - the source Node
 *   <LI>{@link #target} - the target Node
 *   <LI>{@link #delta} - the minimum number of rows the edge should span
 *   <LI>{@link #weight} - a hint indicating this edge's importance
 *   <LI>{@link #width} - the edge's width
 *   <LI>{@link #padding} - the amount of space to leave on either side of the edge
 *   <LI>[{@link #offsetSource}] - the edge's attachment point at the source node
 *   <LI>[{@link #offsetTarget}] - the edge's attachment point at the target node
 * </UL>
 * <P>The output of a layout consists of bending longer edges, and potentially inverting
 * edges to remove cycles in the graph.  The output consists of:
 * <UL>
 *   <LI>{@link #vNodes} - the virtual nodes (if any) which make up the bendpoints
 *   <LI>{@link #isFeedback} - <code>true</code> if the edge points backwards
 * </UL>
 *
 * @author hudsonr
 * @since 2.1.2
 */
public class Edge {

int cut;

/**
 * An arbitrary data field for use by clients.
 */
public Object data;

/**
 * The minimum rank separation between the source and target nodes. The default value is
 * 1.
 * @deprecated use accessors instead
 */
public int delta = 1;

/**
 * The ending point.
 * @deprecated use {@link #getPoints()}
 */
public Point end;

bool flag;

/**
 * @deprecated INTERNAL field, use accessor method
 * Indicates an edge was inverted during the layout
 */
public bool isFeedback_ = false;

/**
 * The edge's attachment point at the <em>source</em> node. The default value is -1, which
 * indicates that the edge should use the node's default {@link Node#getOffsetOutgoing()
 * outgoing} attachment point.
 * @deprecated use accessors instead
 */
public int offsetSource = -1;

/**
 * The edge's attachment point at the <em>target</em> node. The default value is -1, which
 * indicates that the edge should use the node's default {@link Node#getOffsetIncoming()
 * incoming} attachment point.
 * @deprecated use accessors instead
 */
public int offsetTarget = -1;

/**
 * The minimum amount of space to leave on both the left and right sides of the edge.
 * @deprecated use accessors instead
 */
public int padding = 10;

private PointList points;

/**
 * The source Node.
 */
public Node source;
/**
 * The starting point.
 * @deprecated use {@link #getPoints()}
 */
public Point start;

/**
 * The target Node.
 */
public Node target;

bool tree;

/**
 * The virtual nodes used to bend edges which go across one or more ranks.  Each virtual
 * node is just a regular node which occupies some small amount of space on a row. It's
 * width is equivalent to the edge's width.  Clients can use each virtual node's location
 * (x, y, width, and height) as the way to position an edge which spans multiple rows.
 */
public NodeList vNodes;
/**
 * A hint indicating how straight and short the edge should be relative to
 * other edges in the graph. The default value is <code>1</code>.
 */
public int weight = 1;

/**
 * @deprecated use accessors instead
 */
public int width = 1;

/**
 * Constructs a new edge with the given source and target nodes.  All other fields will
 * have their default values.
 * @param source the source Node
 * @param target the target Node
 */
public this(Node source, Node target) {
    this(null, source, target);
}

/**
 * Constructs a new edge with the given source, target, delta, and weight.
 * @param source the source Node
 * @param target the target Node
 * @param delta the minimum edge span
 * @param weight the weight hint
 */
public this(Node source, Node target, int delta, int weight) {
    this(source, target);
    this.delta = delta;
    this.weight = weight;
}

/**
 * Constructs a new edge with the given data object, source, and target node.
 * @param data an arbitrary data object
 * @param source the source node
 * @param target the target node
 */
public this(Object data, Node source, Node target) {
    this.data = data;
    this.source = source;
    this.target = target;
    source.outgoing.add(this);
    target.incoming.add(this);
}

/**
 * Returns the delta value. The delta is the minimum rank separation for the edge's source
 * and target nodes.
 * @return the delta.
 * @since 3.2
 */
public int getDelta() {
    return delta;
}

/**
 * For internal use only. Returns the index of the {@link Node} (or {@link VirtualNode})
 * on this edge at the given rank.  If this edge doesn't have a node at the given rank, -1
 * is returned.
 * @param rank the rank
 * @return the edges index at the given rank
 */
int getIndexForRank(int rank) {
    if (source.rank is rank)
        return source.index;
    if (target.rank is rank)
        return target.index;
    if (vNodes !is null)
        return vNodes.getNode(rank - source.rank - 1).index;
    return -1;
}

/**
 * For internal use only. Returns the target node's row minus the source node's row.
 * @return the distance from the source to target ranks
 */
public int getLength() {
    return (target.rank - source.rank);
}

public int getPadding() {
    return padding;
}

/**
 * Returns the path connecting the edge's source and target.
 * @return a point list
 * @since 3.2
 */
public PointList getPoints() {
    return points;
}

int getSlack() {
    return (target.rank - source.rank) - delta;
}

/**
 * Returns the effective source offset for this edge.  The effective source offset is
 * either the {@link #offsetSource} field, or the source node's default outgoing offset if
 * that field's value is -1.
 * @return the source offset
 */
public int getSourceOffset() {
    if (offsetSource !is -1)
        return offsetSource;
    return source.getOffsetOutgoing();
}

/**
 * Returns the effective target offset for this edge.  The effective target offset is
 * either the {@link #offsetTarget} field, or the target node's default incoming offset if
 * that field's value is -1.
 * @return the target offset
 */
public int getTargetOffset() {
    if (offsetTarget !is -1)
        return offsetTarget;
    return target.getOffsetIncoming();
}

public int getWidth() {
    return width;
}

/**
 * Swaps the source and target nodes. If any positional data has been calculated, it is
 * inverted as well to reflect the new direction.
 * @since 2.1.2
 */
public void invert() {
    source.outgoing.remove(this);
    target.incoming.remove(this);

    Node oldTarget = target;
    target = source;
    source = oldTarget;

    int temp = offsetSource;
    offsetSource = offsetTarget;
    offsetTarget = temp;

    target.incoming.add(this);
    source.outgoing.add(this);

    if (points !is null)
        points.reverse();

    if (vNodes !is null) {
        NodeList newVNodes = new NodeList();
        for (int j = vNodes.size() - 1; j >= 0; j--) {
            newVNodes.add(vNodes.getNode(j));
        }
        vNodes = newVNodes;
    }

    if (start !is null) {
        Point pt = start;
        start = end;
        end = pt;
    }
}

/**
 * Returns <code>true</code> if the edge was a feedback edge. The layout algorithm may
 * invert one or more edges to remove all cycles from the input. The set of edges that are
 * inverted are referred to as the "feedback" set.
 * @return <code>true</code> if the edge is feedback
 * @since 3.2
 */
public bool isFeedback() {
    return isFeedback_;
}

/**
 * For internal use only.  Returns the node opposite the given node on this edge.
 * @param end one end
 * @return the other end
 */
public Node opposite(Node end) {
    if (source is end)
        return target;
    return source;
}

/**
 * Sets the delta value.
 * @param delta the new delta value
 * @since 3.2
 */
public void setDelta(int delta) {
    this.delta = delta;
}

/**
 * Sets the padding for this edge.
 * @param padding the padding
 * @since 3.2
 */
public void setPadding(int padding) {
    this.padding = padding;
}

void setPoints(PointList points) {
    this.points = points;
    start = points.getFirstPoint();
    end = points.getLastPoint();
}

/**
 * Sets the source node and adds this edge to the new source's outgoing edges. If the
 * source node is previously set, removes this edge from the old source's outgoing edges.
 * @param node the new source
 * @since 3.2
 */
public void setSource(Node node) {
    if (source is node)
        return;
    if (source !is null)
        source.outgoing.remove(this);
    source = node;
    if (source !is null)
        source.outgoing.add(this);
}

public void setSourceOffset(int offset) {
    this.offsetSource = offset;
}

/**
 * Sets the target node and adds this edge to the new target's incoming edges. If the
 * target node is previously set, removes this edge from the old target's incoming edges.
 * @param node the new target
 * @since 3.2
 */
public void setTarget(Node node) {
    if (target is node)
        return;
    if (target !is null)
        target.incoming.remove(this);
    target = node;
    if (target !is null)
        target.incoming.add(this);
}

public void setTargetOffset(int offset) {
    this.offsetTarget = offset;
}

/**
 * Sets the width of the edge.
 * @param width the new width
 * @since 3.2
 */
public void setWidth(int width) {
    this.width = width;
}

}