//======================================================================//  PROJECT:            _programming.java_//  FILE:               SketchPad.java//  PURPOSE:            Chapter 6 lablet, second of two//  VERSION:            2.1//  TARGET:             Java v1.1//  UPDATE HISTORY:     2.1     10/15/98   minor tidying up//                      2.0     4/21/98    1.1 event model, member classes//                      1.1     6/29/97    tidied up//                      1.0     8/22/96    the version in _p.j_//======================================================================//------------------------------- NOTES --------------------------------/*    This applet provides the user with a simple sketch pad for drawing.    Drawing is accomplished by clicking and dragging the mouse, or by    using the arrow keys.        In this sample we demonstrate three different ways of handling     events in the Java 1.1 model:    1. Having the applet implement a listener interface (which we do for       the ActionEvent triggered by the Clear button, for the ItemEvent       triggered by one of the checkboxes, and for the KeyEvents triggered       by pressing one of the arrow keys.    2. Using an auxiliary class that extends an adapter (which we do       with the ClickPoint class that responds to mouse events).    3. Using a "member class" to extend an adapter (which we do       to handle MouseDragged events). *///------------------------------ IMPORTS -------------------------------import java.awt.*;import java.awt.event.*;import java.applet.*; //========================== SketchPad CLASS ===========================/** * There are five categories of events we need to handle here.  We make * the applet itself a listener for three of them, we use an auxiliary * class for mouse clicks, and an internal class for mouse motion. */public class SketchPad extends    Applet                       implements ActionListener,   // for the button click                                  ItemListener,     // for the checkboxes                                  KeyListener       // for the arrow keys{    private Button       clear;                          // to clear the drawing    private Checkbox     color1, color2, color3, color4; // to set drawing color        // As much as we'd like to, we can't give endPoint private access.    // An inner class (like Dragger) should have access to all the members    // of the enclosing class, but a common compiler bug won't let us get    // to the private members.            Point        endPoint;      // end point for each line segment                private ClickPoint   startPoint;    // start point for each line segment    private final Point  DEFAULT_POINT = new Point(5, 25); // where we start        private Color        currentColor;  // drawing color        //------------------- The Usual Applet METHODS ---------------------    public void init()    {        setLayout(new BorderLayout());        setBackground(Color.white);                // Initialize the start and end points to just inside the        // upper left corner of the drawing region.        startPoint = new ClickPoint(DEFAULT_POINT);        endPoint = new Point(DEFAULT_POINT);                clear = new Button("Clear");        add("North", clear);                // Set up the control panel to hold the color checkboxes        Panel colorControls = new Panel();        colorControls.setBackground(Color.lightGray);                CheckboxGroup drawingColors = new CheckboxGroup();        color1 = new Checkbox("Red", drawingColors, false);        colorControls.add(color1);                color2 = new Checkbox("Green", drawingColors, false);        colorControls.add(color2);                color3 = new Checkbox("Blue", drawingColors, false);        colorControls.add(color3);                color4 = new Checkbox("Black", drawingColors, true);        colorControls.add(color4);                currentColor = Color.black;        add("South", colorControls);                // Here we add the event listeners we mentioned in part (1)        // of the notes.  In each of these, the applet itself is the        // listener for the event, so we use "this" as the argument.        // In the last of these, we say this.addActionListener(this)        // instead of just addActionListener(this), to emphasize that        // the applet itself is the source of the key events.                clear.addActionListener(this);        color1.addItemListener(this);        color2.addItemListener(this);        color3.addItemListener(this);        color4.addItemListener(this);        this.addKeyListener(this);                // Now we register the applet as the source of the mouse events        // that will be handled by our ClickPoint object, startPoint        // (see note 2).                this.addMouseListener(startPoint);                // Finally, register the applet as the source of mouse motion        // events that will be handled by an unnamed instance of our        // member class, Dragger (see note 3).                this.addMouseMotionListener(new Dragger());     }        /**     * A call to repaint() causes a call to update(), which normally     * erases the frame and then calls paint().  We don't want to clobber     * what we've already drawn, so we override update() to make sure that     * it doesn't do any erasing.     */     public void update(Graphics g)    {        paint(g);    }    /**     * In response to a call to repaint...update, we draw the newest line     * segment and update the start point so that the next segment picks     * up where this one left off.     */    public void paint(Graphics g)    {        g.setColor(currentColor);        g.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);                startPoint.setLocation(endPoint);    }        //-------------------- ActionListener METHOD -----------------------        /**     * Here, we clear the sketch pad by painting over the entire applet     * frame in the white background color.     * <BR>     * Since there's only one possible source for an ActionEvent in     * this applet (namely, the clear button), we don't bother checking the     * source of this event.     */    public void actionPerformed(ActionEvent e)    {    	Dimension d = getSize();        Graphics g = getGraphics();        g.setColor(Color.white);        g.fillRect(0, 0, d.width, d.height);                startPoint.setLocation(DEFAULT_POINT);        endPoint.setLocation(DEFAULT_POINT);                requestFocus();    }        //--------------------- ItemListener METHOD ------------------------        /**     * Respond to a click in any of the four color checkboxes.  Unlike     * the situation in the actionPerformed() method above, we do need     * to check the source of the event.  We do it here by calling getItem()     * to return the name of the checkbox, but we could equally well have      * used a call to getSource() and matched it against the checkboxes     * themselves.     */    public void itemStateChanged(ItemEvent e)    {        String boxName = "" + e.getItem();        if (boxName.equals("Red"))        {            currentColor = Color.red;        }        else if (boxName.equals("Green"))        {            currentColor = Color.green;        }        else if (boxName.equals("Blue"))        {            currentColor = Color.blue;        }        else        {            currentColor = Color.black;        }                requestFocus();    }        //--------------------- KeyListener METHODS ------------------------        /**     * There are three methods we have to implement for the KeyListener     * interface.  Only one, keyPressed(), is of any interest to us here,     * but the interface requires that we implement the other two, which     * we do by giving them empty bodies.     * <BR>     * This is somewhat wasteful, and we do things the "hard way" just     * to underscore the point that implementing an interface requires     * that we implement *all* of its methods.  It would have been better     * to make a new adapter class (Note 1) or use an inner class adapter     * (Note 3).     */    public void keyPressed(KeyEvent e)    {        endPoint.x = startPoint.x;        endPoint.y = startPoint.y;                // Now change the end point based on which key was pressed        switch (e.getKeyCode())        {        case KeyEvent.VK_LEFT:            endPoint.x -= 5;  break;        case KeyEvent.VK_RIGHT:            endPoint.x += 5;  break;        case KeyEvent.VK_UP:            endPoint.y -= 5;  break;        case KeyEvent.VK_DOWN:            endPoint.y += 5;  break;        default:            return;     // Ignore presses on any other keys.        }        repaint();    }        /*        Ignore these two varieties of KeyEvents.    */    public void keyTyped(KeyEvent e)    { }        public void keyReleased(KeyEvent e)    { }        //--------------------- Dragger MEMBER CLASS -----------------------        /**     * This is the "member class" that we use to the handle mouse motion     * events caused by dragging the mouse.  Notice that this class is     * defined *inside* the SketchPad class.  Doing so gives a Dragger     * object access to all the methods and data of the enclosing class     * (which is why we don't have to write a constructor of our own for it).     */    private class Dragger extends MouseMotionAdapter    {        public void mouseDragged(MouseEvent e)        {            endPoint.setLocation(e.getPoint());            repaint();        }    }}//========================= ClickPoint CLASS ===========================/** * A ClickPoint object stores the location of the last mouse click, which * it updates in response to a MousePressed event.  In essence, a ClickPoint * object is almost an ordinary Point, except that it changes its coordinates * whenever a mouse click occurs. * <BR> * By having this class extend MouseAdapter, we only need to implement * the mouse motion handler methods that are of use to us, rather than * having to provide empty implementations (as we did in GalaEvents). * We save a bit of empty code this way, at the expense of having to invent * a new class solely for the purpose of dealing with clicks. * <BR> * Recall (p. 257) that the MouseAdapter class automatically implements the * MouseListener interface.  We make use of this when we add an instance * of our ClickPoint class as a MouseListener in the applet's init() method. */class ClickPoint extends MouseAdapter{    public int x, y;  // These are public, like the ones in Point.        /**     * Construct a ClickPoint object with a specified initial point.     */    public ClickPoint(Point p)    {        x = p.x;        y = p.y;    }        /**     * Set the coordinates to those of the point specified in the     * argument.  Note that setLocation() is also a method of Point.     * We give our function the same name because it acts the same     * as the version in Point.     */    public void setLocation(Point p)    {        x = p.x;        y = p.y;    }        /**     * Update this object's coordinates in response to a mouse down event.     */    public void mousePressed(MouseEvent e)    {        Point p = e.getPoint();        x = p.x;        y = p.y;    }}