001: import java.awt.*;
002: import java.awt.geom.*;
003: import java.awt.event.*;
004: import javax.swing.*;
005: import javax.swing.event.*;
006:
007: /**
008: A panel to draw a graph
009: */
010: public class GraphPanel extends JPanel
011: {
012: /**
013: Constructs a graph.
014: @param aToolBar the tool bar with the node and edge tools
015: @param aGraph the graph to be displayed and edited
016: */
017: public GraphPanel(ToolBar aToolBar, Graph aGraph)
018: {
019: toolBar = aToolBar;
020: graph = aGraph;
021: setBackground(Color.WHITE);
022:
023: addMouseListener(new
024: MouseAdapter()
025: {
026: public void mousePressed(MouseEvent event)
027: {
028: Point2D mousePoint = event.getPoint();
029: Node n = graph.findNode(mousePoint);
030: Edge e = graph.findEdge(mousePoint);
031: Object tool = toolBar.getSelectedTool();
032: if (tool == null) // select
033: {
034: if (e != null)
035: {
036: selected = e;
037: }
038: else if (n != null)
039: {
040: selected = n;
041: dragStartPoint = mousePoint;
042: dragStartBounds = n.getBounds();
043: }
044: else
045: {
046: selected = null;
047: }
048: }
049: else if (tool instanceof Node)
050: {
051: Node prototype = (Node) tool;
052: Node newNode = (Node) prototype.clone();
053: boolean added = graph.add(newNode, mousePoint);
054: if (added)
055: {
056: selected = newNode;
057: dragStartPoint = mousePoint;
058: dragStartBounds = newNode.getBounds();
059: }
060: else if (n != null)
061: {
062: selected = n;
063: dragStartPoint = mousePoint;
064: dragStartBounds = n.getBounds();
065: }
066: }
067: else if (tool instanceof Edge)
068: {
069: if (n != null) rubberBandStart = mousePoint;
070: }
071: lastMousePoint = mousePoint;
072: repaint();
073: }
074:
075: public void mouseReleased(MouseEvent event)
076: {
077: Object tool = toolBar.getSelectedTool();
078: if (rubberBandStart != null)
079: {
080: Point2D mousePoint = event.getPoint();
081: Edge prototype = (Edge) tool;
082: Edge newEdge = (Edge) prototype.clone();
083: if (graph.connect(newEdge,
084: rubberBandStart, mousePoint))
085: selected = newEdge;
086: }
087:
088: revalidate();
089: repaint();
090:
091: lastMousePoint = null;
092: dragStartBounds = null;
093: rubberBandStart = null;
094: }
095: });
096:
097: addMouseMotionListener(new
098: MouseMotionAdapter()
099: {
100: public void mouseDragged(MouseEvent event)
101: {
102: Point2D mousePoint = event.getPoint();
103: if (dragStartBounds != null)
104: {
105: if (selected instanceof Node)
106: {
107: Node n = (Node) selected;
108: Rectangle2D bounds = n.getBounds();
109: n.translate(
110: dragStartBounds.getX() - bounds.getX()
111: + mousePoint.getX() - dragStartPoint.getX(),
112: dragStartBounds.getY() - bounds.getY()
113: + mousePoint.getY() - dragStartPoint.getY());
114: }
115: }
116: lastMousePoint = mousePoint;
117: repaint();
118: }
119: });
120: }
121:
122: public void paintComponent(Graphics g)
123: {
124: super.paintComponent(g);
125: Graphics2D g2 = (Graphics2D) g;
126: Rectangle2D bounds = getBounds();
127: Rectangle2D graphBounds = graph.getBounds(g2);
128: graph.draw(g2);
129:
130: if (selected instanceof Node)
131: {
132: Rectangle2D grabberBounds = ((Node) selected).getBounds();
133: drawGrabber(g2, grabberBounds.getMinX(), grabberBounds.getMinY());
134: drawGrabber(g2, grabberBounds.getMinX(), grabberBounds.getMaxY());
135: drawGrabber(g2, grabberBounds.getMaxX(), grabberBounds.getMinY());
136: drawGrabber(g2, grabberBounds.getMaxX(), grabberBounds.getMaxY());
137: }
138:
139: if (selected instanceof Edge)
140: {
141: Line2D line = ((Edge) selected).getConnectionPoints();
142: drawGrabber(g2, line.getX1(), line.getY1());
143: drawGrabber(g2, line.getX2(), line.getY2());
144: }
145:
146: if (rubberBandStart != null)
147: {
148: Color oldColor = g2.getColor();
149: g2.setColor(PURPLE);
150: g2.draw(new Line2D.Double(rubberBandStart, lastMousePoint));
151: g2.setColor(oldColor);
152: }
153: }
154:
155: /**
156: Removes the selected node or edge.
157: */
158: public void removeSelected()
159: {
160: if (selected instanceof Node)
161: {
162: graph.removeNode((Node) selected);
163: }
164: else if (selected instanceof Edge)
165: {
166: graph.removeEdge((Edge) selected);
167: }
168: selected = null;
169: repaint();
170: }
171:
172: /**
173: Edits the properties of the selected graph element.
174: */
175: public void editSelected()
176: {
177: PropertySheet sheet = new PropertySheet(selected);
178: sheet.addChangeListener(new
179: ChangeListener()
180: {
181: public void stateChanged(ChangeEvent event)
182: {
183: repaint();
184: }
185: });
186: JOptionPane.showMessageDialog(null,
187: sheet,
188: "Properties",
189: JOptionPane.QUESTION_MESSAGE);
190: }
191:
192: /**
193: Draws a single "grabber", a filled square
194: @param g2 the graphics context
195: @param x the x coordinate of the center of the grabber
196: @param y the y coordinate of the center of the grabber
197: */
198: public static void drawGrabber(Graphics2D g2, double x, double y)
199: {
200: final int SIZE = 5;
201: Color oldColor = g2.getColor();
202: g2.setColor(PURPLE);
203: g2.fill(new Rectangle2D.Double(x - SIZE / 2,
204: y - SIZE / 2, SIZE, SIZE));
205: g2.setColor(oldColor);
206: }
207:
208: public Dimension getPreferredSize()
209: {
210: Rectangle2D bounds
211: = graph.getBounds((Graphics2D) getGraphics());
212: return new Dimension(
213: (int) bounds.getMaxX(),
214: (int) bounds.getMaxY());
215: }
216:
217: private Graph graph;
218: private ToolBar toolBar;
219: private Point2D lastMousePoint;
220: private Point2D rubberBandStart;
221: private Point2D dragStartPoint;
222: private Rectangle2D dragStartBounds;
223: private Object selected;
224: private static final Color PURPLE = new Color(0.7f, 0.4f, 0.7f);
225: }