home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 July & August
/
Pcwk78a98.iso
/
Internet
/
Javadraw
/
DATA.Z
/
javex.java
< prev
next >
Wrap
Text File
|
1995-10-08
|
18KB
|
543 lines
/*
* javex.java - 19 Jan 1996 - Version 1.03
*
* Note: This source code is subject to perpetual refinement!
*
* Copyright 1996 by Bill Giel
*
* E-mail: rvdi@usa.nai.net
* WWW: http://www.nai.net/~rvdi/home.htm
*
*
* Revision 1.01 - revised hms class to calculate GMT. This permits the clock
* 10 Feb 96 to be used to display the time at any location by supplying
* a TIMEZONE parameter in the HTML call.
*
* Revision 1.02 - revised timezone to accept real numbers, for places like
* 11 Feb 96 India, with a 5.5 hour time difference. I learn something
* new everyday!
*
* Revision 1.03 - fixed loop in run() to exit if clockThread==null, rather
* than simple for(;;)
*
* Usage:
*
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted, provided that any use properly credits
* the author, i.e. "Javex Clock courtesy of <A HREF="mailto:rvdi@usa.nai.net">
* Bill Giel</A>.
*
*
* THE AUTHOR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHOR SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). YOU WOULD
* HAVE TO BE OUT OF YOUR MIND TO USE THIS SOFTWARE IN A HIGH-RISK ENVIRONMENT
* AND, AS SUCH MAY BE THE CASE, THE AUTHOR SPECIFICALLY DISCLAIMS ANY EXPRESS
* OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES, INCLUDING BUT NOT
* LIMITED TO USE OR MISUSE OF THIS SOFTWARE RESULTING IN NUCLEAR EXPLOSIONS,
* GLOBAL WARMING OR OZONE-LAYER DEPLETION.
*/
import java.awt.*;
import java.applet.*;
import java.lang.*;
import java.util.*;
import java.net.*;
class hms extends Date
{
//Note that localOffset is hours difference from GMT
//west of Greenwich meridian is positive, east is negative.
//i.e. New York City (Eastern Standard Time) is +5
// Eastern Daylight Time is +4
public hms(double localOffset){
super();
long tzOffset=getTimezoneOffset()*60L*1000L;
setTime(getTime() + tzOffset - (long)(localOffset*3600.0*1000.0));
}
public double get_hours()
{
return (double)super.getHours()+(double)getMinutes()/60.0;
}
}
abstract class clockHand
{
protected int baseX[], baseY[];
protected int transX[],transY[];
protected int numberOfPoints;
public clockHand(int originX, int originY, int length,int thickness,int points){
baseX= new int[points]; baseY=new int[points];
transX= new int[points]; transY=new int[points];
initiallizePoints(originX,originY,length,thickness);
numberOfPoints=points;
}
abstract protected void initiallizePoints( int originX,
int originY,
int length,
int thickness);
abstract public void draw(Color color, double angle, Graphics g);
protected void transform(double angle)
{
for(int i=0;i<numberOfPoints;i++){
transX[i]=(int)( (baseX[0]-baseX[i]) * Math.cos(angle) -
(baseY[0]-baseY[i]) * Math.sin(angle) +
baseX[0]);
transY[i]=(int)( (baseX[0]-baseX[i]) * Math.sin(angle) +
(baseY[0]-baseY[i]) * Math.cos(angle) +
baseY[0]);
}
}
}
class sweepHand extends clockHand
{
public sweepHand(int originX,int originY, int length, int points)
{
super(originX,originY,length,0,points);
}
protected void initiallizePoints(int originX,int originY, int length, int unused)
{
unused=unused; //We don't use the thickness parameter in this class
//This comes from habit to prevent compiler warning
//concerning unused arguments.
baseX[0]=originX; baseY[0]=originY;
baseX[1]=originX; baseY[1]=originY-length/5;
baseX[2]=originX; baseY[2]=originY+length;
}
public void draw(Color color, double angle, Graphics g)
{
transform(angle);
g.setColor(color);
g.drawLine(transX[1],transY[1],transX[2],transY[2]);
}
}
class hmHand extends clockHand
{
public hmHand(int originX,int originY, int length,int thickness, int points){
super(originX,originY,length,thickness,points);
}
protected void initiallizePoints( int originX,
int originY,
int length,
int thickness)
{
baseX[0]=originX;
baseY[0]=originY;
baseX[1]=baseX[0]-thickness/2;
baseY[1]=baseY[0]+thickness/2;
baseX[2]=baseX[1];
baseY[2]=baseY[0]+length- thickness;
baseX[3]=baseX[0];
baseY[3]=baseY[0]+length;
baseX[4]=baseX[0]+thickness/2;
baseY[4]=baseY[2];
baseX[5]=baseX[4];
baseY[5]=baseY[1];
}
public void draw(Color color,double angle, Graphics g)
{
transform(angle);
g.setColor(color);
g.fillPolygon(transX,transY,numberOfPoints);
}
}
public class Javex extends Applet implements Runnable
{
//JAVADRAW Wizard.Cut.Start
String AText = "SFS Software";
Font AFont = new Font ("TimesRoman", Font.PLAIN, 10);
Color ABackgroundcolor = Color.black;
Color AFacecolor = Color.green;
Color ASweepcolor = Color.white;
Color AMinutecolor = Color.red;
Color AHourcolor = Color.magenta;
Color ATextcolor = Color.black;
Color ACasecolor = Color.gray;
Color ATrimcolor = Color.pink;
int width = 100;
int height = 100;
//JAVADRAW Wizard.Cut.End
static final int BACKGROUND=0; //Background image index
static final int LOGO=1; //Logo image index
static final double MINSEC=0.104719755; //Radians per minute or second
static final double HOUR=0.523598776; //Radians per hour
Thread clockThread = null;
//User options, see getParameterInfo(), below.
String logoString=null;
Image images[] = new Image[2]; //Array to hold optional images
boolean isPainted=false; //Force painting on first update, if not painted
//Center point of clock
int x1,y1;
//Array of points for triangular icon at 12:00
int xPoints[]=new int[3], yPoints[]=new int[3];
//Class to hold time, with method to return (double)(hours + minutes/60)
hms cur_time;
//The clock's seconds, minutes, and hours hands.
sweepHand sweep;
hmHand minuteHand,
hourHand;
//The last parameters used to draw the hands.
double lastHour;
int lastMinute,lastSecond;
//Offscreen image and device context, for buffered output.
Image offScrImage;
Graphics offScrGC;
// Use to test background image, if any.
MediaTracker tracker;
int minDimension; // Ensure a round clock if applet is not square.
int originX; // Upper left corner of a square enclosing the clock
int originY; // with respect to applet area.
double tzDifference=0;
//Users' parameters - self-explanatory?
public String[][] getParameterInfo()
{
String[][] info = {
{"bgImageURL", "string", "URL of background image, if any <null>"},
{"logoString", "string", "Name to display on watch face <JAVEX>"},
{"logoImageURL","string", "URL of logo image to display on watch face <null>"},
{"timezone", "real", "Timezone difference from GMT (decimal hours,+ West/- East)<0>"},
};
return info;
}
//Applet name, author and info lines
public String getAppletInfo()
{
return "JAVEX 1.03 - analog clock applet by Bill Giel, 2 Mar 96\nhttp://www.nai.net/~rvdi/home.htm or rvdi@usa.nai.net";
}
void showURLerror(Exception e)
{
String errorMsg = "JAVEX URL error: "+e;
showStatus(errorMsg);
System.err.println(errorMsg);
}
// This lets us create clocks of various sizes, but with the same
// proportions.
private int size(int percent)
{
return (int)((double)percent/100.0 * (double)minDimension);
}
public void init()
{
URL imagesURL[] = new URL[2];
String szImagesURL[] = new String[2];
tracker = new MediaTracker(this);
String paramString = getParameter( "WIDTH" );
if( paramString != null )
width = Integer.valueOf(paramString).intValue();
paramString = getParameter( "HEIGHT" );
if( paramString != null )
height = Integer.valueOf(paramString).intValue();
paramString = getParameter( "TIMEZONE" );
if( paramString != null )
tzDifference = Double.valueOf(paramString).doubleValue();
logoString = getParameter( "LOGOSTRING");
if( logoString == null )
logoString=AText;
else if(logoString.length() > 8)
logoString= logoString.substring(0,8); //Max 8 characters!
szImagesURL[BACKGROUND] = getParameter("BGIMAGEURL");
szImagesURL[LOGO] = getParameter("LOGOIMAGEURL");
for(int i=0; i<2; i++){
if(szImagesURL[i] != null){
try{
imagesURL[i]=new URL(getDocumentBase(),szImagesURL[i]);
} catch (MalformedURLException e)
{
showURLerror(e);
imagesURL[i]=null;
images[i]=null;
}
if(imagesURL[i] != null){
showStatus("Javex loading image: " + imagesURL[i].toString());
images[i]=getImage(imagesURL[i]);
if(images[i] != null)
tracker.addImage(images[i],i);
showStatus("");
}
if(images[i] != null)
try{
tracker.waitForID(i);
}catch (InterruptedException e)
{
images[i]=null;
}
}
else images[i]=null;
}
cur_time=new hms(tzDifference);
lastHour=-1.0;
lastMinute=-1;
lastSecond=-1;
x1=width/2;
y1=height/2;
minDimension= Math.min(width, height);
originX=(width-minDimension)/2;
originY=(height-minDimension)/2;
xPoints[1]=x1-size(3); xPoints[2]=x1+size(3); xPoints[0]=x1;
yPoints[1]=y1-size(38);yPoints[2]=y1-size(38); yPoints[0]=y1-size(27);
sweep=new sweepHand(x1,y1,size(40),3);
minuteHand=new hmHand(x1,y1,size(40),size(6),6);
hourHand=new hmHand(x1,y1,size(25),size(8),6);
offScrImage = createImage(width,height);
offScrGC = offScrImage.getGraphics();
}
public void start()
{
if(clockThread == null){
clockThread = new Thread(this);
clockThread.start();
}
}
public void stop()
{
if(null != clockThread){
clockThread.stop();
clockThread=null;
}
}
private void drawHands(Graphics g)
{
double angle;
int i,j;
int x,y;
angle=MINSEC * lastSecond;
sweep.draw(AFacecolor, angle, g);
if(cur_time.getMinutes() != lastMinute){
minuteHand.draw(AFacecolor,MINSEC*lastMinute,g);
if(cur_time.get_hours() != lastHour)
hourHand.draw(AFacecolor,HOUR*lastHour,g);
}
g.setColor(ATextcolor);
g.fillRect(originX+size(12),y1-size(2),size(10),size(4));
g.fillRect(x1-size(2),originY + minDimension-size(22),size(4),size(10));
g.fillPolygon( xPoints, yPoints, 3);
for(i=1;i<12;i+=3)
for(j=i;j<i+2;j++){
x=(int)(x1+Math.sin(HOUR*j)*size(35));
y=(int)(y1-Math.cos(HOUR*j)*size(35));
g.fillOval(x-size(3),y-size(3),size(6),size(6));
}
//Set the font and get font info...
g.setFont(AFont);
FontMetrics fm=g.getFontMetrics();
//Paint our logo...
g.drawString(logoString,x1-fm.stringWidth(logoString)/2,y1-size(12));
//Get the day of the month...
String day=Integer.toString(cur_time.getDate(),10);
//Paint it...
g.drawString( day,
originX + minDimension-size(14)-fm.stringWidth(day),
y1+size(5));
//and put a box around it.
g.drawRect( originX + minDimension-size(14)-fm.stringWidth(day)-size(2),
y1-size(5)-size(2),
fm.stringWidth(day)+size(4),
size(10)+size(4));
if(images[LOGO] != null){
x = originX + (minDimension-images[LOGO].getWidth(this))/2;
y = y1 + (minDimension/2 - size(22) - images[LOGO].getHeight(this))/2;
if(x > 0 && y > 0)
offScrGC.drawImage(images[LOGO], x, y, this);
}
lastHour=cur_time.get_hours();
hourHand.draw(AHourcolor,HOUR*lastHour,g);
lastMinute=cur_time.getMinutes();
minuteHand.draw(AMinutecolor,MINSEC*lastMinute,g);
g.setColor(AMinutecolor);
g.fillOval(x1-size(4),y1-size(4),size(8),size(8));
g.setColor(ASweepcolor);
g.fillOval(x1-size(3),y1-size(3),size(6),size(6));
lastSecond=cur_time.getSeconds();
angle=MINSEC*lastSecond;
sweep.draw(ASweepcolor, angle,g);
g.setColor(ATrimcolor);
g.fillOval(x1-size(1),y1-size(1),size(2),size(2));
}
private Color parseColorString(String colorString)
{
if(colorString.length()==6){
int R = Integer.valueOf(colorString.substring(0,2),16).intValue();
int G = Integer.valueOf(colorString.substring(2,4),16).intValue();
int B = Integer.valueOf(colorString.substring(4,6),16).intValue();
return new Color(R,G,B);
}
else return Color.lightGray;
}
public void run()
{
//Let's not hog the system, now...
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
repaint();
while(null != clockThread){
cur_time=new hms(tzDifference);
repaint();
try{
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
System.exit(0);
}
public void paint(Graphics g)
{
int i,x0,y0,x2,y2;
if(images[BACKGROUND] == null){
offScrGC.setColor(ABackgroundcolor);
offScrGC.fillRect(0,0,width,height);
}
else
offScrGC.drawImage(images[BACKGROUND], 0, 0, this);
offScrGC.setColor(ACasecolor);
//Shrink one pixel so we don't clip anything off...
offScrGC.fillOval( originX+1,
originY+1,
minDimension-2,
minDimension-2);
offScrGC.setColor(AFacecolor);
offScrGC.fillOval( originX + size(5),
originY + size(5),
minDimension - size(10),
minDimension - size(10));
offScrGC.setColor(ATrimcolor);
offScrGC.drawOval( originX+1,
originY+1,
minDimension-2,
minDimension-2);
offScrGC.drawOval( originX + size(5),
originY + size(5),
minDimension - size(10),
minDimension - size(10));
offScrGC.setColor(ATextcolor);
//Draw graduations, a longer index every fifth mark...
for(i=0;i<60;i++){
if(i==0 || (i>=5 && i%5 == 0)){
x0=(int)(x1+size(40)*Math.sin(MINSEC*i));
y0=(int)(y1+size(40)*Math.cos(MINSEC*i));
}
else{
x0=(int)(x1+size(42)*Math.sin(MINSEC*i));
y0=(int)(y1+size(42)*Math.cos(MINSEC*i));
}
x2=(int)(x1+size(44)*Math.sin(MINSEC*i));
y2=(int)(y1+size(44)*Math.cos(MINSEC*i));
offScrGC.drawLine(x0,y0,x2,y2);
}
drawHands(offScrGC);
g.drawImage(offScrImage,0,0,this);
isPainted=true;
}
public synchronized void update(Graphics g)
{
if(!isPainted)
paint(g);
else{
drawHands(offScrGC);
g.drawImage(offScrImage,0,0,this);
}
}
}