Make your own free website on Tripod.com
/* * DarthFader_1_0.java 2.1 01/03/98 * * Copyright (c) 1997, 1998 by Kevin Swan. All rights reserved. * * I reserve all rights to this software. You may use it and * distribute it freely, provided you do not remove this header * and attribute partial credit to the author, Kevin Swan. * * 27 Feb 1998 Created and released as version 1.0. * 28 Feb 1998 Added mouse event handlers and associated actions. * Released as version 1.1. * 28 Feb 1998 Added directive support. * Modified init () to print version info to stderr. * Released as version 2.0. * 01 Mar 1998 Fixed a bug in the pause() methods, they shouldn't have * been incrementing currLine. * Released as version 2.1. */ import java.util.Vector; import java.applet.*; import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; <--!end comments-->

* This is the Java 1.0 version of DarthFader. * *

This is a simple fader applet, complete with cheesy name. There are * plenty of fader applets out there, but no one seems to want to share * their source code. This is my version of a fader applet, which I will * distribute for free, complete with source code, just like all of my * other projects. * *

If you use this applet, my only request is that you notify me at * 013639s@dragon.acadiau.ca. If you modify this applet and distribute * it, you must leave the header at the top intact, and indicate in your * documentation that your work is derived from mine. * *

The applet accepts the following <PARAM> tags: * *

* * * * * * * * * * * * * * * * * * *
* * data * * * This is the name of the data file to use. It is requested * as a URL relative to the CODEBASE attribute * of the <APPLET> tag. This tag must be * specified. *
* * fontface * * * This is the name of the font face to use. It should be * one of the 3 standard Java font names: *

*

    *
  • Serif *
  • SansSerif *
  • Monospaced *
*

The default is * DarthFader_1_0.DEFAULT_FONT_FACE. *

