import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; /** * Class PolyDrawingListener 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 PolyDrawingListener extends MouseInputAdapter { /** The drawing canvas */ private DrawingCanvas canvas; /** The shared model workspace */ 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; /** True if we're in the midst of drawing a polygon, false if not. This * tells the move/drag event handler whether or not to draw a tracking * polygon. */ private boolean drawing = false; /** The polygonc being drawn */ ConvexPolygon poly; /** The index of the current last vertex */ int n = -1; public PolyDrawingListener(DrawingCanvas canvas, WorkSpace workSpace) { this.canvas = canvas; this.workSpace = workSpace; } /** * Record the initial mouse press as the starting point of the polygon to * be drawn. Subsequent drags (or moves) without an interveing press will * replace the last vertex with the moved-to mouse position, thereby * dynamically tracking the mouse movement. Each subsequent left click * will add a new vertex, and then continue to process. A right click * finishes things off. */ public void mousePressed(MouseEvent e) { Shape selection // The curren wksp selection = workSpace.getSelection(); Point vn = new Point(); // The next new vertex to add int mouseButton = e.getButton(); // Which button was pressed /* * Unselect the current workspace selection, if there is one. */ if (selection != null) { selection.selected = false; } /* * Mouse button 1 is the left, which means we add a new vertex. */ if (mouseButton == 1) { leftMousePressed(e); } /* * Mouse button 2 (or any other) is the right (or taken to be the * right), which means we stop creating and add a new permanent shape * to the workspace. */ else { rightMousePressed(e); } } /** * If we're just starting to draw, create a new 1-point polygon. Whether * staring or continuinng, add another new point. */ private void leftMousePressed(MouseEvent e) { int ch = canvas.getHeight(); int x = e.getX(); int y = e.getY(); int ny = ch - y; int i; // System.out.println("startX=" + startX + ", startY=" + startY); if (! drawing) { Point[] p0 = {new Point(x, ny)}; workSpace.add(new ConvexPolygon(p0, Color.BLACK, false)); } i = workSpace.size() - 1; ((ConvexPolygon) workSpace.get(i)).addVertex(new Point(x, ny)); drawing = true; } private void rightMousePressed(MouseEvent e) { /* * Make sure drawing has started before a right click happens after * drawing has started. If not, just ignore the right click. */ if (drawing) { ConvexPolygon p = (ConvexPolygon) workSpace.get( workSpace.size() - 1); workSpace.setSelection(p); p.selected = true; drawing = false; canvas.repaint(); } } /** None operational variable messaging whether there's a move or a drag. * True if move, false if drag. */ boolean movingOrDragging = true; /** * * Remove the previously drawn polygon and add a new one that has the last * (current) vertex at 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 mouseMovedOrDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); int ch = canvas.getHeight(); int ny = ch - y; int n = workSpace.size() - 1; Shape s = workSpace.get(n); ConvexPolygon p; if (drawing && (s instanceof ConvexPolygon)) { p = (ConvexPolygon) s; if (drawing) { p.setVertex(p.numVertices() - 1, new Point(x, ny)); canvas.repaint(); } } /* System.out.println( "Mouse " + (movingOrDragging ? "moved" : "dragged") + " in panel at " + e.getX() + "," + e.getY()); int[] xsn = new int[xs.length]; int[] ysn = new int[ys.length]; for (int i = 0; i < xs.length; i++) { xsn[i] = xs[i] + startX; ysn[i] = ys[i] + startY; } 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.drawPoly( startX, startY, e.getX() - startX, e.getY() - startY); * */ } /** * Do the same thing for a mouse move as for a drag. */ public void mouseMoved(MouseEvent e) { movingOrDragging = true; mouseMovedOrDragged(e); } /** * Do the same thing for a mouse drag as for a move. */ public void mouseDragged(MouseEvent e) { movingOrDragging = false; mouseMovedOrDragged(e); } /** * 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(); } }