// Michael Tartaglia
// Binary Clock
// 	Program shows time using binary number rows. The top row displayed
//	represents hours, the middle represents minutes, and the bottom represents
// seconds.  The user can switch between binary and standard digital time by
// hovering the cursor over the clock, and switch between international business
// time and colloquial time by clicking the clock.

import java.util.Calendar;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class BinaryClock extends Applet implements MouseListener {
	private final String[] months = {"JAN","FEB","MAR","APR","MAY",
		"JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
	private Calendar date;
	private Image clock;		 // clock image
	private Graphics cg;		 // clock graphics package
	private int[] time = new int[6]; // hours, mins, secs to store
	private boolean isMouseOver, militaryTime, isAM;
	private Font Courier, Arial, ArialSM, ArialXSM;



	public void init() {
	 addMouseListener(this);	// ADD MOUSE LISTENER TO CANVAS

	 clock = this.createImage(100,100);	// SET IMAGE OF CLOCK
	 cg = clock.getGraphics();				// COLLECT GRAPHICS PKG FOR CLOCK

	 Courier = new Font("Courier",Font.BOLD,18);	// SET FONT
	 ArialXSM = new Font("Arial",Font.PLAIN,12);	// SET "EXTRA SMALL" ARIAL FONT
	 ArialSM = new Font("Arial",Font.PLAIN,14);	// SET "SMALL" ARIAL FONT
	 Arial = new Font("Arial",Font.BOLD,24);		// SET REGULAR ARIAL FONT
	
	 isMouseOver = false;	// SET HOVER CHECK BOOLEAN
	 militaryTime = true;	// SET MILITARY TIME (INTERNATIONAL TIME) BOOLEAN
	 isAM = true;				// USE am OR pm CHECK BOOLEAN

	}
	


	public void paintClock()
    // FUNCTION: method sets values for time before continuing to "binary" or
	 //	"standard time" painting subroutines
	 {
	 // CLEAR CLOCK FACE AND PAINT BORDER
	 cg.setColor(Color.white);
	 cg.fillRect(0,0,100,100);
	 cg.setColor(Color.black);
	 cg.drawRect(0,0,67,46);

	 date = Calendar.getInstance();		// GET TIME INSTANCE

  	 time[0] = date.get(Calendar.HOUR);
  	 time[1] = date.get(Calendar.MINUTE);
  	 time[2] = date.get(Calendar.SECOND);
	 time[3] = date.get(Calendar.DATE);
	 time[4] = date.get(Calendar.MONTH);
	 time[5] = date.get(Calendar.YEAR)%100;

	 // CHECK FOR am NEED
	 if (date.get(Calendar.HOUR_OF_DAY) < 12) isAM = true;
	 else isAM = false;
	 
	 // CHECK FOR MILITARY TIME
	 if (militaryTime) time[0] = date.get(Calendar.HOUR_OF_DAY);
	 
	 // CHECK FOR BINARY OR STANDARD CLOCK TO SHOW
	 if (!isMouseOver) paintBinaryClock();
	 else paintDecimalClock();
	}



	public void paintDecimalClock()
	 // FUNCTION: method paints standard clock to global clock buffer
	 {
	 cg.setColor(Color.gray);		// SET COLOR
	 cg.setFont(Arial);				// SET FONT FOR TIME
	 cg.drawString((time[0] <= 9 && !militaryTime ? " " : "")
	       + (time[0] <= 9 && militaryTime ? "0"+time[0] : ""+time[0])
	       + ":" + (time[1] <= 9 ? "0"+time[1] : ""+time[1]),3,20);
	 cg.setColor(Color.black);		// SET COLOR
	 cg.setFont(ArialSM);			// SET FONT FOR SECONDS
	 cg.drawString((time[2] <= 9 ? "0"+time[2] : ""+time[2]),10,33);
	 if (!militaryTime) cg.drawString((isAM ? "AM" : "PM"),36,33);	// DRAW AM OR PM
	 cg.setFont(ArialXSM);			// SET FONT FOR DATE
	 cg.drawString(time[3] + " " + months[time[4]] + " "
	       + (time[5] < 10 ? "'0"+time[5] : "'"+time[5]), 5, 45);
	}



	public void paintBinaryClock() {
	 // FUNCTION: method paints binary clock to global clock buffer
	 cg.setFont(Courier);	// SET FONT
	 cg.setColor(new Color(0,180,0));
	 cg.drawString(toBinary(time[0]),1,14);	// DRAW HOURS AS BINARY
	 cg.setColor(new Color(0,128,0));
	 cg.drawString(toBinary(time[1]),1,29);	// DRAW MINUTES
	 cg.setColor(new Color(0,95,0));
	 cg.drawString(toBinary(time[2]),1,44);	// DRAW SECONDS
	}


	
	private String toBinary(int x) {
	 String b = "";	// BINARY STRING HOLDER
	 while (x > 0) {	// CONVERT DECIMAL TO BINARY USING MODULUS
	  if (x%2 == 0) b = '0'+b;
	  else {b = '1'+b; x -= 1;}
	  x /= 2;
	 }
	 while (b.length() < 6) b = '0'+b;
	 return b;
	}



	public void mousePressed(MouseEvent m) {}
	public void mouseReleased(MouseEvent m) {}
	public void mouseEntered(MouseEvent m) {isMouseOver = true;}
	public void mouseExited(MouseEvent m) {isMouseOver = false;}
	public void mouseClicked(MouseEvent m) {
	 militaryTime = (militaryTime ? false : true);
	}



	public void update(Graphics g) {paint(g);}
	public void paint(Graphics g) {
		paintClock();						// RESET AND PAINT CLOCK BUFFER
		g.drawImage(clock,0,0,this);	// DRAW CLOCK BUFFER IMAGE TO APPLET
		try {Thread.sleep(100); repaint();} // CYCLE PROCESS EVERY 1/10TH SECOND
		catch (InterruptedException x) {}
	}

}
