import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; /** * Class SelectingMovingListener extends Java's MouseInputAdpater to provide * handlers for three mouse events: mouse pressed, mouse dragged, and mouse * released. The comments for the event-handling methods describe in detail * what each method does to allow the user to select and move shapes. *
* The behavior of this listener is different than the other drawing listeners * that are associated with the drawing toolbar. In this case, the general * strategy is as follows. The press event causes the frontmost shape under * the mouse to be selected, if there is any shape there. Per the spec, "under * the mouse" means within 2 pixels of the border of an unfilled shape, or * anywhere within a filled shape (extending out 2 pixels from its border). If * there is any dragging before the release, the selected shape is moved along * the mouse track. Upon release, the shape is selected, which includes * deselecting all other shapes, and drawing the selected shape's handles. If * the is no shape under the mouse, all shapes are deselected. */ public class SelectingMovingListener extends MouseInputAdapter { private DrawingCanvas canvas; private WorkSpace workSpace; /** The starting x-axis position for drawing a shape */ private int startX; /** The starting y-axis position for drawing a shape */ private int startY; /** Quadrant-I normalized value of startY */ private int nStartY; /** Starting x,y as a point */ private Point startXY; /** True if the user is moving the mouse. */ private boolean moving = false; /** The shape that has been selected and possibly moved. */ private Shape selection; public SelectingMovingListener(DrawingCanvas canvas, WorkSpace workSpace) { this.canvas = canvas; this.workSpace = workSpace; } /** * Select the frontmost shape under the mouse location. See the class * commment for the definition of "under the mouse". */ public void mousePressed(MouseEvent e) { /* * Get the click location, and normalize y, as in all the other tools. */ startX = e.getX(); startY = e.getY(); int ch = canvas.getHeight(); nStartY = ch - startY; /* * Ask the model for the frontmost selection under the most click. */ selection = workSpace.getSelectionAt(startX, nStartY, ch); workSpace.setSelection(selection); /* * Set the moving flag to true if a shape was selected, null * otherwise. */ moving = !(selection == null); /* * Repaint. */ canvas.repaint(); } /** * This drag is fundamentally different than the other drawing listeners. * Here we get the live drag effect by a call to the Shape.move mutator, * rather than removing an old shape and adding a new one. In fact, * the implementation of mouseDragged for drawn shapes could most likely be * done this way, and this might make them more understandable. We should * look into this at some point, including changing the example for mouse * dragging. */ public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); int ch = canvas.getHeight(); int ny = ch - y; int width = x - startX; int height = y - startY; // System.out.println( // "Mouse dragged in panel at " + e.getX() + "," + e.getY()); /* * The moving flag is false if the press point was not on a shape. */ if (moving) { /* * Create the point that's the delta we want to move by. */ Point p = new Point(-(startX - x), -(nStartY - ny)); /* * Do the move. */ selection.move(p); /* * Update the start point to the point we just moved to. I this * way, we'll track properly. */ startX = x; nStartY = ny; /* * Repaint. */ canvas.repaint(); // System.out.println( // startX + " " + x + " " + nStartY + " " + " " + ny); } } /** * Here we don't need to do anything but set the moving flag to false. The * mouseDragged implementation will already have moved the selected shape * to its ending position. */ public void mouseReleased(MouseEvent e) { moving = false; } }