/* Digital Clock - Version 1.0                                        */
/* Author:  Man Keung (Owen) Chan                                     */
/* E-mail:  mchan@ebbets.poly.edu                                     */
/* URL:     http://ebbets.poly.edu/~mchan                             */

/* This software is provided "AS IS," without a warranty of any kind. */
/* It can be freely distributed or modified in any way you like :)    */

import java.applet.*;
import java.util.*;
import java.awt.*;

public class Clock extends Applet implements Runnable {

       Date now;
       Thread mainThr;
       Image img = null;
       boolean border=false;
       MediaTracker mt = new MediaTracker(this);

       /* Image array: 0,1,2,3,4,5,6,7,8,9,AM,PM,:,- */
       Image digits[] = new Image[14];
       int offset;
       boolean showTime = true;    /* shows date if false */
       Color backgroundColor = new Color(255,255,255);
       /* color arry, {"color name",color} */
       private Object[][]  colors = { { "white",   Color.white   },
				      { "black",   Color.black   },
				      { "gray",    Color.gray    },
				      { "red",     Color.red     },
				      { "cyan",    Color.cyan    },
				      { "pink",    Color.pink    },
				      { "yellow",  Color.yellow  },
				      { "green",   Color.green   },
				      { "orange",  Color.orange  },
				      { "magenta", Color.magenta },
				      { "blue",    Color.blue    } };
 

       public void init() {
	  String param;

	  /* get background color if exist */
	  param = getParameter("bgcolor");
	  if (param != null) {
	     backgroundColor = getBackgroundColor(param);
	  }
      
	  /* do you need a border */
	  param = getParameter("border");
	  if (param != null) {
	     border=param.equals("yes")?true:false;
	  }

	  now = new Date();
	  /* load digit images */
	  for (int i=0; i<14; i++) {
	      param = i + ".gif";
	      digits[i] = getImage(getCodeBase(),param);
	      mt.addImage(digits[i],1);
	  }
	  img = createImage(size().width, size().height);
       }

       public void start() {
	  mainThr = new Thread(this);
	  mainThr.start();
       }

       public void stop() {
	  mainThr.stop();
       }

       public void paint ( Graphics g ) {

	if (mt.checkID(1,true)) {

	  img = createImage(size().width, size().height);
	  if ( showTime ) { 
	       displayTime(); 
	  } else { 
		    displayDate(); 
		 }
	  g.drawImage(img,0,0,this);
	}
	else {
		FontMetrics fm = g.getFontMetrics();
		String loadMesg = "Loading digits...";
		int mesgX = 10, mesgY = 10;
		int mesgWidth = fm.stringWidth(loadMesg);

		mesgX = ( size().width - mesgWidth )/2;
		mesgY = size().height/2 + fm.getHeight()/2;
		g.drawString(loadMesg,mesgX,mesgY);
	}

	  /* draw border */
	  if (border) {
	    g.setColor(Color.white);
	    g.drawLine(0,0,size().width-1,0);
	    g.drawLine(0,0,0,size().height-1);
	    g.setColor(Color.gray);
	    g.drawLine(1,size().height-2,size().width-1,size().height-2);
	    g.drawLine(size().width-2,1,size().width-2,size().height-2);
	    g.setColor(Color.black);
	    g.drawLine(1,size().height-1,size().width-1,size().height-1);
	    g.drawLine(size().width-1,1,size().width-1,size().height-1);
	  }
       }

       /* draw current time */
       public void displayTime() {

	  Graphics offg = img.getGraphics();
	  int result;
	  int top = ( size().height - digits[0].getHeight(this) ) / 2;
	  int pos = ( size().width - digits[0].getWidth(this)*8 - digits[10].getWidth(this) ) / 2;
	  int temp;
	  int ampm = 10;   /* default is am */
	  int offset = digits[0].getWidth(this);

	  if ( top < 0 ) top = 0;
	  if ( pos < 0 ) pos = 0;
	  offg.setColor(backgroundColor);
	  offg.fillRect(0,0,size().width, size().height);

	  /* display PM if hour >= 12, digits[10] = AM, digits[11] = PM */
	  if (now.getHours() >= 12) { ampm = 11; }
	  temp = now.getHours() % 12;
	  if ( temp == 0 ) temp = 12;

	  /* draw hour digit 1 */
	  if (temp >= 10) {
	     result = 1;
	  } else result = 0;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;
	  /* draw hour digit 2 */
	  result = temp % 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  offg.drawImage(digits[12],pos,top,this);
	  pos =pos + offset;

	  /* draw minute digit 1 */
	  temp = now.getMinutes() % 60;
	  result = temp/10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  /* draw minute digit 2 */
	  result = temp % 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos =pos + offset;

	  offg.drawImage(digits[12],pos,top,this);
	  pos =pos + offset;

	  /* draw second digit 1 */
	  temp = now.getSeconds() % 60;
	  result = temp/10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  /* draw second digit 2 */
	  result = temp % 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  /* draw am or pm */
	  offg.drawImage(digits[ampm],pos,top,this);
       }

