Refactored implementation.

COMPONENT JAVA
Rubber-Banding and Object-Oriented Design

Vince Huston
Listing 2. Refactored implementation.


 // Purpose.  OO rubber-band design (no: case stmt,
 // state attribute, protected)

 import java.awt.*;
 import java.awt.event.*;
 
 public class RubberBandBetter extends Canvas
                 implements MouseListener, MouseMotionListener {
    abstract class Element {
       private int xo, yo, xe, ye;
       public Element( int x, int y ) {
          xo = xe = x;   yo = ye = y;
       }
       public void move( int x, int y ) {
          Graphics g = getGraphics();
          g.setXORMode( getBackground() );
          drawDerived( g, xo, yo, xe, ye );   // undraw prev artifact
          xe = x;  ye = y;
          drawDerived( g, xo, yo, xe, ye );   // draw current artifact
          g.dispose();
       }
       public void draw( Graphics g ) {
          drawDerived( g, xo, yo, xe, ye );
       }
       public abstract void drawDerived( Graphics g, int a, int b,
                                                     int x, int y);
    }

    class Line extends Element {
       public Line( int x, int y ) { super( x, y ); }
       public void drawDerived( Graphics g, int a, int b, int x, int y ) {
          g.drawLine( a, b, x, y );
    }  }

    class Rectangle extends Element {
       public Rectangle( int x, int y ) { super( x, y ); }
       public void drawDerived( Graphics g, int a, int b, int x, int y ) {
          g.drawRect( Math.min(a,x), Math.min(b,y),
                                     Math.abs(x-a), Math.abs(y-b) );
    }  }

    class Circle extends Element {
       public Circle( int x, int y ) { super( x, y ); }
       public void drawDerived( Graphics g, int a, int b, int x, int y ) {
          g.drawOval( Math.min(a,x), Math.min(b,y),
                                     Math.abs(x-a), Math.abs(y-b) );
    }  }

    private int       total = 0;
    private Element[] drawingList = new Element[30];
 
   public RubberBandBetter() {
       Frame f = new Frame( "GraphicsDemos" );
       f.add( this );  f.setSize( 300, 300 );  f.setVisible( true );
       addMouseListener( this );
       addMouseMotionListener( this );
    }

    public void mouseEntered( MouseEvent e ) { }
    public void mouseExited( MouseEvent e ) { }
    public void mouseClicked( MouseEvent e ) { }
    public void mouseReleased( MouseEvent e ) { }
    public void mousePressed( MouseEvent e ) {
       if ((e.getModifiers() & InputEvent.CTRL_MASK) ==
                                             InputEvent.CTRL_MASK)
          drawingList[total++] = new Circle( e.getX(), e.getY() );
       else if ((e.getModifiers() & InputEvent.BUTTON3_MASK)
                                       == InputEvent.BUTTON3_MASK)
          drawingList[total++] = new Rectangle( e.getX(), e.getY() );
       else
          drawingList[total++] = new Line( e.getX(), e.getY() );
    }

    // MouseMotionListener: btn up
    public void mouseMoved(MouseEvent e) { }
    // MouseMotionListener: btn down
    public void mouseDragged(MouseEvent e) {
        drawingList[total-1].move( e.getX(), e.getY() );
    }

    public void paint( Graphics g ) {
       for (int i=0; i < total; i++) drawingList[i].draw( g );
    }
    public static void main( String[] args ) {
       new RubberBandBetter();
 }  }