package graph; import graph.animation.*; import graph.rep.*; import java.util.Vector; import java.util.Enumeration; import java.awt.Graphics; import java.awt.Color; /** * An efficient Java implementation of a node in a graph. * Each node is contained by a graph, has a vector of its * incoming and outgoing edges, a position and dimension, * and a dynamically growable array of attributes * (see AttributeManager) and a reference to its * graphical representation.

* * A typical usage: *

 *    Graph g = new Graph();
 *    Node a = new Node(10, 10);
 *    Node b = new Node(20, 30);
 *    Edge e = a.attach(b); //create an edge a->b
 *    e.weight = 2;
 *    g.add(a);
 *    g.add(b);
 * 
* * @see Graph * @see Edge * @see NodeRep * @see AttributeManager * @author Michael Shilman (michaels@eecs.berkeley.edu) * @version $Id$ */ public class Node extends Element implements Cloneable { /** * The default node width */ public static final int DEFAULT_WIDTH = 6; /** * The default node height */ public static final int DEFAULT_HEIGHT = DEFAULT_WIDTH; /** * The size of the hierarchical reference frame. */ public static final double FRAME = 1000.0; /** * An array of node attributes. * * @see AttributeManager */ public Object attrs[] = null; /** * The graphical representation of the node. */ public NodeRep rep = new NodeRep();//XXX /** * The graphical representation of the label of the node. */ public LabelRep lbl = new LabelRep();//XXX /** * The name of the node. */ public String name = null; /** * The X position coordinate. */ public double x = 0; /** * The Y position coordinate. */ public double y = 0; /** * The width of the node. */ public double w = DEFAULT_WIDTH; /** * The height of the node. */ public double h = DEFAULT_HEIGHT; /** * The graph to which this node belongs. */ public Graph parent = null; /** * The edges into this node. */ public Vector in = new Vector(); /** * The edges out of this node. */ public Vector out = new Vector(); /** * Create a completely empty node. */ public Node() { super(); } /** * Create a completely empty node at the specified position. */ public Node(double x, double y) { this.x = x; this.y = y; } /** * Create a completely empty node in the specified bouding * box. */ public Node(double x, double y, double w, double h) { this.x = x; this.y = y; this.w = w; this.h = h; } /** * Attach this node to another one, making it the 'tail' node * on the edge. NOTE: for now a node can have up to a maximum * of MAX_EDGE incoming and MAX_EDGE outgoing edges. Also, * nodes cannot yet attach to themselves. */ public Edge attach(Node n) throws GraphException { if(!this.equals(n)) { Edge e = new Edge(this, n); out.addElement(e); n.in.addElement(e); if(!e.head.in.contains(e)) { System.out.println("ERROR HEAD!"); System.exit(0); } if(!e.tail.out.contains(e)) { System.out.println("ERROR TAIL!"); System.exit(0); } //TESTING //System.out.println("HEAD " + n.in.size()); //System.out.println("TAIL " + out.size()); return e; } return null; //else skip it (XXX) } // public boolean equals(Node n) { // //return name.equals(n.name); -- check for null? // //XXX && parent.equals(n.parent) // return super.equals(n); // } /** * Paint all the edges in this node. Edges must be * painted first, before the node, so that * the display looks like what people expect to see * (with the node on top). * * @param g The graphics context. */ public void paintEdges(Graphics g) { for(int i = 0; i < out.size(); i++) { ((Edge)out.elementAt(i)).paint(g); } } /** * Paint this node. * * @param g The graphics context. * @see NodeRep * @see LabelRep */ public void paint(Graphics g) { //System.out.println(">>>> PAINT: " + name + ", " + // x + ", " + y + ", " + // w + ", " + h ); if(rep != null) { rep.paint(g,x,y,w,h); } if(lbl != null) { lbl.paint(g,x,y-w/4); } } /** * Paint this node. * * @param g The graphics context. * @see NodeRep * @see LabelRep */ public void paint(Graphics g, double px, double py, double pw, double ph) { double wx = px+(x*pw/FRAME); double wy = py+(y*ph/FRAME); double ww = w*pw/FRAME; double wh = h*ph/FRAME; //System.out.println(">>>> PAINT: " + name + ", " + // x + ", " + y + ", " + // w + ", " + h ); if(rep != null) { rep.paint(g,wx,wy,ww,wh); } if(lbl != null) { lbl.paint(g,wx,wy); } } }