import java.awt.*;
import java.awt.image.*;
/***********************************************************************
*
* A station clock applet, drawn with anti-aliased graphics.
* This applet uses the AntiAliasingFilter class to draw a clock.
*
*
* Home page: www.source-code.biz
* Copyright 1997-2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.
* License: This is "Open Source" software and released under the GNU/GPL license.
* It is provided "as is" without warranty of any kind. Please contact the author for other licensing arrangements.
*
*
* Version history:
* 1997-07-01 Christian d'Heureuse (chdh): Module created.
* 2003-06-30 chdh: Revision.
*
***********************************************************************/
public class ClockApplet extends java.applet.Applet implements Runnable {
private String clockLabel = "source-code.biz";
private Color bgColor;
private int aaScalingFactor; // anti-aliasing scaling factor
private Color secPtrColor = new Color(0xCC,0x00,0x00);
private Color borderColor = new Color(0xC0,0xC0,0xC0);
private Thread thread;
private Image staticImg;
private Image dynImg;
private int r;
private int centerX;
private int centerY;
private void abend (String msg) {
throw new RuntimeException(getClass().getName()+": "+msg); }
private void drawRadial (Graphics g, double alpha, int r1, int r2,
int width1, int width2) {
double sin = Math.sin(alpha);
double cos = Math.cos(alpha);
double pm1X = sin * r1;
double pm1Y = cos * r1;
double pm2X = sin * r2;
double pm2Y = cos * r2;
double pxr[] = new double[4];
double pyr[] = new double[4];
pxr[0] = pm1X - cos*width1/2;
pyr[0] = pm1Y + sin*width1/2;
pxr[3] = pm1X + cos*width1/2;
pyr[3] = pm1Y - sin*width1/2;
pxr[1] = pm2X - cos*width2/2;
pyr[1] = pm2Y + sin*width2/2;
pxr[2] = pm2X + cos*width2/2;
pyr[2] = pm2Y - sin*width2/2;
int pxi[] = new int[4];
int pyi[] = new int[4];
for (int i=0; i<4; i++) {
pxi[i] = centerX + (int)Math.round(pxr[i]);
pyi[i] = centerY - (int)Math.round(pyr[i]); }
g.fillPolygon (pxi,pyi,4); }
private void drawRadialFcirc (Graphics g, double alpha, int r1,
int circR) {
int p0X = (int)Math.round( centerX + Math.sin(alpha) * r1 );
int p0Y = (int)Math.round( centerY - Math.cos(alpha) * r1 );
g.fillOval (p0X-circR,p0Y-circR,2*circR,2*circR); }
private void drawClockLabel (Graphics g) {
g.setColor (borderColor);
int fontSize = r*20/200;
Font f = new Font("Helvetica",Font.PLAIN,fontSize);
g.setFont (f);
FontMetrics fm = g.getFontMetrics();
g.drawString (clockLabel,centerX-fm.stringWidth(clockLabel)/2,centerY+r/2); }
private void drawFilledCircle (Graphics g, int r, Color c) {
g.setColor (c);
g.fillOval (centerX-r,centerY-r,2*r,2*r); }
private void drawStaticImage (Graphics g, int width, int height) {
r = Math.min(width,height) * 7 / 16;
centerX = width/2;
centerY = height/2;
g.setColor (bgColor);
g.fillRect (0,0,width,height);
int borderWidth = r / 54;
// drawFilledCircle (g,r+borderWidth+borderWidth,new Color(0xf0,0xf0,0xf0));
drawFilledCircle (g,r+borderWidth,borderColor);
drawFilledCircle (g,r,Color.white);
g.setColor (Color.black);
for (int i=0; i<60; i++) {
boolean big = i % 5 == 0;
int rlength = big ? r*10/44 : r*3/44; rlength = Math.max(1,rlength);
int rwidth = big ? r*3/44 : r/44; rwidth = Math.max(1,rwidth);
int r2 = r*42/44;
drawRadial (g,2*Math.PI/60*i,r2-rlength,r2,rwidth,rwidth); }
drawClockLabel (g); }
private void generateStaticImage (int width, int height) {
staticImg = createImage(width,height);
Graphics g = staticImg.getGraphics();
drawStaticImage (g,width,height);
g.dispose(); }
private void drawDynamicImage (Graphics g, int hour, int min, int sec) {
g.setColor (Color.black);
drawRadial (g,2*Math.PI*((hour%12)*60+min)/(12*60),-r*10/44,r*27/44,r*5/44,r*4/44);
drawRadial (g,2*Math.PI*min/60,-r*10/44,r*40/44,r*9/88,r*3/44);
g.setColor (secPtrColor);
int r_1_44 = Math.max(1,r*1/44);
drawRadial (g,2*Math.PI*sec/60,-r*14/44,r*27/44,r_1_44,r_1_44);
drawRadialFcirc (g,2*Math.PI/60*sec,r*27/44,r*9/88); }
private Image genImg (int width, int height, int hour, int min, int sec) {
int aaWidth = width * aaScalingFactor;
int aaHeight = height * aaScalingFactor;
if (staticImg == null || staticImg.getWidth(null)!=aaWidth ||
staticImg.getHeight(null)!=aaHeight) {
generateStaticImage (aaWidth,aaHeight);
dynImg = createImage(aaWidth,aaHeight); }
Graphics g = dynImg.getGraphics();
g.drawImage (staticImg,0,0,null);
drawDynamicImage (g,hour,min,sec);
g.dispose();
if (aaScalingFactor <= 1) return dynImg;
// AreaAveragingScaleFilter aaFilter = new AreaAveragingScaleFilter(width,height);
// ReplicateScaleFilter aaFilter = new ReplicateScaleFilter(width,height);
AntiAliasingFilter aaFilter = new AntiAliasingFilter(aaScalingFactor);
ImageProducer aaProd = new FilteredImageSource(dynImg.getSource(),aaFilter);
Image outImg = createImage(aaProd);
return outImg; }
private void getTimeNew (int[] time) {
java.util.GregorianCalendar cal = new java.util.GregorianCalendar();
time[0] = cal.get(cal.HOUR_OF_DAY);
time[1] = cal.get(cal.MINUTE);
time[2] = cal.get(cal.SECOND); }
public void paint (Graphics g) {
int time[] = new int[3];
getTimeNew (time);
Image img = genImg(getSize().width,getSize().height,time[0],time[1],time[2]);
g.drawImage (img,0,0,null); }
public void update (Graphics g) {
paint (g); }
public void run() {
while (thread == Thread.currentThread()) {
int secOffs = (int) (System.currentTimeMillis() % 1000);
int delayT = 1100 - secOffs;
try {
Thread.sleep (delayT); }
catch (Exception e) {
throw new RuntimeException(e.getMessage()); }
repaint(); }}
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start(); }}
public void stop() {
thread = null; }
public String getAppletInfo() {
return "2003-06-30, Christian d'Heureuse (www.source-code.biz)"; }
public void setBgColor (String s) {
try {
bgColor = new Color(Integer.parseInt(s,16)); }
catch (Exception e) {
abend ("invalid bgColor parameter ("+e.getMessage()+")"); }
repaint(); }
public void setAaScalingFactor (String s) {
try {
aaScalingFactor = Integer.parseInt(s); }
catch (Exception e) {
abend ("invalid aaScalingFactor parameter ("+e.getMessage()+")"); }
repaint(); }
private void getParms() {
bgColor = Color.white;
String s = getParameter("bgColor");
if (s != null) setBgColor (s);
aaScalingFactor = 1;
s = getParameter("aaScalingFactor");
if (s != null) setAaScalingFactor (s); }
public void init() {
getParms();
setBackground (bgColor); }
};