1: import java.awt.*;
2: import java.awt.geom.*;
3: import java.io.*;
4: import java.util.*;
5: import java.util.List;
7: /**
8: A graph consisting of selectable nodes and edges.
9: */
10: public abstract class Graph implements Serializable
11: {
12: /**
13: Constructs a graph with no nodes or edges.
14: */
15: public Graph()
16: {
17: nodes = new ArrayList<Node>();
18: edges = new ArrayList<Edge>();
19: }
21: /**
22: Adds an edge to the graph that joins the nodes containing
23: the given points. If the points aren't both inside nodes,
24: then no edge is added.
25: @param e the edge to add
26: @param p1 a point in the starting node
27: @param p2 a point in the ending node
28: */
29: public boolean connect(Edge e, Point2D p1, Point2D p2)
30: {
31: Node n1 = findNode(p1);
32: Node n2 = findNode(p2);
33: if (n1 != null && n2 != null)
34: {
35: e.connect(n1, n2);
36: edges.add(e);
37: return true;
38: }
39: return false;
40: }
42: /**
43: Adds a node to the graph so that the top left corner of
44: the bounding rectangle is at the given point.
45: @param n the node to add
46: @param p the desired location
47: */
48: public boolean add(Node n, Point2D p)
49: {
50: Rectangle2D bounds = n.getBounds();
51: n.translate(p.getX() - bounds.getX(),
52: p.getY() - bounds.getY());
53: nodes.add(n);
54: return true;
55: }
57: /**
58: Finds a node containing the given point.
59: @param p a point
60: @return a node containing p or null if no nodes contain p
61: */
62: public Node findNode(Point2D p)
63: {
64: for (int i = nodes.size() - 1; i >= 0; i--)
65: {
66: Node n = nodes.get(i);
67: if (n.contains(p)) return n;
68: }
69: return null;
70: }
72: /**
73: Finds an edge containing the given point.
74: @param p a point
75: @return an edge containing p or null if no edges contain p
76: */
77: public Edge findEdge(Point2D p)
78: {
79: for (int i = edges.size() - 1; i >= 0; i--)
80: {
81: Edge e = edges.get(i);
82: if (e.contains(p)) return e;
83: }
84: return null;
85: }
87: /**
88: Draws the graph
89: @param g2 the graphics context
90: */
91: public void draw(Graphics2D g2)
92: {
93: for (Node n : nodes)
94: n.draw(g2);
96: for (Edge e : edges)
97: e.draw(g2);
99: }
101: /**
102: Removes a node and all edges that start or end with that node
103: @param n the node to remove
104: */
105: public void removeNode(Node n)
106: {
107: for (int i = edges.size() - 1; i >= 0; i--)
108: {
109: Edge e = edges.get(i);
110: if (e.getStart() == n || e.getEnd() == n)
111: edges.remove(e);
112: }
113: nodes.remove(n);
114: }
116: /**
117: Removes an edge from the graph.
118: @param e the edge to remove
119: */
120: public void removeEdge(Edge e)
121: {
122: edges.remove(e);
123: }
125: /**
126: Gets the smallest rectangle enclosing the graph
127: @param g2 the graphics context
128: @return the bounding rectangle
129: */
130: public Rectangle2D getBounds(Graphics2D g2)
131: {
132: Rectangle2D r = null;
133: for (Node n : nodes)
134: {
135: Rectangle2D b = n.getBounds();
136: if (r == null) r = b;
137: else r.add(b);
138: }
139: for (Edge e : edges)
140: r.add(e.getBounds(g2));
141: return r == null ? new Rectangle2D.Double() : r;
142: }
144: /**
145: Gets the node types of a particular graph type.
146: @return an array of node prototypes
147: */
148: public abstract Node[] getNodePrototypes();
150: /**
151: Gets the edge types of a particular graph type.
152: @return an array of edge prototypes
153: */
154: public abstract Edge[] getEdgePrototypes();
156: /**
157: Gets the nodes of this graph.
158: @return an unmodifiable list of the nodes
159: */
160: public List<Node> getNodes()
161: {
162: return Collections.unmodifiableList(nodes); }
164: /**
165: Gets the edges of this graph.
166: @return an unmodifiable list of the edges
167: */
168: public List<Edge> getEdges()
169: {
170: return Collections.unmodifiableList(edges);
171: }
173: private ArrayList<Node> nodes;
174: private ArrayList<Edge> edges;
175: }