import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; /** * Class RectDrawingListener 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 draw rectangles. *

* The general drawing strategy is to add and remove rectangles from the * canvas shapeList as the mouse is being dragged, repainting the canvas at * each addition. Since repainting is done efficiently by Java, this * technique is visually OK even if the canvas shapeList contains a large * number of other rectangles to be drawn. */ public class RectDrawingListener 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; /** True if the user is moving the mouse. */ private boolean moving = false; public RectDrawingListener(DrawingCanvas canvas, WorkSpace workSpace) { this.canvas = canvas; this.workSpace = workSpace; } /** * Record the initial mouse press as the starting point of the * rectangle to be drawn. Add a single-point rectangle to the * shapeList to start off the add/remove drawing process. In this way, * mouseDragged will do a remove first, then add a new rect. */ public void mousePressed(MouseEvent e) { Shape selection = workSpace.getSelection(); if (selection != null) { selection.selected = false; } int ch = canvas.getHeight(); startX = e.getX(); startY = e.getY(); nStartY = ch - startY; // System.out.println("startX=" + startX + ", startY=" + startY); workSpace.add(new Rectangle(0, 0, new Point(startX, nStartY), Color.BLACK, false)); moving = true; } /** * Remove the previously drawn rect and add a new one that extends from * the starting point to the current mouse position. Then call * canvas.repaint, which will efficiently redraw the entire canvas, * including all of the other items in the shapeList. */ 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()); workSpace.remove(workSpace.size() - 1); workSpace.add(new Rectangle( width >= 0 ? width : -width, height >= 0 ? height : -height, new Point( width >= 0 ? startX : x, height >= 0 ? nStartY : ny), Color.BLACK, false)); canvas.repaint(); /* * The following might look like an alternative implementation, * however it produces a smearing effect, since rects drawn in * previous invocations of mouseDragged are not erased. * g2.drawRect( startX, startY, e.getX() - startX, e.getY() - startY); * */ } /** * Remove the previously drawn rect and add a new rect in its final * position. Then call repaint. */ public void mouseReleased(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; Rectangle rect; workSpace.remove(workSpace.size() - 1); workSpace.add(rect = new Rectangle( width >= 0 ? width : -width, height >= 0 ? height : -height, new Point( width >= 0 ? startX : x, height >= 0 ? nStartY : ny), Color.BLACK, false)); // System.out.println(x + "," + y + "," + width + "," + height); moving = false; rect.selected = true; workSpace.setSelection(rect); canvas.repaint(); } }