* * fontsize * * * This is the size to use for the font. The default is * DarthFader_1_0.DEFAULT_FONT_SIZE. *
* * fadespeed * * * This determines how fast the text will fade in and out. It * must be between DarthFader_1_0.MIN_SPEED and * DarthFader_1_0.MAX_SPEED, inclusive. If it is not * specified, the default is * DarthFader_1_0.DEFAULT_FADE_SPEED. *
* * fadeincrement * * * This modifies how fast the text will fade in and out. It * must be a positive number. This is the value added to or * subtracted from the Color values during the fade. If this is * not specified, the default is * DarthFader_1_0.DEFAULT_FADE_INCREMENT. *
* * displaytime * * * This is how many milliseconds to display the message after it * has completed fading in before the applet should begin to fade * it out. The default is * DarthFader_1_0.DEFAULT_DISPLAY_TIME. *
* * @author Kevin Swan, 013639s@dragon.acadiau.ca * @version 2.1, 01 Mar 1998 */ public class DarthFader_1_0 extends Applet implements Runnable { /** * The current version of this applet. */ public static final String VERSION = "2.1"; /** * A constant repreenting the maximum number of milliseconds * the applet may sleep. This is the maximum number a user * may specify as the speed value, and would represent a sleep * time of MIN_SPEED milliseconds. */ public static final int MAX_SPEED = 10; /** * A constant repreenting the minimum number of milliseconds * the applet may sleep. This is the minimum number a user * may specify as the speed value, and would represent a sleep * time of MAX_SPEED milliseconds. */ public static final int MIN_SPEED = 1; /** * A constant representing the default number of milliseconds * the applet should sleep. This value is used for the speed * if the user specifies an invalid value, or none at all. */ public static final int DEFAULT_FADE_SPEED = 5; /** * A constant representing how much to increment or decrement * the color values for each fade. */ public static final int DEFAULT_FADE_INCREMENT = 7; /** * A constant representing the default number of milliseconds * to display the faded-in message. */ public static final int DEFAULT_DISPLAY_TIME = 1000; /** * This is the default font face. */ public static final String DEFAULT_FONT_FACE = "SansSerif"; /** * This is the default font size. */ public static final int DEFAULT_FONT_SIZE = 14; /** * The set of supported directives. */ public static final String[] directives = { "pause", "setFadeSpeed", "setFadeIncrement" }; /** The data to display. */ private String[] data; /** The name of the data file to load. */ private String fileName; /** The line number we're on. */ private int currLine; /** The number of lines in the data file. */ private int numLines; /** The Image to create and use for buffering. */ private Image buffImage; /** The Graphics object from the buffer Image that we can draw on. */ private Graphics buffGraphics; /** The Colors to use. */ private Color bgColor, fgColor, fadeColor; /** The Font to use. */ private Font font; private int fontSize; private String fontFace; /** The height and width of the applet window. */ private int width, height; /** The time to wait displaying the full message before fading out. */ private int displayTime; /** The fade speed. */ private int fadeSpeed; /** How much to add to the color each increment. */ private int fadeIncrement; /** Thread to control the fading. */ private Thread fadeThread; /** boolean to flag if the applet is currently running. */ private boolean running; /** boolean to flag whether we're currently fading in or out. */ private boolean fadeIn; /** * Called during initialization. This is where we check all run-time * flags set by the <PARAM> tags, and load the * text. We will also prepare the text buffer. */ public void init () { this.running = false; String param = null; /* Get and set the dimensions of the applet. */ this.width = this.size ().width; this.height = this.size ().height; this.resize (this.width, this.height); /* Get the desired Font information. */ param = getParameter ("fontsize"); if (param == null) this.fontSize = DarthFader_1_0.DEFAULT_FONT_SIZE; else try { this.fontSize = Integer.parseInt (param); } catch (NumberFormatException nfe) { this.fontSize = DarthFader_1_0.DEFAULT_FONT_SIZE; } param = getParameter ("fontface"); if (param == null) fontFace = DarthFader_1_0.DEFAULT_FONT_FACE; else fontFace = param; this.font = new Font (this.fontFace, 0, this.fontSize); /* Get the name of the file to load. */ param = getParameter ("data"); if (param == null) fileName = null; else fileName = param; /* Set the speed information. */ param = getParameter ("fadespeed"); if (param == null) this.fadeSpeed = DarthFader_1_0.DEFAULT_FADE_SPEED; else try { this.fadeSpeed = Integer.parseInt (param); } catch (NumberFormatException nfe) { this.fadeSpeed = DarthFader_1_0.DEFAULT_FADE_SPEED; } if (this.fadeSpeed > DarthFader_1_0.MAX_SPEED || this.fadeSpeed < DarthFader_1_0.MIN_SPEED) this.fadeSpeed = DarthFader_1_0.DEFAULT_FADE_SPEED; param = getParameter ("fadeincrement"); if (param == null) this.fadeIncrement = DarthFader_1_0.DEFAULT_FADE_INCREMENT; else try { this.fadeIncrement = Integer.parseInt (param); } catch (NumberFormatException nfe) { this.fadeIncrement = DarthFader_1_0.DEFAULT_FADE_INCREMENT; } if (this.fadeIncrement < 0) this.fadeIncrement = DarthFader_1_0.DEFAULT_FADE_INCREMENT; param = getParameter ("displaytime"); if (param == null) this.displayTime = DarthFader_1_0.DEFAULT_DISPLAY_TIME; else try { this.displayTime = Integer.parseInt (param); } catch (NumberFormatException nfe) { this.fadeSpeed = DarthFader_1_0.DEFAULT_DISPLAY_TIME; } this.currLine = -1; this.bgColor = Color.black; this.fgColor = Color.white; this.fadeColor = new Color (this.bgColor.getRGB ()); this.fadeIn = true; this.buffImage = this.createImage (this.width, this.height); this.buffGraphics = this.buffImage.getGraphics (); this.buffGraphics.setColor (this.bgColor); this.buffGraphics.fillRect (0, 0, this.width, this.height); this.buffGraphics.setColor (this.fadeColor); this.buffGraphics.setFont (this.font); this.loadData (); System.err.println ("DarthFader_1_0 v" + DarthFader_1_0.VERSION + "\nCopyright (C) 1998 Kevin Swan, " + "013639s@dragon.acadiau.ca"); } /** * This method is called when the mouse pointer enters the applet. * It should write its information to the status area. * * @param e The actual event. * @param x The x coordinate the event occurred at. * @param y The y coordinate the event occurred at. * * @return true if the event is handed, false otherwise. */ public boolean mouseEnter (Event e, int x, int y) { this.showStatus ("DarthFader_1_0 v" + DarthFader_1_0.VERSION); return true; } /** * This method is called when the mouse pointer exitss the applet. * It should clear the status area. * * @param e The actual event. * @param x The x coordinate the event occurred at. * @param y The y coordinate the event occurred at. * * @return true if the event is handed, false otherwise. */ public boolean mouseExit (Event e, int x, int y) { this.showStatus (""); return true; } /** * This method is called when the mouse is clicked. * It should take the user to the homepage of this applet. * * @param e The actual event. * @param x The x coordinate the event occurred at. * @param y The y coordinate the event occurred at. * * @return true if the event is handed, false otherwise. */ public boolean mouseDown (Event e, int x, int y) { this.toggle (); return true; } /** * This method loads the textual data that we want to display from over * the network. It is called by init(). */ private void loadData () { if (fileName == null) { this.numLines = 1; this.data = new String[this.numLines]; this.data[0] = "No \"data\" parameter specified."; return; } URL dataFile = null; URLConnection dataConnection = null; DataInputStream dis = null; try { dataFile = new URL (getCodeBase (), fileName); } catch (MalformedURLException mue) { this.numLines = 1; this.data = new String[this.numLines]; this.data[0] = "Caught MalformedURLException accessing data file."; return; } try { dataConnection = dataFile.openConnection (); } catch (IOException ioe) { this.numLines = 1; this.data = new String[this.numLines]; this.data[0] = "Caught IOException opening a connection to the data file."; return; } try { dis = new DataInputStream (dataConnection.getInputStream ()); } catch (IOException ioe) { this.numLines = 1; this.data = new String[this.numLines]; this.data[0] = "Caught IOException opening stream on data file."; return; } String line = null; Vector data = new Vector (); int index; this.showStatus ("Retrieving data ..."); while (true) { try { line = dis.readLine (); } catch (IOException ioe) { /* Hope we're at EOF. */ break; } if (line == null) break; data.addElement (line); } // while this.numLines = data.size (); this.data = new String[this.numLines]; for (int i = 0 ; i < data.size () ; i++) this.data[i] = new String ((String) data.elementAt (i)); try { dis.close (); } catch (IOException ioe) { System.err.println ("IOException closing DataInputStream on text data."); } this.showStatus (""); } /* loadData () */ /** * Called to start the applet. If the applet has been running * before, we will pick up where we left off. */ public void start () { running = true; (fadeThread = new Thread (this)).start (); } /** * Stop the applet. */ public void stop () { running = false; if (fadeThread != null) fadeThread.stop (); } /** * If the Applet is running, stop it. If it is stopped, restart it. */ public void toggle () { if (this.running) this.stop (); else this.start (); } /** * Called to update the screen. */ public void update (Graphics g) { this.paint (g); } /** * Called to paint the screen. */ public void paint (Graphics g) { g.drawImage (this.buffImage, 0, 0, this); } /** * The implementation of the run () method, as required * by implementing the Runnable interface. This method * performs the actual animation. */ public void run () { while (running) { if (isLighterOrEqual (fadeColor, fgColor)) { try { fadeThread.sleep (displayTime); } catch (InterruptedException ie) { } fadeIn = false; } else if (isDarkerOrEqual (fadeColor, bgColor)) { fadeIn = true; currLine = (currLine >= (numLines - 1)) ? 0 : currLine + 1; /* * We've just incremented the line count. If the next line * is a directive, we want to handle it and try again. */ String line = this.data [currLine]; while (line.startsWith ("^^")) { /* Handle the directive */ /* Strip off the leading "^^" */ line = line.substring (2, line.length ()); this.serviceDirective (line); currLine = (currLine >= (numLines - 1)) ? 0 : currLine + 1; line = this.data [currLine]; } } if (fadeIn) { if (fadeColor.getRed () + fadeIncrement > 255) fadeColor = new Color (255, 255, 255); else fadeColor = new Color ( fadeColor.getRed () + fadeIncrement, fadeColor.getGreen () + fadeIncrement, fadeColor.getBlue () + fadeIncrement ); } else { if (fadeColor.getRed () - fadeIncrement < 0) fadeColor = new Color (0, 0, 0); else fadeColor = new Color ( fadeColor.getRed () - fadeIncrement, fadeColor.getGreen () - fadeIncrement, fadeColor.getBlue () - fadeIncrement ); } /* Update the buffer. */ this.buffGraphics.setColor (fadeColor); String line = this.data [currLine]; FontMetrics fm = this.getToolkit ().getFontMetrics (this.font); int length = fm.stringWidth (line); int xstart = (this.width / 2) - (length / 2); xstart = (xstart < 0) ? 0 : xstart; int ystart = (this.height / 2) + (fm.getDescent () / 2); ystart = (ystart < fm.getHeight ()) ? fm.getHeight() : ystart; this.buffGraphics.drawString (line, xstart, ystart); try { fadeThread.sleep (5 * (DarthFader_1_0.MAX_SPEED + 1 - fadeSpeed)); } catch (InterruptedException ie) { } repaint (); } /* while */ } /** * This method is used to determine whether or not a directive the * user is attempting to use is supported. This is done for security * reasons, to protect the user from accidentally calling methods * they shouldn't be in Applet and its superclasses. * * @param methodName the name of the method the user is trying to use. * * @return true if the user is permitted to call the named method, * false otherwise. */ public static boolean supportedDirective (String methodName) { for (int i = 0 ; i < directives.length ; i++) if (directives[i].equals (methodName)) return true; return false; } /** * This method is unique to the Java 1.0 version. This is how we * will handle directives, since we cannot take advantage of * the reflection API. * * @param command The directive we are to service, without the * "^^" characters at the front. This is simply * a method name, followed by 0 or more whitespace, * followed by a ( character, then a string argument, then * a ) character. */ public void serviceDirective (String command) { String methodName = command.substring (0, command.indexOf ('(')); methodName = methodName.trim (); if (!supportedDirective (methodName)) { System.err.println ("Unsupported directive: \"" + methodName + "\""); return; } String arg = command.substring (command.indexOf ('(') + 1, command.indexOf(')')); if (methodName.equals ("pause")) if (arg.length () > 0) this.pause (arg); else this.pause (); else if (methodName.equals ("setFadeSpeed")) this.setFadeSpeed (arg); else if (methodName.equals ("setFadeIncrement")) this.setFadeIncrement (arg); else System.err.println ("Logic Error! \"" + methodName + "\" was reported to be legal, but could not be handled!"); return; } /** * Try and pause for the given number of milliseconds. Note that the * time is given as a String. * * @param time a String that should be able to be converted to an * Integer. */ public void pause (String timeStr) { Integer time; try { time = Integer.valueOf (timeStr); } catch (NumberFormatException nfe) { System.err.println ( "Error: Invalid integer specified for pause (): \"" + timeStr + "\""); return; } try { this.fadeThread.sleep (time.intValue ()); } catch (InterruptedException ie) { } return; } /** * This is simply a way for the user to call toggle () * as a directive. This was done to relieve confusion, so the user * can simply use pause () with or without an argument * to cause the applet to pause scrolling. If it is called with * no arguments, this method is called, and the scrolling stops * until the user clicks the text area. * */ public void pause () { this.toggle (); } /** * This method allows the user to dynamically alter the fade speed. * The given argument must be a number in the form of a String, and * it must be between DarthFader_1_0.MIN_SPEED and * DarthFader_1_0.MAX_SPEED. * * @param speedStr A String holding a number to use as the fadeSpeed * value. */ public void setFadeSpeed (String speedStr) { int val; try { val = Integer.parseInt (speedStr); } catch (NumberFormatException nfe) { System.err.println ( "Invalid argument in setFadeSpeed() directive: " + speedStr + "\nExpected an integer value."); return; } if (val < DarthFader_1_0.MIN_SPEED || val > DarthFader_1_0.MAX_SPEED) System.err.println ( "Invalid argument in setFadeSpeed() directive: " + speedStr + "\nOut of range."); else this.fadeSpeed = val; return; } /** * This method allows the user to dynamically alter the fade increment. * The given argument must be a number in the form of a String, and * it must be positive. * * @param incStr A String holding a number to use as the fadeIncrement * value. */ public void setFadeIncrement (String incStr) { int val; try { val = Integer.parseInt (incStr); } catch (NumberFormatException nfe) { System.err.println ( "Invalid argument in setFadeIncrement() directive: " + incStr + "\nExpected an integer value."); return; } if (val < DarthFader_1_0.MIN_SPEED || val > DarthFader_1_0.MAX_SPEED) System.err.println ( "Invalid argument in setFadeIncrement() directive: " + incStr + "\nOut of range."); else this.fadeIncrement = val; return; } /** * Tests the two Colors to see if the first is darker than or equal * to the other. * * @param color1 The first Color. * @param color2 The second Color. * * @return true if the first color is darker than or equal to the * second, or false otherwise. */ private boolean isDarkerOrEqual (Color color1, Color color2) { if (color1.getRed () <= color2.getRed () && color1.getBlue () <= color2.getBlue () && color1.getGreen () <= color2.getGreen ()) return true; if (color1.getRGB () <= color2.getRGB ()) return true; return false; } /** * Tests the two Colors to see if the first is lighter than or equal * to the other. * * @param color1 The first Color. * @param color2 The second Color. * * @return true if the first color is lighter than or equal to the * second, or false otherwise. */ private boolean isLighterOrEqual (Color color1, Color color2) { if (color1.getRed () >= color2.getRed () && color1.getBlue () >= color2.getBlue () && color1.getGreen () >= color2.getGreen ()) { return true; } if (color1.getRGB () >= color2.getRGB ()) { return true; } return false; } }