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