001 
002 
003 
004 
005 
006 
007 
008 
009 
010 
011 
012 
013 
014 
015 
016 
017 
018 
019 
020 
021 
022 
023 
024 
025 
026 
027 
028 
029 
030 
031 
032 
033 
034 
035 
036 
037 
038 
039 
040 
041 
042 
043 
044 
045 
046 
047 
048 
049 
050 
051 
052 
053 
054 
055 
056 
057 
058 
059 
060 
061 
062 
063 
064 
065 
066 
067 
068 
069 
070 
071 
072 
073 
074 
075 
076 
077 
078 
079 
080 
081 
082 
083 
084 
085 
086 
087 
088 
089 
090 
091 
092 
093 
094 
095 
096 
097 
098 
099 
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
110 
111 
112 
113 
114 
115 
116 
117 
118 
119 
120 
121 
122 
123 
124 
125 
126 
127 
128 
129 
130 
131 
132 
133 
134 
135 
136 
137 
138 
139 
140 
141 
142 
143 
144 
145 
146 
147 
148 
149 
150 
151 
152 
153 
154 
155 
156 
157 
158 
159 
160 
161 
162 
163 
164 
165 
166 
167 
168 
169 
170 
171 
172 
173 
174 
175 
176 
177 
178 
179 
180 
181 
182 
183 
184 
 | 
package horstmann.ch08_graphed;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
   A graph consisting of selectable nodes and edges.
 */
public abstract class Graph implements Serializable
{
  private static final long serialVersionUID = 2008L;
  /**
      Constructs a graph with no nodes or edges.
   */
  public Graph()
  {
    nodes = new ArrayList<Node>();
    edges = new ArrayList<Edge>();
  }
  /**
      Adds an edge to the graph that joins the nodes containing
      the given points. If the points aren't both inside nodes,
      then no edge is added.
      @param e the edge to add
      @param p1 a point in the starting node
      @param p2 a point in the ending node
   */
  public boolean connect(Edge e, Point2D p1, Point2D p2)
  {
    Node n1 = findNode(p1);
    Node n2 = findNode(p2);
    if (n1 != null && n2 != null)
    {
      e.connect(n1, n2);
      edges.add(e);
      return true;
    }
    return false;
  }
  /**
      Adds a node to the graph so that the top left corner of
      the bounding rectangle is at the given point.
      @param n the node to add
      @param p the desired location
   */
  public boolean add(Node n, Point2D p)
  {
    Rectangle2D bounds = n.getBounds();
    n.translate(p.getX() - bounds.getX(),
        p.getY() - bounds.getY());
    nodes.add(n);
    return true;
  }
  /**
      Finds a node containing the given point.
      @param p a point
      @return a node containing p or null if no nodes contain p
   */
  public Node findNode(Point2D p)
  {
    for (int i = nodes.size() - 1; i >= 0; i--)
    {
      Node n = nodes.get(i);
      if (n.contains(p)) return n;
    }
    return null;
  }
  /**
      Finds an edge containing the given point.
      @param p a point
      @return an edge containing p or null if no edges contain p
   */
  public Edge findEdge(Point2D p)
  {
    for (int i = edges.size() - 1; i >= 0; i--)
    {
      Edge e = edges.get(i);
      if (e.contains(p)) return e;
    }
    return null;
  }
  /**
      Draws the graph
      @param g2 the graphics context
   */
  public void draw(Graphics2D g2)
  {
    for (Node n : nodes)
      n.draw(g2);
    for (Edge e : edges)
      e.draw(g2);
  }
  /**
      Removes a node and all edges that start or end with that node
      @param n the node to remove
   */
  public void removeNode(Node n)
  {
    for (int i = edges.size() - 1; i >= 0; i--)
    {
      Edge e = edges.get(i);
      if (e.getStart() == n || e.getEnd() == n)
        edges.remove(e);
    }
    nodes.remove(n);
  }
  /**
      Removes an edge from the graph.
      @param e the edge to remove
   */
  public void removeEdge(Edge e)
  {
    edges.remove(e);
  }
  /**
      Gets the smallest rectangle enclosing the graph
      @param g2 the graphics context
      @return the bounding rectangle
   */
  public Rectangle2D getBounds(Graphics2D g2)
  {
    Rectangle2D r = null;
    for (Node n : nodes)
    {
      Rectangle2D b = n.getBounds();
      if (r == null) r = b;
      else r.add(b);
    }
    for (Edge e : edges)
      r.add(e.getBounds(g2));
    return r == null ? new Rectangle2D.Double() : r;
  }
  /**
      Gets the node types of a particular graph type.
      @return an array of node prototypes
   */
  public abstract Node[] getNodePrototypes();
  /**
      Gets the edge types of a particular graph type.
      @return an array of edge prototypes
   */
  public abstract Edge[] getEdgePrototypes();
  /**
      Gets the nodes of this graph.
      @return an unmodifiable list of the nodes
   */
  public List<Node> getNodes()
  {
    return Collections.unmodifiableList(nodes); }
  /**
      Gets the edges of this graph.
      @return an unmodifiable list of the edges
   */
  public List<Edge> getEdges()
  {
    return Collections.unmodifiableList(edges);
  }
  private ArrayList<Node> nodes;
  private ArrayList<Edge> edges;
}
 |