import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;

public class BouncingBallsSol extends Applet {
    private static int width;
    private static int height;

    private Choice choice;
    private TextArea echoArea;

    private BallThread t;
    private Vector balls;

    private int lastX;
    private int lastY;
    private int clickNumber; 
  

    public void init ( ) {
        setBackground(Color.white);
        height = getBounds().height;
        width = getBounds().width;
        addMouseListener(new MouseHandler());
 
       // Create a button and add it to the Frame.
        Button clearButton = new Button("Clear");
        clearButton.setForeground(Color.black);
        clearButton.setBackground(Color.lightGray);
        add(clearButton);
        clearButton.addActionListener(new ClearButtonHandler());

        // Create a menu of user choices and add it to the Frame.
        choice = new Choice();
        choice.addItem("Magenta");
        choice.addItem("Yellow");
        choice.addItem("Blue");
        choice.addItem("Green");
        add(choice);
        choice.addItemListener(new ChoiceHandler());

        // Create a TextArea and add it to the Frame.
        echoArea = new TextArea(2, 50);
        echoArea.setEditable(false);
        add(echoArea);    } // init

    public void start ( ) {
        clickNumber = 0;
        balls = new Vector();
        t = new BallThread(balls);
        t.start( ); 
    } // start

    public void stop () {
            t.stopBallThread();
    } // stop
   
    public void paint(Graphics g) {
        Enumeration e = balls.elements();
        while (e.hasMoreElements()) {
            Ball b = (Ball)(e.nextElement());
            b.paint(g);
        }
    }
    
    private class BallThread extends Thread {
        boolean alive;
        Vector balls;

        public BallThread (Vector balls) { 
            this.balls = balls;
            alive = true;
        }

        public synchronized void stopBallThread () { //substitutes stop() which is deprecated
            alive = false;
        }

        public synchronized boolean isLiving () {
            return alive;
        }
 
        public void run( ) {
            while (isLiving()) {
                Enumeration e = balls.elements();
                while (e.hasMoreElements()) {
                    Ball b = (Ball)(e.nextElement());
                    b.move();
                }
                repaint( );
                try { Thread.sleep(50);
                } catch (InterruptedException exc) { }
            }
        }
    }

    private class Ball {

        int x, y;     // current location
        int dx, dy;   // speed
        int diameter = 10;
        Color color;

        public Ball (int x, int y, int dx, int dy, Color color) {
            this.x = x;
            this.y = y;
            this.dx = dx;
            this.dy = dy;
            this.color = color;
        }

        public void move  () {
            if (x < 0 || x >= BouncingBallsSol.width)
                dx = - dx;
            if (y < 0 || y >= BouncingBallsSol.height)
                dy = - dy;
            x += dx;
            y += dy;
        }

        public void paint (Graphics g) {
            g.setColor(color);
            g.fillOval(x, y, diameter, diameter);
        }

    } // Ball


    // Handling events that occur in the frame

    // Called when the user clicks the mouse button
    private class MouseHandler extends MouseAdapter {
        public void mouseClicked(MouseEvent e) { 
            int x = e.getX();
            int y = e.getY();
            echoArea.setText("Mouse Clicked at " + 
                             e.getX() + ", " + e.getY() + "\n");
            clickNumber = clickNumber + 1;
            // is it the first click?
            if (clickNumber % 2 == 1) {  
            echoArea.append("Click in another point to set direction and speed");
            lastX = x;
            lastY = y;
            }
            // or the second?
            else {
                String c = choice.getSelectedItem();
                if (c.equals("Magenta"))
                    balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.magenta));
                else if (c.equals("Blue"))
                    balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.blue));
                else if (c.equals("Yellow"))
                    balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.yellow));
                else balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.green));
            }
        } // mouseClicked
    }


    // Called when the user selects clear Button
    private class ClearButtonHandler implements ActionListener {
        public void actionPerformed (ActionEvent e) {
            echoArea.setText("Clear button selected ");
            repaint();
            t.stopBallThread();
            clickNumber = 0;
            balls = new Vector();
            t = new BallThread(balls);
            t.start( ); 
        }
    }
     
    // Called when the user selects a Choice
    private class ChoiceHandler implements ItemListener {
        public void itemStateChanged (ItemEvent e) {
            String c =  (String) (e.getItem());
            echoArea.setText("Color selected: " + c);
            // prepare to handle first mouse click for this choice
            clickNumber = 0;
            echoArea.append("\nClick to set starting position of new ball");                       }
    }    
} // BouncingBallsSol


