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: }