        // Digital display of a Timer running object.
        // A control panel at the bottom of the frame
        // allows the timer functions to be operated.
import java.awt.*;
import java.awt.event.*;

class Watch extends Frame implements ActionListener {
    // Set up the segments of the digital display.
    public Watch(){
        final int width = 250, height = 150;
        setSize(width,height);
        setBackground(Color.white);

        // Put the segments of the display in the frame.
        createSegments();
        // Put the controls in the frame.
        createControls();
        // Create the stop watch object.
        timer = new Timer();
        // Adjust the natural size of the window.
        pack();
    }

    // Set the components from the elapsed time, and paint everything.
    public void paint(Graphics g){
        setTime(timer.getElapsedTime());
        super.paint(g);
    }

    // Sleep for a short while before finding out what the
    // elapsed time is and repainting.
    public void run(){
        // How many milliseconds to pause between checking the time.
        final int timeToSleep = 100;
        while(true){
            try {
                Thread.sleep(timeToSleep);
            }
            catch(InterruptedException e){
                // Just go around again.
            }
            repaint();
        }
    }

    // Create the panel holding the segments of the display.
    private void createSegments(){
        Panel p = new Panel();
        // Set a font for the buttons in the panel.
        p.setFont( new Font("SansSerif",Font.PLAIN,16));
        for(int i = 0; i < fields.length; i++){
            fields[i] = new Label("0");
            p.add(fields[i]);
        }
        add("Center",p);
    }

    public void actionPerformed(ActionEvent e) throws RuntimeException {
        String command = e.getActionCommand();
        // Make sure that suspend and resume always appear in the
        // same position.
        final int suspendResumeIndex = 2;
        // Obtain the panel containing the buttons.
        Panel controlPanel = getControlPanel();

        if(command.equals(controlStrings[Reset])){
            // We could have come from any state, so remove everything.
            controlPanel.removeAll();
            controlPanel.add(controlButtons[Start]);
            timer.reset();
        }
        else if(command.equals(controlStrings[Start])){
            controlPanel.remove(controlButtons[Start]);
            controlPanel.add(controlButtons[Reset]);
            controlPanel.add(controlButtons[Stop]);
            controlPanel.add(controlButtons[Suspend],null,suspendResumeIndex);
            timer.start();
        }
        else if(command.equals(controlStrings[Suspend])){
            controlPanel.remove(controlButtons[Suspend]);
            controlPanel.add(controlButtons[Resume],null,suspendResumeIndex);
            timer.suspend();
        }
        else if(command.equals(controlStrings[Resume])){
            controlPanel.remove(controlButtons[Resume]);
            controlPanel.add(controlButtons[Suspend],null,suspendResumeIndex);
            timer.resume();
        }
        else if(command.equals(controlStrings[Stop])){
            controlPanel.removeAll();
            controlPanel.add(controlButtons[Reset]);
            timer.stop();
        }
        else{
            throw new RuntimeException("Unknown command "+command);
        }
        // Make everything fit in the new arrangement.
        pack();
        repaint();
    }

    private void createControls(){
        for(int b = 0; b < numButtons; b++){
            controlButtons[b] = new Button(controlStrings[b]);
            controlButtons[b].setActionCommand(controlStrings[b]);
            controlButtons[b].addActionListener(this);
        }
        // Initially, the timer can only be started.
        controlPanel.add(controlButtons[Start]);
        add(controlPanel,"South");
    }

    // Set the fields of the display according to
    // the elapsed time in milliseconds.
    private void setTime(long milliseconds){
        // Basic numbers of seconds, minutes and hours.
        long seconds = milliseconds/1000;
        long minutes = seconds/60;
        long hours = seconds/3600;

        // Reduce to their two-digit forms.
        seconds %= 60;
        minutes %= 60;
        hours %= 24;

        // Hours.
        fields[HOUR1].setText(Long.toString(hours/10));
        fields[HOUR2].setText(Long.toString(hours%10));
        fields[COLON1].setText(":");
        // Minutes.
        fields[MIN1].setText(Long.toString(minutes/10));
        fields[MIN2].setText(Long.toString(minutes%10));
        fields[COLON2].setText(":");
        // Seconds.
        fields[SEC1].setText(Long.toString(seconds/10));
        fields[SEC2].setText(Long.toString(seconds%10));
    }

    protected Panel getControlPanel(){
        return controlPanel;
    }

    // Indices into fields[].
    private static final int HOUR1 = 0, HOUR2 = HOUR1+1;
    private static final int COLON1 = HOUR2+1;
    private static final int MIN1 = COLON1+1, MIN2 = MIN1+1;
    private static final int COLON2 = MIN2+1;
    private static final int SEC1 = COLON2+1, SEC2 = SEC1+1;
    // How many fields we have.
    private static final int num_fields = SEC2+1;
    private Label fields[] = new Label[num_fields];

    // Field for the controls.
    // Indices into the button arrays: controlStrings, controlButtons.
    private static int Reset = 0, Start = 1, Suspend = 2,
                        Resume = 3, Stop = 4;
    // Strings associated with the control buttons.
    private static String controlStrings[] = {
        "Reset", "Start", "Suspend", "Resume", "Stop",
    };
    private static int numButtons = controlStrings.length;
    // The panel holding the control buttons.
    // The control buttons.
    private Button[] controlButtons = new Button[numButtons];

    private Panel controlPanel = new Panel();
    // The object keeping time for us.
    private Timer timer;
}
