Mercurial > projects > dwt-addons
diff dwtx/draw2d/graph/Node.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/graph/Node.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,332 @@ +/******************************************************************************* + * Copyright (c) 2003, 2008 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.Node; + +import dwt.dwthelper.utils; +import dwtx.dwtxhelper.Collection; +import tango.text.convert.Format; + +import dwtx.draw2d.geometry.Dimension; +import dwtx.draw2d.geometry.Insets; +import dwtx.draw2d.graph.EdgeList; +import dwtx.draw2d.graph.Subgraph; +import dwtx.draw2d.graph.Edge; + +/** + * A node in a DirectedGraph. A node has 0 or more incoming and outgoing {@link Edge}s. A + * node is given a width and height by the client. When a layout places the node in the + * graph, it will determine the node's x and y location. It may also modify the node's + * height. + * + * A node represents both the <EM>input</EM> and the <EM>output</EM> for a layout + * algorithm. The following fields are used as input to a graph layout: + * <UL> + * <LI>{@link #width} - the node's width. + * <LI>{@link #height} - the node's height. + * <LI>{@link #outgoing} - the node's outgoing edges. + * <LI>{@link #incoming} - the node's incoming edges. + * <LI>padding - the amount of space to be left around the outside of the node. + * <LI>{@link #incomingOffset} - the default attachment point for incoming edges. + * <LI>{@link #outgoingOffset} - the default attachment point for outgoing edges. + * <LI>parent - the parent subgraph containing this node. + * </UL> + * <P> + * The following fields are calculated by a graph layout and comprise the <EM>output</EM>: + * <UL> + * <LI>{@link #x} - the node's x location + * <LI>{@link #y} - the node's y location + * <LI>{@link #height} - the node's height may be stretched to match the height of other + * nodes + * </UL> + * + * @author Randy Hudson + * @since 2.1.2 + */ +public class Node { + +Node left, right; + +Object[] workingData; +int[] workingInts; + +/** + * Clients may use this field to mark the Node with an arbitrary data object. + */ +public Object data; + +//used by various graph visitors +bool flag; + +/** + * The height of this node. This value should be set prior to laying out the directed + * graph. Depending on the layout rules, a node's height may be expanded to match the + * height of other nodes around it. + */ +public int height = 40; + +/** + * @deprecated use {@link #setRowConstraint(int)} and {@link #getRowConstraint()} + */ +public int rowOrder = -1; + +/** + * The edges for which this node is the target. + */ +public EdgeList incoming; + +/** + * The default attachment point for incoming edges. <code>-1</code> indicates that the + * node's horizontal center should be used. + */ +public int incomingOffset = -1; + +// A non-decreasing number given to consecutive nodes in a Rank. +int index; + +//Used in Compound graphs to quickly determine whether a node is inside a subgraph. +int nestingIndex = -1; + +/** + * The edges for which this node is the source. + */ +public EdgeList outgoing; + +Insets padding; +private Subgraph parent; +int rank; + +/** + * @deprecated for internal use only + */ +public double sortValue; + +/** + * The node's outgoing offset attachment point. + */ +public int outgoingOffset = -1; + +/** + * The node's width. The default value is 50. + */ +public int width = 50; + +/** + * The node's x coordinate. + */ +public int x; +/** + * The node's y coordinate. + */ +public int y; + +/** + * Constructs a new node. + */ +public this() { } + +/** + * Constructs a node with the given data object + * @param data an arbitrary data object + */ +public this(Object data) { + this(data, null); +} + +/** + * Constructs a node inside the given subgraph. + * @param parent the parent subgraph + */ +public this(Subgraph parent) { + this(null, parent); +} + +/** + * Constructs a node with the given data object and parent subgraph. This node is added to + * the set of members for the parent subgraph + * @param data an arbitrary data object + * @param parent the parent subgraph or <code>null</code> + */ +public this(Object data, Subgraph parent) { + this.data = data; + this.parent = parent; + incoming = new EdgeList(); + outgoing = new EdgeList(); + workingData = new Object[3]; + workingInts = new int[4]; + if (parent !is null) + parent.addMember(this); +} + +/** + * Returns the incoming attachment point. This is the distance from the left edge to the + * default incoming attachment point for edges. Each incoming edge may have it's own + * attachment setting which takes priority over this default one. + * @return the incoming offset + */ +public int getOffsetIncoming() { + if (incomingOffset is -1) + return width / 2; + return incomingOffset; +} + +/** + * Returns the outgoing attachment point. This is the distance from the left edge to the + * default outgoing attachment point for edges. Each outgoing edge may have it's own + * attachment setting which takes priority over this default one. + * @return the outgoing offset + */ +public int getOffsetOutgoing() { + if (outgoingOffset is -1) + return width / 2; + return outgoingOffset; +} + +/** + * Returns the padding for this node or <code>null</code> if the default padding for the + * graph should be used. + * @return the padding or <code>null</code> + */ +public Insets getPadding() { + return padding; +} + +/** + * Returns the parent Subgraph or <code>null</code> if there is no parent. Subgraphs are + * only for use in {@link CompoundDirectedGraphLayout}. + * @return the parent or <code>null</code> + */ +public Subgraph getParent() { + return parent; +} + +/** + * For internal use only. Returns <code>true</code> if the given node is equal to this + * node. This method is implemented for consitency with Subgraph. + * @param node the node in question + * @return <code>true</code> if nested + */ +bool isNested(Node node) { + return node is this; +} + +/** + * Sets the padding. <code>null</code> indicates that the default padding should be used. + * @param padding an insets or <code>null</code> + */ +public void setPadding(Insets padding) { + this.padding = padding; +} + +/** + * Sets the parent subgraph. This method should not be called directly. The constructor + * will set the parent accordingly. + * @param parent the parent + */ +public void setParent(Subgraph parent) { + this.parent = parent; +} + +/** + * Sets the row sorting constraint for this node. By default, a node's constraint is + * <code>-1</code>. If two nodes have different values both >= 0, the node with the + * smaller constraint will be placed to the left of the other node. In all other cases no + * relative placement is guaranteed. + * @param value the row constraint + * @since 3.2 + */ +public void setRowConstraint(int value) { + this.rowOrder = value; +} + +/** + * Returns the row constraint for this node. + * @return the row constraint + * @since 3.2 + */ +public int getRowConstraint() { + return rowOrder; +} + +/** + * Sets the size of this node to the given dimension. + * @param size the new size + * @since 3.2 + */ +public void setSize(Dimension size) { + width = size.width; + height = size.height; +} + +/** + * @see Object#toString() + */ +public String toString() { + return Format("N({})", data ); //$NON-NLS-1$ //$NON-NLS-2$ +} + +Iterator iteratorNeighbors() { + return new class(outgoing) Iterator { + int offset; + EdgeList list; + this(EdgeList a){ + list = a; + } + public Object next() { + Edge edge = list.getEdge(offset++); + if (offset < list.size()) + return edge.opposite(this.outer); + if (list is outgoing) { + list = incoming; + offset = 0; + } else + list = null; + return edge.opposite(this.outer); + } + + public bool hasNext() { + if (list is null) + return false; + if (offset < list.size()) + return true; + if (list is outgoing) { + list = incoming; + offset = 0; + } + return offset < list.size(); + } + + public void remove() { + throw new RuntimeException("Remove not supported"); //$NON-NLS-1$ + } + }; +} + +/** + * Returns a reference to a node located left from this one + * @return <code>Node</code> on the left from this one + * @since 3.4 + */ +public Node getLeft() { + return left; +} + +/** + * Returns a reference to a node located right from this one + * @return <code>Node</code> on the right from this one + * @since 3.4 + */ +public Node getRight() { + return right; +} + +}