       /* draw current date */
       public void displayDate() {

	  Graphics offg = img.getGraphics();
	  int result = 0;
	  int temp = 0;
	  int top = ( size().height - digits[0].getHeight(this) ) / 2;
	  int pos = ( size().width - digits[0].getWidth(this)*8 ) / 2;
	  int offset = digits[0].getWidth(this);

	  offg.setColor(backgroundColor);
	  offg.fillRect(0,0,size().width, size().height);
	  
	  temp = now.getMonth() + 1;
	  
	  if ( top < 0 ) top = 0;
	  if ( pos < 0 ) pos = 0;
	  /* draw month digit 1 */
	  if (temp >= 10) {
	     result = 1;
	  } else result = 0;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;
	  /* draw month digit 2 */
	  result = temp % 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  offg.drawImage(digits[13],pos,top,this);
	  pos = pos + offset;

	  /* draw day digit 1 */
	  temp = now.getDate();
	  result = temp / 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  /* draw day digit 2 */
	  result = temp % 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  offg.drawImage(digits[13],pos,top,this);
	  pos =pos + offset;

	  /* draw year digit 1 */
	  temp = now.getYear();
	  result = temp / 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;

	  /* draw year digit 2 */
	  result = temp % 10;
	  offg.drawImage(digits[result],pos,top,this);
	  pos = pos + offset;
       }

       public void update ( Graphics g ) {
	  now = new Date();
	  paint(g);
       }

       public void run() {
	  while (true) {
	    try {
		  mt.waitForID(1);
		  mainThr.sleep(500);
	    } catch (InterruptedException e) {}
	    repaint();
	  }
       }

       /* click mouse to display more information */
       public boolean mouseDown(Event evt, int x, int y) {
    
	    InfoBox f = new InfoBox(x,y,6,40,"About");
	    f.tell("Digital Clock - Version 1.0\n");
	    f.tell("Author:\tOwen Chan\n");
	    f.tell("E-mail:\tmchan@ebbets.poly.edu\n");
	    f.tell("URL:\thttp://ebbets.poly.edu/~mchan");
	    f.show();
	 
	    return true;
       }
       
       /* mouse enters applet, show date */
       public boolean mouseEnter(Event evt, int x, int y) {
	    showTime = false;
	    showStatus("Digital Clock 1.0 - click to display more information");
	    return true;
       }

       /* mouse leaves applet, show time */
       public boolean mouseExit(Event evt, int x, int y) {
	    showTime = true;
	    showStatus("");
	    return true;
       }

       /* decode background color */
       private Color getBackgroundColor(String name) {

	 try {
	    StringTokenizer tokens = new StringTokenizer(name, ",");
	    /* decode RGB */
	    if ( tokens.countTokens() == 3) {
	       int red   = Integer.parseInt(tokens.nextToken());
	       int green = Integer.parseInt(tokens.nextToken());
	       int blue  = Integer.parseInt(tokens.nextToken());
	    
	       return new Color(red, green, blue);
	    } else { /* look up color in color array */
		     for (int i = 0; i < colors.length; i++) {
			 if (name.equals(colors[i][0])) {
			     return (Color)colors[i][1];
			 }
		     }
		   }
	  } catch (Exception e) { return backgroundColor; }
	  return backgroundColor;
       }

}

/* display more information in another window */
class InfoBox extends Frame {

    /* flag detects if the window has already been shown */
    static boolean flag = false;  
    TextArea info;
    Button ok;

    public InfoBox(int x, int y, int rows, int cols, String title) {
	super(title);

	add("Center", info = new TextArea(rows, cols));
	info.setEditable(false);
	info.setBackground(Color.white);
	setBackground(Color.white);
	setResizable(false);
	Panel buttons = new Panel();
	add("South", buttons);
	buttons.add(ok = new Button("OK"));
	move(x,y);
	pack();
    }

    public void show() {

      if (!flag) {
	InfoBox.flag = true;
	super.show();
      }
    }

    void tell(String s) {
	info.appendText(s);
    }

    public boolean action(Event e, Object arg) {
	if (e.target == ok) {
	    hide();
	    InfoBox.flag = false;
	    return true;
	}

	return false;
    }
}
	  
