/**
 File:      ClockApplet.java
 Author:    Angus McIntyre <angus@pobox.com>
 Date:      22.05.96
 Updated:   17.03.98
 
 Simple Java applet to display a clock and update it continuously.
 Two kinds of clocks are included, a digital clock and a simple
 analog clock. Both work broadly the same way - a thread is created,
 which updates the clock display once every second or every minute.
 

    HISTORY
    -------
    
    22.05.96    SLAM    First version implemented
    27.05.96    SLAM    Classes merged, bugs fixed
    29.11.96    SLAM    Made a subclass of 'ExtendedApplet', to allow
                        use of parameter parsing routines.
   	17.03.98	SLAM	Added 'time-zone' argument so that the clocks
   						can be made to display the time in a given
   						time zone rather than the time in the user's
   						machine.
    
    TO-DO
    -----
    
    ClockApplet
    
        * Allow for specification of time-zone, so that we can create 
          a display with multiple clocks, all showing different times.
          
        * Reduce update period for clocks when 'show-seconds' is off:
          this will reduce the chance of clocks 'lagging'.
              
    LEGAL
    -----
    
    This software is free. It can be used and modified in any way you 
    choose, but it may not be sold, either separately or as part of a 
    collection without explicit prior permission from the author. The 
    author assumes no liability for any loss, damage or mental or 
    physical trauma you may incur through use of or inability to use 
    this software. This disclaimer must appear on any modified or 
    unmodified version of the software in which the name of the author
    also appears.
    
**/

/* ----------------------------------------------------------------------
 *                              IMPORTS
 * ---------------------------------------------------------------------- */

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

/* ----------------------------------------------------------------------
 *                              CLOCK APPLET
 * ---------------------------------------------------------------------- */

// Class:   ClockApplet
//
// The base applet class. This class is responsible for maintaining
// information about the animation control, the time, and some common
// variables.

public class ClockApplet extends ExtendedApplet implements Runnable {
	static  	final   int		no_time_zone_offset = -999;

    private     Thread  clock_thread = null;
    private     int     sleep_time;
    protected   Date    date;
    protected   boolean show_seconds_p = false;
    protected   boolean twenty_four_hour_p = false;
	protected	int		time_zone_offset;
	protected	int		time_zone_offset_milliseconds;
   
    // Constructor: ClockApplet()
    //
    // Initialize the variable that will be used to store the date.
    
    public  ClockApplet() {
        date = new Date();
    }
    
    // Method:  init()
    //
    // Read some basic parameters, and calculate the time that the
    // clock can be allowed to sleep between updates. If the clock
    // shows seconds, it sleeps for only 1000 milliseconds. If it
    // does not show seconds, it can sleep for longer. In theory, it
    // could sleep for a full minute (60000 milliseconds), but this
    // can lead to the display lagging (which looks odd if there
    // happen to be other clocks on the same page), so I've set it
    // to check for possible updates every fifteen seconds even if
    // it's not showing seconds. 
    
    public void init() {
        show_seconds_p = parseBooleanParameter("show-seconds",true);
        sleep_time = (show_seconds_p ? 1000 : 15000);
        
        // Check for a time_zone_offset parameter. This parameter will
        // indicate the time relative to GMT.
        
        time_zone_offset = parseIntegerParameter("time-zone",no_time_zone_offset);
        time_zone_offset_milliseconds = ( time_zone_offset == no_time_zone_offset ?
        								  0 :
        								  (60 * 60 * 1000 * 
        								   (time_zone_offset +
        								   	(date.getTimezoneOffset() / 60))));
    }
    
    // Method:  paint(Graphics)
    //
    // Called by the system to paint the applet. This in turn calls
    // the 'drawClock()' method.
    
    public void paint(Graphics g) {
        drawClock(g);
    }
    
    // Method:  start()
    //
    // The animation control thread is started by this method. If it's
    // null, a new thread is created and launched.
    
    public void start() {
        if (clock_thread == null) {
            clock_thread = new Thread(this);
            clock_thread.start();
        }
    }
    
    // Method:  stop()
    //
    // Stop the thread. If the user moves off to another window, this
    // method will get called to stop animation.
    
    public void stop() {
        if ((clock_thread != null) &&
            (clock_thread.isAlive()))
            clock_thread.stop();
        clock_thread = null;
    }
    
    // Method:  run()
    //
    // This method causes the clock to sleep repeatedly for a fixed
    // length of time, waking at intervals to update the clock display.
    // It will continue indefinitely.
    
    public void run() {
        while(true) {
            try { Thread.sleep(sleep_time); }
                catch (InterruptedException e) { }
            updateClock(this.getGraphics());
        }
    }
    
    // Method:  drawClock(Graphics)
    //
    // Draw the clock. This method simply updates the clock's
    // internal time record, ready for whatever subclass method
    // does the actual drawing.
    
    public void drawClock(Graphics g) {
        updateTimeRecord();
    }
    
    // Method:  updateClock(Graphics)
    //
    // Update the clock. This will be called repeatedly. This
    // implementation simply updates the time record in preparation
    // for the actual drawing performed by the subclass method.
    
    public void updateClock(Graphics g) {
        updateTimeRecord();
    }
    
    // Method:  updateTimeRecord
    //
    // Bring the internal time record up to date by getting the
    // time in milliseconds from the supporting system.
    
    public void updateTimeRecord() {
        date.setTime(System.currentTimeMillis() +
        			 time_zone_offset_milliseconds);
    }
}






