// Purpose.  Threads - bouncing balls 

import java.awt.*;
import java.awt.event.*;

public class Bounce extends Frame {
   private Canvas canvas;

   // without  canvas.setVisible( false )  and  box.isVisible() --
   //    window disposing and exiting
   //    java.lang.NullPointerException:
   //            at Ball.move(Bounce.java:80)
   //            at Ball.run(Bounce.java:96)
   //    java.lang.NullPointerException:
   class WindowClose extends WindowAdapter {
      public void windowClosing( WindowEvent e ) {
         System.out.println( "window disposing and exiting" );
         canvas.setVisible( false );
         dispose();
         System.exit( 0 );
      }
   }
   public Bounce() {
      super( "Bounce" );
      setBounds( 50, 100, 300, 200 );
      addWindowListener( new WindowClose() );
      canvas = new Canvas();
      add( canvas, "Center" );
      Panel p = new Panel();
      addButton( p, "Start", 
         new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
               Thread t = new Ball( canvas );
               t.start();
            }
         }
      );
      addButton( p, "Exit", 
         new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
               System.out.println( "window disposing and exiting" );
               canvas.setVisible( false );
               dispose();
               System.exit( 0 );
            }
         }
      );
      add( p, "South" );
      setVisible( true );
   }
   public void addButton( Container c, String name, ActionListener a) {
      Button b = new Button( name );
      c.add( b );
      b.addActionListener( a );
   }
   public static void main( String[] args ) {
      new Bounce();
   }
}

class Ball extends Thread {
   private Canvas box;
   private static final int XSIZE = 10;
   private static final int YSIZE = 10;
   private static int num = 0;
   private int x;
   private int y = 0;
   private int dx = 2;
   private int dy = 2;
   private int i;
   private static Color[] col = {Color.red, Color.green, Color.blue,
      Color.cyan, Color.magenta, Color.yellow, Color.orange};

   public Ball( Canvas c ) {
      box = c;
      i = num % 7;
      x = 20 * num++;
   }
   public void draw() {
      Graphics g = box.getGraphics();
      g.setColor( col[i] );
      g.fillOval( x, y, XSIZE, YSIZE );
      g.dispose();
   }
   public void move() {
      if ( ! box.isVisible() ) return;
      Graphics g = box.getGraphics();
      g.setColor( col[i] );
      g.setXORMode( box.getBackground() );
      g.fillOval( x, y, XSIZE, YSIZE );
      x += dx;
      y += dy;
      Dimension d = box.getSize();
      if (x < 0) { x = 0; dx = -dx; }
      if (x + XSIZE >= d.width) { x = d.width - XSIZE; dx = -dx; }
      if (y < 0) { y = 0; dy = -dy; }
      if (y + YSIZE >= d.height) { y = d.height - YSIZE; dy = -dy; }
      g.fillOval( x, y, XSIZE, YSIZE );
      g.dispose();
   }
   public void run() {
      draw();
      while (true) {
         move();
         try {
            Thread.sleep( 5 );
         } catch( InterruptedException e ) {
            System.out.println( "thread interrupted" );
         }
      }
   }
}
