// Purpose. Rubber-band drawing demo (less-than-OO, brute force design) import java.awt.*; import java.awt.event.*; public class RubberBandBrute extends Canvas implements MouseListener, MouseMotionListener { abstract class Element { //3 protected int xo, yo; public abstract void draw( Graphics g ); } class Line extends Element { private int xe, ye; public Line( int a, int b, int x, int y ) { xo = a; yo = b; xe = x; ye = y; } public void draw( Graphics g ) { g.drawLine( xo, yo, xe, ye ); } } class Rectangle extends Element { protected int w, h; public Rectangle( int x, int y, int ww, int hh ) { xo = x; yo = y; w = ww; h = hh; } public void draw( Graphics g ) { g.drawRect( xo, yo, w, h ); } } class Circle extends Rectangle { public Circle( int x, int y, int ww, int hh ) { super( x, y, ww, hh ); } public void draw( Graphics g ) { g.drawOval( xo, yo, w, h ); } } private int x1, y1, x2, y2, total = 0; private Element[] drawingList = new Element[30]; //2 private int currentState; private final int LINE = 1, RECT = 2, CIRC = 3; public RubberBandBrute() { Frame f = new Frame( "RubberBandBrute" ); 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 mousePressed( MouseEvent e ) { if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) currentState = CIRC; //4 else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) currentState = RECT; //4 else currentState = LINE; //4 x1 = x2 = e.getX(); y1 = y2 = e.getY(); } public void mouseReleased( MouseEvent e ) { if (currentState == LINE) //6 drawingList[total++] = new Line( x1, y1, e.getX(), e.getY() ); else if (currentState == RECT) drawingList[total++] = new Rectangle( Math.min(x1,e.getX()), Math.min(y1,e.getY()), Math.abs(e.getX()-x1), Math.abs(e.getY()-y1) ); else drawingList[total++] = new Circle( Math.min(x1,e.getX()), Math.min(y1,e.getY()), Math.abs(e.getX()-x1), Math.abs(e.getY()-y1) ); } public void mouseMoved(MouseEvent e) { } // MouseMotionListener: btn up public void mouseDragged(MouseEvent e) { // MouseMotionListener: btn down Graphics g = getGraphics(); g.setXORMode( getBackground() ); //1 if (currentState == LINE) // undraw previous position //5 g.drawLine( x1, y1, x2, y2 ); else if (currentState == RECT) g.drawRect( Math.min(x1,x2), Math.min(y1,y2), Math.abs(x2-x1), Math.abs(y2-y1) ); else g.drawOval( Math.min(x1,x2), Math.min(y1,y2), Math.abs(x2-x1), Math.abs(y2-y1) ); x2 = e.getX(); y2 = e.getY(); if (currentState == LINE) // draw current position g.drawLine( x1, y1, x2, y2 ); else if (currentState == RECT) g.drawRect( Math.min(x1,x2), Math.min(y1,y2), Math.abs(x2-x1), Math.abs(y2-y1) ); else g.drawOval( Math.min(x1,x2), Math.min(y1,y2), Math.abs(x2-x1), Math.abs(y2-y1) ); g.dispose(); } public void paint( Graphics g ) { for (int i=0; i < total; i++) drawingList[i].draw( g ); } public static void main( String[] args ) { new RubberBandBrute(); } } // 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; //12 public Element( int x, int y ) { xo = xe = x; yo = ye = y; } // move() is the TEMPLATE METHOD, drawDerived() is the placeholder public void move( int x, int y ) { //8 Graphics g = getGraphics(); g.setXORMode( getBackground() ); drawDerived( g, xo, yo, xe, ye ); // undraw previous artifact xe = x; ye = y; drawDerived( g, xo, yo, xe, ye ); // draw current artifact g.dispose(); } public void draw( Graphics g ) { //11 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), //14 Math.abs(x-a), Math.abs(y-b) ); //13 } } 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), //14 Math.abs(x-a), Math.abs(y-b) ); //13 } } // STATE design pattern - the last ele of drawingList is the current STATE private Element[] drawingList = new Element[30]; private int total = 0; public RubberBandBetter() { Frame f = new Frame( "RubberBandBetter" ); 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 ) { } // STATE design pattern - case statement gone public void mouseReleased( MouseEvent e ) { } //10 public void mousePressed( MouseEvent e ) { if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) drawingList[total++] = new Circle( e.getX(), e.getY() ); //9 else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) drawingList[total++] = new Rectangle( e.getX(), e.getY() ); //9 else drawingList[total++] = new Line( e.getX(), e.getY() ); //9 } public void mouseMoved(MouseEvent e) { } // MouseMotionListener: btn up // STATE design pattern - case statement gone public void mouseDragged(MouseEvent e) { // MouseMotionListener: btn down drawingList[total-1].move( e.getX(), e.getY() ); //7 } public void paint( Graphics g ) { for (int i=0; i < total; i++) drawingList[i].draw( g ); } public static void main( String[] args ) { new RubberBandBetter(); } }