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