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<Node>();
018:       edges = new ArrayList<Edge>();
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 = 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 = 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 (Node n : nodes)
094:          n.draw(g2);
095: 
096:       for (Edge e : edges)
097:          e.draw(g2);
098: 
099:    }
100: 
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:    }
115: 
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:    }
124: 
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:    }
143: 
144:    /**
145:       Gets the node types of a particular graph type.
146:       @return an array of node prototypes
147:    */
148:    public abstract Node[] getNodePrototypes();
149: 
150:    /**
151:       Gets the edge types of a particular graph type.
152:       @return an array of edge prototypes
153:    */
154:    public abstract Edge[] getEdgePrototypes();
155: 
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); }
163: 
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:    }
172: 
173:    private ArrayList<Node> nodes;
174:    private ArrayList<Edge> edges;
175: }
176: 
177: 
178: 
179: 
180: