/** Clock - Yet another clock Applet in Java. @author Martin Sullivan. This was written as a refresh/revision exercise. The author writes: I, like not a few people around me have waded through books styled "Power Java for the Very Stupid Made Easy with a CD" or thereabouts. Satisfied that I knew enough Java to get by, there was then a Hiatus where no useful Java was written. Since some time has now elapsed, I wrote this to refresh my memory and to catch up on newer Java language features. As a result the style may be a bit slanted toward the gratuitous use of such features. Some of these features were actually stripped out when it made things just too clunky, at one time it was two Classes separated by an Interface, just for the hell of it. Initial attempts at compilation were marked by the Java Compiler whinging about "Depricated features". So the classes and methods were rewritten to use pure Java 1.1. This means that the are a number of lossages with various browsers which may be running this program and may not be too uptodate with their Java. @version $Id: Clock.java,v 1.2 2001/03/07 14:49:10 sullivan Exp $ */ /* Clock - A Clock JAVA Applet by Martin Sullivan. Copyright (C) 1999 ZOIS Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (version 1). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A full copy of the GNU General Public License can be found at http://www.gnu.org/copyleft/gpl.html or can be obtained by writing to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Author: Martin Sullivan. ZOIS Ltd., Stag House, 55 Kirkgate, Cockermouth CA13 9PH Email: sullivan@zois.co.uk */ /* $Log: Clock.java,v $ Revision 1.2 2001/03/07 14:49:10 sullivan Added GPL to allow publication on web-site. First published as a Class only mid-1999. */ import java.applet.*; import java.awt.*; import java.util.*; /** Clock - Yet another clock Aplet in Java. */ public class Clock extends Applet implements Runnable { static final int POINTS = 12; Thread clockThread = null; Mark mark = new Mark (); SecondHand secondHand = new SecondHand (); MinuteHand minuteHand = new MinuteHand (); HourHand hourHand = new HourHand (); boolean timeSet = false; Calendar c = Calendar.getInstance (); public void start () { clockThread = new Thread (this); clockThread.start (); } // start public void stop () { clockThread.stop (); clockThread = null; } // stop static double asrads (int degrees) { return (((double) degrees / (double) 180.0) * (double) Math.PI); /* Degrees to the machine preferred Radians, Note the static declaration. */ } // asrads public void run () { while (clockThread != null) { c = Calendar.getInstance (); /* Lossages here, The doc says c should be the current time for the default Time Zone and Daylight Savings Time (DST). However it seems to be a random value on some systems and on others the DST is ignored. */ secondHand.setHand (asrads (c.get (Calendar.SECOND) * 360 / 60)); minuteHand.setHand (asrads ( (c.get (Calendar.MINUTE) * 360 / 60) + (c.get (Calendar.SECOND) * 360 / 60 / 60))); hourHand.setHand (asrads ( (c.get (Calendar.HOUR) * 360 / 12) + (c.get (Calendar.MINUTE) * 360 / 60 / 12) + (c.get (Calendar.SECOND) * 360 / 60 / 60 / 12))); /* We work in Degrees for simplicity. */ timeSet = true; repaint (); try { clockThread.sleep (1000); } // try catch (InterruptedException e) { } // catch } // for } // run void drawFace (Graphics g, int maxsize, Point centre) { mark.drawMarks (g, maxsize, centre, POINTS); } // drawFace public void paint (Graphics g) { int maxsize; int widthOffset; int heightOffset; Point centre = new Point (); /* Point is a Lossage. It gives really old Java implementions grief. */ /* We use a radial coordintes system, which means we figure out a cenral point and the maximum size of the circle. */ maxsize = (getSize().width < getSize().height ? getSize().width : getSize().height); widthOffset = (getSize().width < maxsize ? 0 : getSize().width - maxsize) / 2; heightOffset = (getSize().height < maxsize ? 0 : getSize().height - maxsize) / 2; centre.setLocation ((maxsize / 2) + widthOffset, (maxsize / 2) + heightOffset); /* Draw the Clock. A double buffering method could have been used but found to be unnecessary. */ g.clearRect (0, 0, getSize().width, getSize().height); drawFace (g, maxsize, centre); if (timeSet) { secondHand.drawHand (g, maxsize, centre); minuteHand.drawHand (g, maxsize, centre); hourHand.drawHand (g, maxsize, centre); } // if } // paint public String getAppletInfo () { return ("Yet another Java clock, this one by Martin Sullivan."); } // getAppletInfo /* Classes in this program are actually Inner Classes, a feature new to Java 1.1. Things like this should be familier to Pascal programmers where functions and procedures could be nested. */ class Mark extends RadialLine { Mark () { super (1.0, 0.9); } // Mark.Mark void drawMarks (Graphics g, int maxsize, Point centre, int no) { int ix; for (ix = 0; ix < no; ix++) { this.setRadialLine (asrads (ix * 360 / no)); this.drawRadialLine (g, maxsize, centre); } // for } // drawMarks } // Mark /* Classes from here to class drawRadialLine are a bit over the top with polymorphism and inheritence. */ class HourHand extends Hand { HourHand () { super (0.5); } // HourHand::HourHand } // HourHand class MinuteHand extends Hand { MinuteHand () { super (0.70); } // MinuteHand::MinuteHand } // MinuteHand class SecondHand extends Hand { SecondHand () { super (0.85, 0.75); } // SecondHand::SecondHand } // SecondHand class Hand extends RadialLine { Hand (double length) { super (length); } // Hand.Hand Hand (double length, double arcStart) { super (length, arcStart); } // Hand.Hand void setHand (double vector) { setRadialLine (vector); } // setHand void drawHand (Graphics g, int max, Point centre) { drawRadialLine (g, max, centre); } // drawRadialLine } // Hand class RadialLine extends Applet { private double vector; private Point start = new Point (); private Point end = new Point (); private double length; private double arcStart = 0.05; RadialLine () { this.length = 1.0; } // RadialLine.RadialLine RadialLine (double length) { this.length = length; } // RadialLine.RadialLine RadialLine (double length, double arcStart) { this.length = length; this.arcStart = arcStart; } // RadialLine.RadialLine void setRadialLine (double vector) { /* This bit of maths is to sort out the co-ordinate system so that vector = 0 means straight up (12h00) */ this.vector = vector - (Math.PI / (double) 2); } // setRadialLine void drawRadialLine (Graphics g, int max, Point centre) { double halfMax; double yvec; double xvec; halfMax = (double) (max / 2); xvec = Math.cos (vector) * halfMax; yvec = Math.sin (vector) * halfMax; start.setLocation ( (int) (xvec * arcStart) + centre.x, (int) (yvec * arcStart) + centre.y); end.setLocation ( (int) (xvec * length) + centre.x, (int) (yvec * length) + centre.y); g.drawLine (start.x, start.y, end.x, end.y); } // draw } // RadialLine } // Clock