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