/* FadingText 1.01 Jim Nelson, 19 May 1996 jnelson@crl.com http://www.crl.com/~jnelson/ Copyright (c) 1996 Jim Nelson (jnelson@crl.com). All rights reserved. Permission to re-distribute this applet granted by the author. No warranties are made on the fitness of this program or its source code. Description: FadingText will "fade" various text messages in and out of view. It supports up to eight messages, a few palettes of colors, and adjustable timing. Optionally, URLs can be associated with the any or all of the messages, which the browser will jump to if the user clicks on the message. The URL will be displayed in the status bar if the mouse is held over the message as it's displayed. Applet parameters: text[1-8]: up to eight messages can be added as parameters. (optional, although at least one required to make this useful). url[1-8]: each text message can have an associated URL that the browser will jump to if the applet is clicked on while that message is in view. (optional) fadeDelay: time (in milliseconds) to delay between text colorizations (fading). (optional, 100 msec default). holdDelay: time (in milliseconds) to delay once the text has completely faded into view. (optional, 750 msec default). blankDelay: time (in milliseconds) to delay once the text has completely faded out of view, (optional, 750 msec default). palette: describes the background and foreground colors. The choices currently are: BLACKTOWHITE WHITETOBLACK BLACKTOYELLOW (optional, default is WHITETOBLACK) fontSize: the size of the font to use in points. (optional, 36 point size is default). Example: Notes: This class is the first Java applet or application I've written. I used the NervousText class as a "shell" to get me started, so kudos to the respective authors of that class. Bugs: Although there's technically nothing wrong with specifying text parameters non-sequentially (i.e. "text1", and "text3" with no "text2"), the applet currently won't handle it properly. Note that this is *not* true for the URL parameters. The URLs must be relative. Absolute URLs aren't supported right now. The applet cannot handled being resized once started. Not an issue with the code here, but if subclassed or cannibalized for another applet, beware. Wishlist: border: specifies the size of the border to place around the applet. The color of the border is the same as the text when in full view. (optional, default is 0 which is no border) */ import java.applet.Applet; import java.applet.AppletContext; import java.awt.*; import java.net.URL; import java.net.MalformedURLException; public class FadingText extends Applet implements Runnable { // // constants // static final int fadeMsgMax = 8; static final int fadeStepMax = 4; static final int fadeDelayDefault = 100; static final int holdDelayDefault = 750; static final int blankDelayDefault = 750; static final int fontSizeDefault = 36; // // palettes // static final Color whiteToBlackPalette[] = { Color.white, Color.lightGray, Color.gray, Color.black }; static final Color blackToWhitePalette[] = { Color.black, Color.gray, Color.lightGray, Color.white }; static final Color blackToYellowPalette[] = { Color.black, Color.gray, Color.orange, Color.yellow }; // // variables // Color [] fadeArray = null; String msgArray[] = { null, null, null, null, null, null, null, null }; URL msgUrl[] = { null, null, null, null, null, null, null, null }; int msgX[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int msgY[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int msgCount = 0; int currentMsg = 0; int colorCtr = 0; boolean fadeInText = true; Thread updateThread = null; int fadeDelay = fadeDelayDefault; int holdDelay = holdDelayDefault; int blankDelay = blankDelayDefault; int fontHeight; int fontSize = fontSizeDefault; boolean mouseInApplet = false; boolean displayedMessage = false; Dimension appletDimensions = null; // // methods // public String getAppletInfo() { return "FadingText 1.00, copyright (c) 1996 Jim Nelson (jnelson@crl.com)"; } public void init() { String param; int ctr; // have at least one param for testing/debugging of applet msgArray[0] = getParameter("text1"); if(msgArray[0] == null) { msgArray[0] = "Your message here."; } msgCount++; // read in the rest of the text parameters for(ctr = 1; ctr < fadeMsgMax; ctr++) { String paramName = "text" + (ctr + 1); msgArray[ctr] = getParameter(paramName); if(msgArray[ctr] != null) { msgCount++; } } // read in the URL parameters for(ctr = 0; ctr < fadeMsgMax; ctr++) { String paramName = "url" + (ctr + 1); param = getParameter(paramName); if(param != null) { try { msgUrl[ctr] = new URL(getDocumentBase(), param); } catch(MalformedURLException m) { } } } param = getParameter("holdDelay"); if(param != null) { holdDelay = Integer.parseInt(param); } param = getParameter("fadeDelay"); if(param != null) { fadeDelay = Integer.parseInt(param); } param = getParameter("blankDelay"); if(param != null) { blankDelay = Integer.parseInt(param); } param = getParameter("fontSize"); if(param != null) { fontSize = Integer.parseInt(param); } // default palette is white background to black foreground fadeArray = whiteToBlackPalette; // if a palette is specified, go with it param = getParameter("palette"); if(param != null) { if(param.equalsIgnoreCase("BLACKTOWHITE")) { fadeArray = blackToWhitePalette; } else if(param.equalsIgnoreCase("WHITETOBLACK")) { fadeArray = whiteToBlackPalette; } else if(param.equalsIgnoreCase("BLACKTOYELLOW")) { fadeArray = blackToYellowPalette; } } // get the applet's size Dimension appletDimensions = size(); // clear the background setBackground(fadeArray[0]); // set up the font and get font information setFont(new Font("TimesRoman", Font.BOLD, fontSize)); fontHeight = getGraphics().getFontMetrics(getFont()).getHeight(); // precalculate the font X and Y position in the applet box for(ctr = 0; ctr < fadeMsgMax; ctr++) { if(msgArray[ctr] == null) { continue; } msgX[ctr] = (appletDimensions.width - getGraphics().getFontMetrics().stringWidth(msgArray[ctr])) / 2; if(msgX[ctr] < 0) { msgX[ctr] = 0; } msgY[ctr] = (appletDimensions.height - fontHeight) / 2; // add back in the font height because the y-coordinate // describes the *base* of the font, not the top msgY[ctr] += fontHeight; if(msgY[ctr] < 0) { msgY[ctr] = 0; } } } public void start() { if(updateThread == null) { updateThread = new Thread(this); updateThread.start(); } } public void stop() { updateThread = null; } public void run() { while(updateThread != null) { // pause the thread the configured amount of time (depends // on what stage of displaying the text the thread is at) try { if(colorCtr == 0) { Thread.sleep(blankDelay); } else if(colorCtr == (fadeStepMax - 1)) { Thread.sleep(holdDelay); } else { Thread.sleep(fadeDelay); } } catch (InterruptedException e) { } // move the color counter up or down, depending on the // "direction" the fade is travelling if(fadeInText == true) { if(++colorCtr >= fadeStepMax) { // message has faded into view, time to start winding down colorCtr = fadeStepMax - 1; fadeInText = false; } } else { if(--colorCtr < 0) { colorCtr = 0; fadeInText = true; // text has faded out, time to switch messages if(++currentMsg >= msgCount) { // end of messages, roll over to the first one currentMsg = 0; } } } // some changes have been made, repaint the whole she-bang repaint(); // update the status bar UpdateStatusBar(); } } // overriden to avoid flickering public void update(Graphics g) { if(colorCtr == 0) { super.update(g); } else { paint(g); } } public void paint(Graphics g) { // anything to display for this round? if(msgArray[currentMsg] == null) { // nope return; } // if the colorCtr is 0, then update() took care of blanking the // component if(colorCtr != 0) { // set the current fade color g.setColor(fadeArray[colorCtr]); // print the string in the right spot g.drawString(msgArray[currentMsg], msgX[currentMsg], msgY[currentMsg]); } } // if the user runs the mouse over the message, display its URL (if // any) in the status bar public boolean mouseEnter(Event event, int x, int y) { mouseInApplet = true; UpdateStatusBar(); return true; } // likewise, need to know when the user moves the mouse out of the applet // clear the status bar to blank any lingering messages (if any were // displayed) public boolean mouseExit(Event event, int x, int y) { mouseInApplet = false; if(displayedMessage == true) { getAppletContext().showStatus(""); displayedMessage = false; } return true; } // if user clicks on applet, will jump to URL (if one was specified // in applet parameters) public boolean mouseDown(Event event, int x, int y) { // see if a message is visible and it has an URL if((colorCtr != 0) && (msgUrl[currentMsg] != null)) { // jump to that URL getAppletContext().showDocument(msgUrl[currentMsg]); } return true; } // if (a) the mouse is over the applet, (b) a message is being displayed, // and (c) that message has an associated URL, display the URL in the // status bar ... otherwise, if a message had been displayed, clear it public void UpdateStatusBar() { if((mouseInApplet == true) && (colorCtr != 0) && (msgUrl[currentMsg] != null)) { getAppletContext().showStatus(msgUrl[currentMsg].toString()); displayedMessage = true; } else if(displayedMessage == true) { getAppletContext().showStatus(""); } } }