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: