home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Gallery
/
INTERGAL.bin
/
intergal
/
prgs
/
idv21
/
data.z
/
FunScroll.java
< prev
next >
Wrap
Text File
|
1996-12-07
|
61KB
|
2,126 lines
/*
* Copyright (c) 1996 by Jan Andersson, Torpa Konsult AB.
*
* Permission to use, copy, and distribute this software for
* NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*/
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.awt.*;
/**
* FunScroll - A Funnier (?) scrolling text applet.
*
* @version 1.27 96/09/06
* @author Jan Andersson (janne@torpa.se)
*
*/
public class FunScroll extends Applet implements Runnable
{
static final int MaxLines = 50; // max no. of line parameters
static final int ShadowIn = 0; // frame types:
static final int ShadowOut = 1;
static final int ShadowEtchedIn = 2;
static final int ShadowEtchedOut = 3;
Image bgImage = null; // backgound image
Image tiledBgImage = null; // tiled backgound image
MediaTracker mediaTracker; // to track loading of backgound image
Thread thread = null; // animation thread
ThreadGroup threadGroup = null; // animation thread group
boolean suspended = false; // animation thread suspended
int threadDelay = 100; // animation thread delay
String lineData = null; // line data file (url)
int updateInterval = 0; // update interval (to read data file)
int animateCount = 0; // reload data (from data file)
Font font = null; // default font
int dx = 3; // delta x
int dy = 2; // delta y
String delim = null; // text attribute delimiters
long threadStartTime; // time thread started
Vector animatedTexts = null; // animated texts
Vector urlStrings = null; // associated url's
String urlTarget = null; // target widow or frame
int noOfTexts = 0; // number of texts
int currentTextIndex = 0; // current text index
FunScrollAnimatedText currentText; // current text instance
int frameWidth = 0; // frame width
int frameType = ShadowIn; // frame type
int frameMargin = 0; // frame margin
Color frameDark1 = null; // darker frame color
Color frameDark2 = null; // (slightly) darker frame color
Color frameBright = null; // brighter frame color
Image offImage; // "off-screen" image
Graphics offGraphics; // "off-screen" graphics
Dimension offSize; // "off-screen" size
Dimension textSize; // textArea size
protected boolean initiated = false; // true when initiated
static final boolean debug = false;// debug flag
static final String sourceLocation =
"http://www.algonet.se/FunScroll/FunScroll.html";
static final String versionInfo =
"FunScroll 2.3";
/**
* Init applet
*/
public void init()
{
// we need a few parameters to draw the initial message...
// get color parameters
Color fg = readColor(getParameter("fgColor"), Color.black);
//ID Insert Mark 2
setForeground(fg);
setBackground(bg);
// create the initial offscreen graphics context
offSize = size();
offImage = createImage(offSize.width, offSize.height);
offGraphics = offImage.getGraphics();
// get current Thread group
threadGroup = Thread.currentThread().getThreadGroup();
}
/**
* Init parameters and create animated text instances
*/
public void initParameters()
{
Vector lineVector = new Vector();
urlStrings = new Vector();
String par = getParameter("lineData");
if (par != null) {
lineData = par;
initLineParametersFromInputURL(lineData, lineVector, urlStrings);
par = getParameter("updateInterval");
if (par != null)
updateInterval = Integer.valueOf(par).intValue();
}
else
initLineParameters(lineVector, urlStrings);
// init frame (border) params
par = getParameter("frameWidth");
if (par != null)
frameWidth = Integer.valueOf(par).intValue();
par = getParameter("frameMargin");
if (par != null)
frameMargin = Integer.valueOf(par).intValue();
par = getParameter("frameType");
if (par != null) {
if (par.equalsIgnoreCase("ShadowOut"))
frameType = ShadowOut;
else if (par.equalsIgnoreCase("ShadowEtchedIn"))
frameType = ShadowEtchedIn;
else if (par.equalsIgnoreCase("ShadowEtchedOut"))
frameType = ShadowEtchedOut;
else
frameType = ShadowIn;
}
// get frame/window target
urlTarget = getParameter("target");
//ID Insert Mark 4
mediaTracker = new MediaTracker(this);
mediaTracker.addImage(bgImage, 0);
// get font parameters
//ID Insert Mark 3
if (fontName == null)
fontName = "TimesRoman";
int style = Font.BOLD;
if (fontStyle != null) {
if (fontStyle.equalsIgnoreCase("plain"))
style = Font.PLAIN;
else if (fontStyle.equalsIgnoreCase("bold"))
style = Font.BOLD;
else if (fontStyle.equalsIgnoreCase("italic"))
style = Font.ITALIC;
}
if (fontSize == null)
fontSize = "24";
int size = Integer.valueOf(fontSize).intValue();
// make sure fonts are created with the right size
// Note: size-parameter are plattform dependent and the
// only way to get the same size on all plattforms is to
// check the "real" size using FontMetrics.
// Note: we only loop until "real" size if less than 6
// or size differs more that 3 pixels...
FontMetrics fm;
int realSize = size;
dbg("init font...");
do {
dbg("trying: " + fontName + "," + realSize);
font = new Font(fontName, style, realSize--);
fm = getFontMetrics(font);
} while ((fm.getDescent() + fm.getAscent()) > size &&
realSize >= size-3 && size >= 6);
if (realSize < size-3 || size < 6)
// assume weird font used... Use parsed size.
font = new Font(fontName, style, size);
// get animation thread delay time
par = getParameter("delay");
if (par != null)
threadDelay = Integer.valueOf(par).intValue();
// get dx/dy movement
par = getParameter("dx");
if (par != null)
dx = Integer.valueOf(par).intValue();
par = getParameter("dy");
if (par != null)
dy = Integer.valueOf(par).intValue();
// get delimiters string
delim = getParameter("delim");
// create animated texts
createAnimatedTexts(lineVector,
font, getForeground(), getBackground(),
dx, dy, delim);
initiated = true;
}
/**
* Gets a parameter of the applet.
*
* Use this function to overload java.applet.Applet.getParameter
* to handle ISO Latin 1 characters correctly in Netscape 2.0.
* Following a suggestion from Peter Sylvester,
* Peter.Sylvester@edelweb.fr.
*
* Note: this is a work-a-round for a bug in Netscape and should
* be removed!
*/
public String getParameter(String s) {
String tmp = super.getParameter(s);
if (tmp == null)
return null;
char ec[] = tmp.toCharArray();
for (int i=0; i < ec.length; i++) {
if (ec[i] >= 0xff00)
ec[i] &= 0x00ff ;
}
return(new String(ec)) ;
}
/**
* Init unparsed line parameters (Vector of Strings) and
* (possibly) associated url's.
*/
protected void initLineParameters(Vector lineVector, Vector urlVector)
{
// get unparsed line parameters
dbg("get line parameters...");
for (int i=0; i<MaxLines; i++) {
String lineParName = "line" + i;
String linePar=getParameter(lineParName);
String urlParName = "url" + i;
String urlPar = getParameter(urlParName);
if (linePar != null) {
dbg(" " + lineParName + ":" + linePar);
lineVector.addElement(linePar);
dbg(" " + urlParName + ":" + urlPar);
urlVector.addElement(urlPar);
}
}
if (lineVector.size() <= 0)
// assume no line parameter provided; use default
initDefaultLineParameters(lineVector);
}
/**
* Init unparsed line parameters (Vector of Strings) and
* (possibly) associated url's from input file.
*/
protected void initLineParametersFromInputURL(
String urlString, Vector lineVector, Vector urlVector) {
// create URL
URL url = null;
DataInputStream is = null;
// 1'st, try URL in context of document
try {
url = new URL(getDocumentBase(), urlString);
is = new DataInputStream(url.openStream());
} catch (Exception e) {
is = null;
}
if (is == null) {
// then try URL directly
try {
url = new URL(urlString);
is = new DataInputStream(url.openStream());
} catch (Exception e) {
dbg("initLineParametersFromInputURL(): Can't read URL");
initURLErrorLineParameters(urlString, lineVector);
updateInterval = 0;
return;
}
}
// read from input stream
try {
String line = null;
line = is.readLine();
while (line != null) {
// add to line vector
if (line.length() > 0)
lineVector.addElement(line);
line = is.readLine();
// add to url vector
if (line != null && line.length() > 4 &&
line.substring(0, 4).equalsIgnoreCase("URL:")) {
// assume url specified...
urlVector.addElement(line.substring(4));
line = is.readLine();
}
else {
urlVector.addElement(null);
}
}
is.close();
}
catch (IOException e) {
// ignore (?)
}
if (lineVector.size() <= 0) {
// assume no line parameter provided; use error message
dbg("initLineParametersFromInputURL(): No lines!");
initURLErrorLineParameters(urlString, lineVector);
updateInterval = 0;
}
}
/**
* Init default line parameters (Vector of Strings).
* Used when not line parameters specified.
*/
protected void initDefaultLineParameters(Vector v)
{
//ID Insert Mark 1
}
/**
* Init error line parameters (Vector of Strings).
* Used at error, when trying to get input from URL.
*/
protected void initURLErrorLineParameters(String url, Vector v) {
v.addElement("<nervous><30><color=#FF0000>Error!");
v.addElement("<100>Could not read url: " + url);
}
/**
* Applet Info.
*/
public String getAppletInfo() {
return versionInfo;
}
/**
* Parameter Info.
*/
public String[][] getParameterInfo() {
// More should be added...
String[][] info = {
{"line<n>", "string", "Message line <n>" },
{"url<n>", "string", "URL <n>" },
{"lineData","string", "Message line data file" },
{"updateInterval", "int", "Update interval to read data file (0)" },
{"delim", "string", "Delimiter string (<>)" },
{"frameWidth", "int", "Frame border width (0)" },
{"frameMargin", "int", "Frame margin width (0)" },
{"frameType", "string", "Frame type (ShadowIn)" },
{"font", "string", "Message font (TimesRoman)" },
{"style", "string", "Message font style (bold)" },
{"size", "int", "Message font size (22)" },
{"delay", "int", "Animation delay time in millisec. (100)" },
{"dx", "int",
"No of pixels to move horizontally for each animation (2)" },
{"dy", "int",
"No of pixels to move vertically for each animation (1)" },
{"fgColor", "string", "Foreground Color" },
{"bgColor", "string", "Background Color" },
};
return info;
}
/**
* Convert a Hexadecimal String with RGB-Values to Color
* Uses aDefault, if no or not enough RGB-Values
*/
public Color readColor(String aColor, Color aDefault) {
if (aColor == null)
return aDefault;
Integer rgbValue = null;
try {
if (aColor.startsWith("#"))
rgbValue = Integer.valueOf(aColor.substring(1), 16);
else if (aColor.startsWith("0x"))
rgbValue = Integer.valueOf(aColor.substring(2), 16);
else
// assume symbolic color name
rgbValue = Integer.valueOf(FunScrollColorSupport.lookup(aColor), 16);
} catch (NumberFormatException e) {
rgbValue = null;
}
if (rgbValue == null)
return aDefault;
return new Color(rgbValue.intValue());
}
/**
* Create animated text vector. I.e vector with FunScrollAnimatedText
* instances.
*/
public void createAnimatedTexts(Vector lines, Font font,
Color fg, Color bg,
int dx, int dy,
String delim)
{
noOfTexts = 0;
animatedTexts = new Vector(lines.size());
dbg("Creating Animated Text...");
for (int i=0; i<lines.size(); i++) {
dbg(" " + (String) lines.elementAt(i));
animatedTexts.addElement(
new FunScrollAnimatedText(
this, (String) lines.elementAt(i), font,
fg, bg, dx, dy, delim));
noOfTexts++;
}
currentTextIndex = 0;
currentText = (FunScrollAnimatedText)
animatedTexts.elementAt(currentTextIndex);
offImage = null; // to be sure...
}
/**
* Animate the texts
*/
public void animate(Graphics g, int offset, int width, int height) {
// update current text
if (currentText.update(g)) {
// done; get next text
currentTextIndex++;
if (currentTextIndex >= noOfTexts) {
// all text lines animated
if (lineData != null && updateInterval > 0)
animateCount++;
currentTextIndex = 0;
}
currentText = (FunScrollAnimatedText)
animatedTexts.elementAt(currentTextIndex);
currentText.reset(offset, width, height, g);
}
}
/**
* Paint tiled background image.
* Based on code by Tony Kolman, 02/20/96.
*
* Note: there are performance problems here.
*/
public void paintTiledImage(Graphics g, Image im,
int offset, int width, int height) {
if (tiledBgImage == null) {
int imgw = im.getWidth(null);
int imgh = im.getHeight(null);
if (imgw > 0 && imgh > 0) {
// we have the background image; create tiled background image
tiledBgImage = createImage(width, height);
Graphics tiledBgGraphics = tiledBgImage.getGraphics();
tiledBgGraphics.setColor(getBackground());
tiledBgGraphics.fillRect(0, 0, width, height);
for (int x = 0; x < width; x += imgw) {
for (int y = 0; y < height; y += imgh) {
tiledBgGraphics.drawImage(im, x, y, null);
}
}
}
}
if (tiledBgImage != null) {
g.drawImage(tiledBgImage, offset, offset, null);
}
}
/**
* Paint last animation
*/
public void paint(Graphics g) {
if (offImage != null)
// paint the image onto the screen
g.drawImage(offImage, 0, 0, null);
}
/**
* Paint "loading..." message
*/
public void paintLoadMessage(Graphics g)
{
dbg("paintLoadMessage()");
offGraphics.setColor(getBackground());
offGraphics.fillRect(0, 0, offSize.width, offSize.height);
offGraphics.setColor(getForeground());
offGraphics.drawString("FunScroll: Loading applet...", 10, 10);
// Paint the image onto the screen
g.drawImage(offImage, 0, offSize.height/3 , null);
}
/**
* Draw a frame at the specified position.
*/
protected void drawFrame(Graphics g, int x, int y, int w, int h,
int type, int thickness, int margin)
{
if(thickness <= 0)
return;
if (frameDark1 == null) {
// create frame colors from background
frameDark1 = FunScrollColorSupport.darker(getBackground(), .50);
frameDark2 = FunScrollColorSupport.darker(getBackground(), .10);
frameBright = FunScrollColorSupport.brighter(getBackground(), .50);
}
switch (type) {
case ShadowOut:
for(int i=0;i<thickness;i++) {
// top left
g.setColor(frameBright);
drawTopLeftLines(g, x, y, w, h, i, margin);
// bottom right
g.setColor(frameDark1);
drawBottomRightLines(g, x, y, w, h, i, margin);
}
break;
case ShadowEtchedIn:
for(int i=0;i<thickness;i++) {
// top left
if(i == 0)
g.setColor(frameDark1);
else if (i == thickness-1)
g.setColor(frameBright);
else
g.setColor(frameDark2);
drawTopLeftLines(g, x, y, w, h, i, margin);
// bottom right
if(i == 0)
g.setColor(frameBright);
else if (i == thickness-1)
g.setColor(frameDark1);
else
g.setColor(frameDark2);
drawBottomRightLines(g, x, y, w, h, i, margin);
}
break;
case ShadowEtchedOut:
for(int i=0;i<thickness;i++) {
// top left
if(i == 0)
g.setColor(frameBright);
else if (i == thickness-1)
g.setColor(frameDark1);
else
g.setColor(getBackground());
drawTopLeftLines(g, x, y, w, h, i, margin);
// bottom right
if(i == 0)
g.setColor(frameDark1);
else if (i == thickness-1)
g.setColor(frameBright);
else
g.setColor(getBackground());
drawBottomRightLines(g, x, y, w, h, i, margin);
}
break;
default: // ShadowIn (default)
for(int i=0;i<thickness;i++) {
// top left
g.setColor(frameDark1);
drawTopLeftLines(g, x, y, w, h, i, margin);
// bottom right
g.setColor(frameBright);
drawBottomRightLines(g, x, y, w, h, i, margin);
}
}
// reset background color
g.setColor(getBackground());
}
void drawTopLeftLines(Graphics g,
int x, int y, int w, int h, int i, int margin)
{
g.drawLine(x+margin+i, y+margin+i, x+w-margin-i-1, y+margin+i);
g.drawLine(x+margin+i, y+margin+i, x+margin+i, y+h-margin-i-1);
}
void drawBottomRightLines(Graphics g,
int x, int y, int w, int h, int i, int margin)
{
g.drawLine(x+margin+i, y+h-margin-i-1, x+w-margin-i-1, y+h-margin-i-1);
g.drawLine(x+w-margin-i-1, y+margin+i, x+w-margin-i-1, y+h-margin-i-1);
}
/**
* Update a frame of animation
*
*/
public void update(Graphics g)
{
if (!initiated) {
paintLoadMessage(g);
return;
}
long tm = 0;
if (debug)
tm = System.currentTimeMillis();
// get size of applet
Dimension d = size();
// Create the offscreen graphics context if required
if((offImage == null) ||
(d.width != offSize.width) ||
(d.height != offSize.height)) {
// create off-screen graphics context
offSize = d;
offImage = createImage(d.width, d.height);
offGraphics = offImage.getGraphics();
// init text area size
textSize = new Dimension(d.width-(2*(frameWidth+frameMargin)),
d.height-(2*(frameWidth+frameMargin)));
// reset Animated Text item
currentText.reset(frameMargin+frameWidth,
d.width, d.height, offGraphics);
// paint frame
offGraphics.setColor(getBackground());
offGraphics.fillRect(0, 0, d.width, d.height);
drawFrame(offGraphics,
0, 0, d.width, d.height,
frameType, frameWidth, frameMargin);
// from here on just manipulate the text area, using a
// clip rectangle.
offGraphics.clipRect(frameMargin+frameWidth, frameMargin+frameWidth,
textSize.width, textSize.height);
}
// reset text background
offGraphics.setColor(getBackground());
offGraphics.fillRect(frameMargin+frameWidth, frameMargin+frameWidth,
textSize.width, textSize.height);
if ((bgImage != null) &&
(mediaTracker.statusID(0, true) & MediaTracker.COMPLETE) != 0) {
// background image loaded; paint it
paintTiledImage(offGraphics, bgImage, frameMargin+frameWidth,
textSize.width, textSize.height);
}
// animate text
animate(offGraphics, frameMargin+frameWidth, d.width, d.height);
// paint the image onto the screen
g.drawImage(offImage, 0, 0, null);
dbg("time for update():" + (System.currentTimeMillis() - tm));
}
/**
* Run the loop. This method is called by class Thread.
*/
public void run() {
if (Thread.currentThread() == thread) {
thread.setPriority(Thread.MIN_PRIORITY);
// init parameters (once)
if (!initiated) {
// immediately paint the "Loading.." message
Graphics g = getGraphics();
paintLoadMessage(g);
getToolkit().sync();
initParameters();
}
}
while (Thread.currentThread() == thread) {
// Repaint. I.e call update() to go trough one frame of
// animation.
repaint();
// Delay depending on how far we are behind (to assure
// we really delay as much as requested).
try {
threadStartTime += threadDelay;
int delay = (int) Math.max(
threadDelay/2, threadStartTime - System.currentTimeMillis());
dbg("Sleep:" + delay);
Thread.sleep(delay);
} catch (InterruptedException e) {
break;
}
// reload data from URL if required
if (lineData != null && updateInterval > 0) {
if (animateCount >= updateInterval) {
// reaload line data from URL
dbg("Re-init data from URL");
animateCount = 0;
Vector lineVector = new Vector();
initLineParametersFromInputURL(
lineData, lineVector, urlStrings);
createAnimatedTexts(lineVector, font,
getForeground(), getBackground(),
dx, dy, delim);
}
}
}
}
/**
* Start the applet by forking an animation thread.
*/
public void start() {
repaint();
if (thread == null) {
// create new animate thread (using thread-group saved in init)
if (threadGroup != null)
thread = new Thread(threadGroup, this);
else
thread = new Thread(this);
thread.start();
}
// remember the thread start time
threadStartTime = System.currentTimeMillis();
}
/**
* Stop the applet. The thread will exit because run() exits.
*/
public void stop() {
thread = null;
}
/**
* Take care of mouse-up event to handle Suspend/Resume
* and to show about info.
*/
public boolean mouseUp(Event evt, int x, int y) {
if ((evt.modifiers & Event.SHIFT_MASK) != 0) {
showAbout();
return true;
}
String urlString = null;
if (currentTextIndex < urlStrings.size())
urlString = (String) urlStrings.elementAt(currentTextIndex);
// handle Suspend/Resume
// Note: Netscape 3.0 doesnt like Thread.suspend() so, im
// now existing the thread instead...
if (suspended || thread == null) {
start();
suspended = false;
}
else if (urlString == null) {
stop();
suspended = true;
}
if (suspended)
// show version when suspended (sneak promotion ;-)
showStatus(getAppletInfo() + " - Click to resume.");
else {
if (urlString != null)
// show document as specified in urlString
showDocument(urlString);
else
// tell about about popup...
showStatus(getAppletInfo() + " - Shift-click for info...");
}
return true;
}
/**
* Take care of mouse-enter event to handle show URL (if specified)
*/
public boolean mouseEnter(Event evt, int x, int y) {
showUrl();
return true;
}
/**
* Display "about" popup frame
*/
void showAbout() {
FunScrollAbout about = new FunScrollAbout(getAppletInfo());
about.appendText("\t" + getAppletInfo() + "\n\n");
about.appendText("Copyright (c) 1996 by " +
"Jan Andersson, Torpa Konsult AB.\n\n");
about.appendText("Info, updates and documentation at " +
sourceLocation + "\n\n");
about.appendText("Applet information:\n");
about.appendText(" Document base: " + getDocumentBase()+"\n");
about.appendText(" Code base: " + getCodeBase()+"\n\n");
about.appendText(" Applet parameters:\n");
about.appendText(" width = " + getParameter("WIDTH")+"\n");
about.appendText(" height = " + getParameter("HEIGHT")+"\n\n");
// Display parameter info
about.appendText(" Message lines (line<n> parameters):\n");
for (int i = 0; i < noOfTexts; i++) {
FunScrollAnimatedText txt = (FunScrollAnimatedText)
animatedTexts.elementAt(i);
about.appendText(" line" + i +" = " +
txt.getUnparsedTextLine() + "\n");
about.appendText(" url" + i +" = ");
String urlString = null;
if (i < urlStrings.size())
urlString = (String) urlStrings.elementAt(i);
about.appendText(urlString + "\n");
}
about.appendText("\n Other parameters:\n");
String params[][] = getParameterInfo();
for (int i = 2; i < params.length; i++) {
String parInfo = " " + params[i][0] + " = " +
getParameter(params[i][0]);
if (parInfo.length() <= 17)
parInfo += "\t";
about.appendText(parInfo + "\t [" + params[i][2] + "]\n");
}
about.show();
}
/**
* Display current url in status line.
*/
void showUrl() {
// display current url if specified
if (urlStrings != null && currentTextIndex < urlStrings.size()) {
String urlString =
(String) urlStrings.elementAt(currentTextIndex);
if (urlString != null) {
String tmp = urlString.toUpperCase();
int tIndex = tmp.indexOf("TARGET=");
if (tIndex > 0)
urlString = urlString.substring(0, tIndex);
showStatus(urlString);
}
else
showStatus("");
}
}
/**
* Show document as specified in URL string
*/
void showDocument(String urlString) {
// check if target option specified in URL string
String target = null;
String tmp = urlString.toUpperCase();
int tIndex = tmp.indexOf("TARGET=");
if (tIndex > 0) {
target = urlString.substring(tIndex+7);
urlString = urlString.substring(0, tIndex);
target = target.trim();
dbg("target:" + target);
}
if (target == null)
// use target provided as parameter
target = urlTarget;
// try to get url in context of current document
URL url = null;
try {
url = new URL(getDocumentBase(), urlString);
}
catch (MalformedURLException e) {
showStatus(e.getMessage());
url = null;
}
if (url == null) {
// next, try to get url directly
try {
url = new URL(urlString);
}
catch (MalformedURLException e) {
showStatus(e.getMessage());
url = null;
}
}
// Load URL, using showDocument()
if (url != null) {
showStatus("Loading: " + urlString + "...");
if (target == null)
getAppletContext().showDocument(url);
else
getAppletContext().showDocument(url, target);
}
}
/**
* Simple debug...
*/
static public void dbg(String str) {
if (debug) {
System.out.println("Debug: " + str);
System.out.flush();
}
}
}
/*
* Copyright (c) 1995 by Jan Andersson, Torpa Konsult AB.
*
* Permission to use, copy, and distribute this software for
* NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*/
/**
* FunScroll "about" popup.
*
* @version 1.1 96/07/17
* @author Jan Andersson (janne@torpa.se)
*/
class FunScrollAbout extends Frame
{
static final int rows = 27;
static final int cols = 70;
TextArea info;
Button close;
/**
* Create About popup frame
*/
FunScrollAbout(String label) {
super(label);
add("Center", info = new TextArea(rows, cols));
info.setEditable(false);
//info.setBackground(Color.white);
Panel buttons = new Panel();
add("South", buttons);
buttons.add(close = new Button("Close"));
pack();
}
/**
* Show frame
*/
public void show() {
info.select(0,0);
super.show();
}
/**
* Append text
*/
void appendText(String s) {
info.appendText(s);
}
/**
* Handle window destroy event
*/
public boolean handleEvent(Event e) {
if (e.id == Event.WINDOW_DESTROY) {
dispose();
return true;
}
return super.handleEvent(e);
}
/**
* Handle "close" button action
*/
public boolean action(Event e, Object arg) {
if (e.target == close) {
//hide();
dispose();
return true;
}
return false;
}
}
/*
* Copyright (c) 1995 by Jan Andersson, Torpa Konsult AB.
*
* Permission to use, copy, and distribute this software for
* NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*/
/**
* FunScroll Animated Text(s)
*
* @version 1.8 96/08/31
* @author Jan Andersson (janne@torpa.se)
*/
class FunScrollAnimatedText
{
// states:
static final int START = 0; // start sequence
static final int SHOW = 1; // show sequence
static final int END = 2; // end sequence
static final int DONE = 3; // done sequence
int state = START; // animate state
FunScroll appl; // FunScroll applet
FunScrollTextAttr attr; // attributes
String unparsedText; // unparsed text line
String[] lines; // lines of text
protected int[] lineWidths; // how wide each line is
int noOfLines = 1; // number of lines
char chars[]; // the characters
int noOfChars; // number of characters
int xPos[]; // the x positions
int yPos[]; // the y positions
boolean visible[]; // flags set to true if character visible
int delayCount = 0; // used to delay for a while
int offset; // the offset (x and y)
int width; // the applet width
int height; // the applet height
int textHeight; // text height
int lineHeight; // text line height
Color bg; // background color
Color fg; // foreground color
Color darkBg; // dark background
Color lightDarkBg; // lightdark background
Color brightBg; // bright background
Color brightFg; // bright foreground
Font font; // font
FontMetrics fontMetrics; // font metrics
int ascent; // font ascent
int descent; // font descent
int leading; // font leading
int maxWidth; // max width
int sinDegree; // used for sin-wave text
int xStart; // starting X pos
int yStart; // starting Y pos
int dx; // x distance to move
int dy; // y distance to move
public FunScrollAnimatedText(FunScroll appl, String line,
Font font, Color fg, Color bg,
int dx, int dy, String delim)
{
this.appl = appl;
this.font = font;
this.fg = fg;
this.bg = bg;
this.dy = dy;
this.dx = dx;
this.unparsedText = line;
// parse message line and init attributes
attr = new FunScrollTextAttr(line, delim);
appl.dbg("Parsed Attributes:");
appl.dbg(" msg:" + attr.msg());
appl.dbg(" startScroll:" + attr.startScroll());
appl.dbg(" endScroll:" + attr.endScroll());
appl.dbg(" showDelay:" + attr.showDelay());
appl.dbg(" endDelay:" + attr.endDelay());
appl.dbg(" style:" + attr.style());
appl.dbg(" drawStyle:" + attr.drawStyle());
appl.dbg(" color:" + attr.color());
appl.dbg("dy:" + dy + " dx:" + dx);
// get color attribute (if specified)
if (attr.color() != null)
this.fg = appl.readColor(attr.color(), fg);
appl.dbg(" color:" + fg);
// init font stuff
fontMetrics = appl.getFontMetrics(font);
ascent = fontMetrics.getAscent();
descent = fontMetrics.getDescent();
leading = fontMetrics.getLeading();
// init character related varaiables
String msg = attr.msg();
Vector linesOftext = new Vector();
noOfChars = msg.length();
chars = new char[noOfChars];
msg.getChars(0, noOfChars, chars, 0);
xPos = new int[noOfChars];
yPos = new int[noOfChars];
visible = new boolean[noOfChars];
textHeight = fontMetrics.getHeight();
if (attr.style() == FunScrollTextAttr.NERVOUS ||
attr.style() == FunScrollTextAttr.SINEWAVE)
// need some extra space here!
textHeight += 4;
lineHeight = fontMetrics.getHeight();
int currXPos = 0;
int currYPos = ascent;
boolean escape = false;
boolean newLine = false;
int lineStartIndex = 0;
int i;
for (i = 0; i < noOfChars; i++) {
if (escape) {
// we already have an escape character
if (chars[i] == 'n') {
// got "\n" - line break; i.e line really consists
// of more than one line
chars[i-1] = ' ';
chars[i] = ' ';
newLine = true;
}
escape = false;
}
else if (chars[i] == '\\') {
// escaped characted; wait for next character
escape = true;
}
else {
if (newLine) {
// get line of text
linesOftext.addElement(
msg.substring(lineStartIndex, i-2));
lineStartIndex = i;
// we have a new line
noOfLines++;
textHeight += fontMetrics.getHeight();
currXPos = fontMetrics.charsWidth(chars, 0, i);
currYPos += lineHeight; //descent + ascent;
newLine = false;
}
if (i > 0)
xPos[i] = fontMetrics.charsWidth(chars, 0, i) - currXPos;
else
xPos[i] = currXPos;
maxWidth = Math.max(maxWidth, xPos[i]);
yPos[i] = currYPos;
}
}
if (i > lineStartIndex)
// get line of text
linesOftext.addElement(
msg.substring(lineStartIndex, i));
// init array of lines and line widths
lineWidths = new int[noOfLines];
lines = new String[noOfLines];
for (i=0; i < noOfLines; i++) {
lines[i] = (String)linesOftext.elementAt(i);
lineWidths[i] = fontMetrics.stringWidth(lines[i]);
}
}
/**
* Reset array of x positions
*/
void resetX()
{
int currXPos = 0;
int currYPos = (noOfChars > 0) ? yPos[0] : 0;
for (int i = 0; i < noOfChars; i++) {
if (currYPos != yPos[i]) {
// new line
currXPos = fontMetrics.charsWidth(chars, 0, i);
currYPos = yPos[i];
}
if (i > 0)
xPos[i] = fontMetrics.charsWidth(chars, 0, i) - currXPos;
else
xPos[i] = currXPos;
}
}
/**
* Reset width and height
*/
void reset(int offset, int width, int height, Graphics g)
{
this.offset = offset;
this.width = width;
this.height = height;
int scroll = attr.startScroll();
switch (scroll) {
case FunScrollTextAttr.NONE:
xStart = (width-maxWidth)/2;
yStart = (height-textHeight)/2;
break;
case FunScrollTextAttr.LEFT:
xStart = width-dx-offset;
yStart = (height-textHeight)/2;
break;
case FunScrollTextAttr.RIGHT:
xStart = dx+offset;
yStart = (height-textHeight)/2;
break;
case FunScrollTextAttr.UP:
xStart = (width-maxWidth)/2;
yStart = height-descent-offset;
break;
case FunScrollTextAttr.DOWN:
xStart = (width-maxWidth)/2;
yStart = 0-textHeight+offset;
break;
}
// adjust for offset
width -= 2*offset;
height -= 2*offset;
// Reset array of x positions
resetX();
// reset state
state = START;
FunScroll.dbg("State: START");
// reset font and foreground
g.setFont(font);
g.setColor(fg);
}
public String getUnparsedTextLine()
{
return unparsedText;
}
/**
* Update. I.e move and paint.
*/
boolean update(Graphics g)
{
move();
paint(g);
if (state == DONE && delayCount <= 0)
return true; // we are done!
else
return false;
}
/**
* Move characters
*/
void move()
{
boolean switchState = false;
int scroll = FunScrollTextAttr.NONE;
switch (state) {
case START:
// start sequence
scroll = attr.startScroll();
if (scroll == FunScrollTextAttr.NONE) {
// no animation; just switch state
switchState = true;
}
else {
// some kind of animation; check if all characters displ.
if (textDisplayed(scroll)) {
// yupp; switch state
switchState = true;
}
}
if (!switchState) {
// just move text (scroll)
moveText(scroll);
updateVisible(scroll);
break;
}
// switch state
updateVisible(scroll);
state = SHOW;
FunScroll.dbg("State: SHOW");
delayCount = attr.showDelay();
// fall trough!
case SHOW:
// show sequence
if (--delayCount >= 0) {
// delay. I.e break out
break;
}
// switch state
state = END;
FunScroll.dbg("State: END");
// fall trough!
case END:
// end sequence
// check if all characters still visible
if (updateVisible(attr.endScroll()) == 0 ||
attr.endScroll() == FunScrollTextAttr.NONE) {
// none visible or no end animation; switch state
state = DONE;
FunScroll.dbg("State: DONE");
delayCount = attr.endDelay();
return;
}
else {
moveText(attr.endScroll());
}
break;
case DONE:
// done sequence; just delay
delayCount--;
break;
}
}
/**
* Return true if (all) text is displayed
*/
boolean textDisplayed(int scroll)
{
switch (scroll) {
case FunScrollTextAttr.LEFT:
// scrolling left
if (maxWidth > width) {
// text is wider that applet width
if (maxWidth+xStart < width-4*dx)
return true;
}
else {
int appletMidPoint = width/2;
int textMidPoint = xStart+maxWidth/2;
if (textMidPoint <= appletMidPoint)
return true;
}
break;
case FunScrollTextAttr.RIGHT:
// scrolling right
if (maxWidth > width) {
// text is wider that applet width
if (xPos[0]+xStart > 4*dx)
return true;
}
else {
int appletMidPoint = width/2;
int textMidPoint = xStart+maxWidth/2;
if (textMidPoint >= appletMidPoint)
return true;
}
break;
case FunScrollTextAttr.UP:
// scrolling up
if (yStart <= (height-textHeight)/2-descent)
return true;
break;
case FunScrollTextAttr.DOWN:
// scrolling down
if (yStart >= (height-textHeight)/2-descent)
return true;
break;
}
return false;
}
/**
* update array with flags if characters are visible. Return
* number of visible characters.
*/
int updateVisible(int scroll)
{
int visibleCount = 0;
for (int i = 0; i < noOfChars; i++) {
visible[i] = (xPos[i]+xStart > offset &&
xPos[i]+xStart < width-offset &&
yPos[i]+yStart+lineHeight > offset &&
yPos[i]+yStart-lineHeight < height-offset);
if (visible[i])
visibleCount++;
}
// special treatment of explode animation
if (scroll == FunScrollTextAttr.EXPLODE) {
// if only 5 or less chars visible (per line) consider this as done
if (visibleCount <= (noOfLines*5))
visibleCount = 0;
}
return visibleCount;
}
void moveText(int scroll)
{
switch (scroll) {
case FunScrollTextAttr.LEFT:
xStart -= dx;
break;
case FunScrollTextAttr.RIGHT:
xStart += dx;
break;
case FunScrollTextAttr.UP:
yStart -= dy;
break;
case FunScrollTextAttr.DOWN:
yStart += dy;
break;
case FunScrollTextAttr.EXPLODE:
moveExplodeText();
break;
}
}
/**
* Move exploding text
*/
void moveExplodeText() {
int mid = noOfChars/2;
float maxDist = maxWidth/4;
for (int i = 0; i < mid; i++) {
// move to the left
float percentOfMax = (float)(mid-i)/mid;
xPos[i] -= (int) Math.max((percentOfMax * maxDist), 2.0);
}
for (int i = mid; i < noOfChars; i++) {
// move to the right
float percentOfMax = (float) (i-mid)/mid;
xPos[i] += (int) Math.max((percentOfMax * maxDist), 2.0);
}
}
/**
* Paint characters
*/
void paint(Graphics g)
{
// set foreground color
g.setColor(fg);
switch (attr.style()) {
case FunScrollTextAttr.SINEWAVE:
paintSineWave(g);
break;
case FunScrollTextAttr.NERVOUS:
paintNervous(g);
break;
default:
if (attr.endScroll() == FunScrollTextAttr.EXPLODE)
paintExplode(g);
else
paintNormal(g);
break;
}
}
/**
* Paint "exploding" text line
*/
void paintExplode(Graphics g) {
for (int i = 0; i < noOfChars; i++) {
if (visible[i])
drawNormalChar(g, i);
}
}
/**
* Paint normal text line
*/
void paintNormal(Graphics g) {
switch (attr.drawStyle()) {
case attr.ENGRAVE:
case attr.EMBOSS:
// pain emboss or engrave line
paintEmbossEngrave(g);
break;
case attr.SHADOW:
// pain shadowed line
paintShadow(g);
break;
case attr.NONE:
// draw normal line(s)
for (int i=0; i < noOfLines; i++) {
drawAlignedString(g, i,
xStart, yStart + ascent + (lineHeight*i));
}
break;
}
}
/**
* Paint emboss/engrave text line
*/
void paintEmbossEngrave(Graphics g) {
// init colors (first time)
if (darkBg == null) {
darkBg = FunScrollColorSupport.darker(bg, 0.5);
lightDarkBg = FunScrollColorSupport.darker(bg, 0.5 - (0.5/2));
brightBg = FunScrollColorSupport.brighter(bg, 0.5);
}
int drawStyle = attr.drawStyle();
Color upperLeftColor = (drawStyle == attr.ENGRAVE) ? darkBg : brightBg;
Color upperRightColor = (drawStyle == attr.ENGRAVE) ? brightBg : darkBg;
Color mainColor = (drawStyle == attr.ENGRAVE) ? lightDarkBg : bg;
int depth = 1; // hardkoded ;-(
for (int i=0; i < noOfLines; i++) {
drawAlignedString(g, i,
xStart, yStart + ascent + (lineHeight*i));
// upper left edge
g.setColor(upperLeftColor);
drawAlignedString(g, i,
xStart,
yStart + ascent + (lineHeight*i) - depth);
// lower right edge
g.setColor(upperRightColor);
drawAlignedString(g, i,
xStart + depth*2,
yStart + ascent + (lineHeight*i) + depth);
// main body of the character
g.setColor(mainColor);
drawAlignedString(g, i,
xStart + depth,
yStart + ascent + (lineHeight*i));
}
}
/**
* Paint emboss/engrave text line
*/
void paintShadow(Graphics g) {
int shadowOffset = 4;
if (brightFg == null)
brightFg = FunScrollColorSupport.brighter(fg, 0.75);
for (int i=0; i < noOfLines; i++) {
g.setColor(brightFg);
drawAlignedString(g, i,
xStart + shadowOffset,
yStart + ascent + (lineHeight*i) + shadowOffset);
g.setColor(fg);
drawAlignedString(g, i,
xStart,
yStart + ascent + (lineHeight*i));
}
}
/**
* draw aligned string
*/
void drawAlignedString(Graphics g, int index, int x, int y)
{
switch(attr.align()) {
case attr.LEFT:
break;
case attr.RIGHT:
x = width - x - lineWidths[index];
break;
case attr.CENTER:
x = x + (maxWidth - lineWidths[index])/2;
break;
}
g.drawString(lines[index], x, y);
}
/**
* Paint sine-wave text line
*/
void paintSineWave(Graphics g) {
int currYPos = (noOfChars > 0) ? yPos[0] : 0;
int degree = sinDegree;
for (int i = noOfChars-1; i >= 0; i--) {
if (currYPos != yPos[i]) {
// new line
currYPos = yPos[i];
degree = sinDegree;
}
if (visible[i]) {
// draw character
int sinHeight = lineHeight/3;
int y = (int) (Math.sin(degree*3.1414/180) * sinHeight);
drawChar(g, i, xPos[i]+xStart, yPos[i]+yStart+y);
}
degree -= 15;
if (degree <= 0)
degree = 360;
}
sinDegree -= 15;
if (sinDegree <= 0)
sinDegree = 360;
}
/**
* Paint nervous text line
*/
void paintNervous(Graphics g) {
for (int i = 0; i < noOfChars; i++) {
if (visible[i])
drawNervousChar(g, i);
}
}
/**
* Draw nervous character
*/
void drawNervousChar(Graphics g, int index)
{
int x = (int)(Math.random() * 2) + xPos[index];
int y = (int)(Math.random() * 4) + yPos[index];
drawChar(g, index, x+xStart, y+yStart);
}
/**
* Draw normal character
*/
void drawNormalChar(Graphics g, int index)
{
drawChar(g, index, xPos[index]+xStart, yPos[index]+yStart);
}
/**
* Draw character
*/
void drawChar(Graphics g, int index, int x, int y)
{
int drawStyle = attr.drawStyle();
if (drawStyle == attr.NONE || drawStyle == attr.SHADOW) {
if (drawStyle == attr.SHADOW) {
int shadowOffset = 4;
if (brightFg == null)
brightFg = FunScrollColorSupport.brighter(fg, 0.75);
g.setColor(brightFg);
g.drawChars(chars, index, 1,
x + shadowOffset, y + shadowOffset);
g.setColor(fg);
}
// default draw style
g.drawChars(chars, index, 1, x, y);
return;
}
// draw style is ENGRAVE or EMBOSS
// init colors (first time)
if (darkBg == null) {
darkBg = FunScrollColorSupport.darker(bg, 0.5);
lightDarkBg = FunScrollColorSupport.darker(bg, 0.5 - (0.5/2));
brightBg = FunScrollColorSupport.brighter(bg, 0.5);
}
int depth = 1; // hardkoded ;-(
Color upperLeftColor =
(drawStyle == attr.ENGRAVE) ? darkBg : brightBg;
Color upperRightColor =
(drawStyle == attr.ENGRAVE) ? brightBg : darkBg;
Color mainColor =
(drawStyle == attr.ENGRAVE) ? lightDarkBg : bg;
// upper left edge
g.setColor(upperLeftColor);
g.drawChars(chars, index, 1, x, y-depth);
// lower right edge
g.setColor(upperRightColor);
g.drawChars(chars, index, 1, x+depth*2, y+depth);
// main body of the character
g.setColor(mainColor);
g.drawChars(chars, index, 1, x+depth, y);
}
}
/*
* Copyright (c) 1995 by Jan Andersson, Torpa Konsult AB.
*
* Permission to use, copy, and distribute this software for
* NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*/
/**
* FunScroll Color Support
*
* @version 1.1 96/06/23
* @author Jan Andersson (janne@torpa.se)
*/
class FunScrollColorSupport {
static Hashtable colors;
/**
* Returns a darker version of color.
*/
static Color darker(int r, int g, int b, double factor) {
return new Color(Math.max((int)(r * (1 - factor)), 0),
Math.max((int)(g * (1 - factor)), 0),
Math.max((int)(b * (1 - factor)), 0));
}
/**
* Returns a darker version of color.
*/
static Color darker(Color c, double factor) {
int r, g, b;
r = c.getRed();
g = c.getGreen();
b = c.getBlue();
return darker(r, g, b, factor);
}
/**
* Returns a brighter version of color.
*/
static Color brighter(int r, int g, int b, double factor) {
int r2, g2, b2;
r2 = r + (int)((255 - r) * factor);
g2 = g + (int)((255 - g) * factor);
b2 = b + (int)((255 - b) * factor);
return new Color(r2, g2, b2);
}
/**
* Returns a brighter version of color.
*/
static Color brighter(Color c, double factor) {
int r, g, b;
r = c.getRed();
g = c.getGreen();
b = c.getBlue();
return brighter(r, g, b, factor);
}
/**
* lookup rgb string representing color name
*/
public static String lookup(String name) {
if(colors == null)
createHashTable();
String nameLowerCase = name.toLowerCase();
return (String)colors.get(nameLowerCase);
}
/**
* Create hash table
*/
public static void createHashTable() {
colors = new Hashtable(650);
colors.put("aliceblue", "f0f8ff");
colors.put("antiquewhite", "faebd7");
colors.put("aquamarine", "7fffd4");
colors.put("azure", "f0ffff");
colors.put("beige", "f5f5dc");
colors.put("bisque", "ffe4c4");
colors.put("black", "000000");
colors.put("blanchedalmond", "ffebcd");
colors.put("blue", "0000ff");
colors.put("blueviolet", "8a2be2");
colors.put("brown", "a52a2a");
colors.put("burlywood", "deb887");
colors.put("cadetblue", "5f9ea0");
colors.put("chartreuse", "7fff00");
colors.put("chocolate", "d2691e");
colors.put("coral", "ff7f50");
colors.put("cornflowerblue", "6495ed");
colors.put("cornsilk", "fff8dc");
colors.put("cyan", "00ffff");
colors.put("darkgoldenrod", "b8860b");
colors.put("darkgreen", "006400");
colors.put("darkkhaki", "bdb76b");
colors.put("darkolivegreen", "556b2f");
colors.put("darkorange", "ff8c00");
colors.put("darkorchid", "9932cc");
colors.put("darksalmon", "e9967a");
colors.put("darkseagreen", "8fbc8f");
colors.put("darkslateblue", "483d8b");
colors.put("darkslategray", "2f4f4f");
colors.put("darkslategrey", "2f4f4f");
colors.put("darkturquoise", "00ced1");
colors.put("darkviolet", "9400d3");
colors.put("deeppink", "ff1493");
colors.put("deepskyblue", "00bfff");
colors.put("dimgray", "696969");
colors.put("dimgrey", "696969");
colors.put("dodgerblue", "1e90ff");
colors.put("firebrick", "b22222");
colors.put("floralwhite", "fffaf0");
colors.put("forestgreen", "228b22");
colors.put("green", "00ff00");
colors.put("gainsboro", "dcdcdc");
colors.put("ghostwhite", "f8f8ff");
colors.put("gold", "ffd700");
colors.put("goldenrod", "daa520");
colors.put("gray", "bebebe");
colors.put("honeydew", "f0fff0");
colors.put("hotpink", "ff69b4");
colors.put("indianred", "cd5c5c");
colors.put("ivory", "fffff0");
colors.put("khaki", "f0e68c");
colors.put("lavender", "e6e6fa");
colors.put("lavenderblush", "fff0f5");
colors.put("lawngreen", "7cfc00");
colors.put("lemonchiffon", "fffacd");
colors.put("lightblue", "add8e6");
colors.put("lightcoral", "f08080");
colors.put("lightcyan", "e0ffff");
colors.put("lightgoldenrod", "eedd82");
colors.put("lightgoldenrodyellow","fafad2");
colors.put("lightgray", "d3d3d3");
colors.put("lightgrey", "d3d3d3");
colors.put("lightpink", "ffb6c1");
colors.put("lightsalmon", "ffa07a");
colors.put("lightseagreen", "20b2aa");
colors.put("lightskyblue", "87cefa");
colors.put("lightslateblue", "8470ff");
colors.put("lightslategray", "778899");
colors.put("lightslategrey", "778899");
colors.put("lightsteelblue", "b0c4de");
colors.put("lightyellow", "ffffe0");
colors.put("limegreen", "32cd32");
colors.put("linen", "faf0e6");
colors.put("magenta", "ff00ff");
colors.put("maroon", "b03060");
colors.put("mediumaquamarine", "66cdaa");
colors.put("mediumblue", "0000cd");
colors.put("mediumorchid", "ba55d3");
colors.put("mediumpurple", "9370db");
colors.put("mediumseagreen", "3cb371");
colors.put("mediumslateblue", "7b68ee");
colors.put("mediumspringgreen", "00fa9a");
colors.put("mediumturquoise", "48d1cc");
colors.put("mediumvioletred", "c71585");
colors.put("midnightblue", "191970");
colors.put("mintcream", "f5fffa");
colors.put("mistyrose", "ffe4e1");
colors.put("moccasin", "ffe4b5");
colors.put("navajowhite", "ffdead");
colors.put("navy", "000080");
colors.put("navyblue", "000080");
colors.put("oldlace", "fdf5e6");
colors.put("olivedrab", "6b8e23");
colors.put("orange", "ffa500");
colors.put("orangered", "ff4500");
colors.put("orchid", "da70d6");
colors.put("palegoldenrod", "eee8aa");
colors.put("palegreen", "98fb98");
colors.put("paleturquoise", "afeeee");
colors.put("palevioletred", "db7093");
colors.put("papayawhip", "ffefd5");
colors.put("peachpuff", "ffdab9");
colors.put("peru", "cd853f");
colors.put("pink", "ffc0cb");
colors.put("plum", "dda0dd");
colors.put("powderblue", "b0e0e6");
colors.put("purple", "a020f0");
colors.put("red", "ff0000");
colors.put("rosybrown", "bc8f8f");
colors.put("royalblue", "4169e1");
colors.put("saddlebrown", "8b4513");
colors.put("salmon", "fa8072");
colors.put("sandybrown", "f4a460");
colors.put("seagreen", "2e8b57");
colors.put("seashell", "fff5ee");
colors.put("sienna", "a0522d");
colors.put("skyblue", "87ceeb");
colors.put("slateblue", "6a5acd");
colors.put("slategray", "708090");
colors.put("slategrey", "708090");
colors.put("snow", "fffafa");
colors.put("springgreen", "00ff7f");
colors.put("steelblue", "4682b4");
colors.put("tan", "d2b48c");
colors.put("thistle", "d8bfd8");
colors.put("tomato", "ff6347");
colors.put("turquoise", "40e0d0");
colors.put("violet", "ee82ee");
colors.put("violetred", "d02090");
colors.put("wheat", "f5deb3");
colors.put("white", "ffffff");
colors.put("whitesmoke", "f5f5f5");
colors.put("yellow", "ffff00");
colors.put("yellowgreen", "9acd32");
}
}
/*
* Copyright (c) 1995 by Jan Andersson, Torpa Konsult AB.
*
* Permission to use, copy, and distribute this software for
* NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*/
/**
* Attributes of FunScroll Animated Text
*
* @version 1.3 96/08/20
* @author Jan Andersson (janne@torpa.se)
*/
class FunScrollTextAttr
{
// scroll styles:
static final int NONE = 0; // no scrolling (default)
static final int LEFT = 1; // scroll left
static final int RIGHT = 2; // ... right
static final int UP = 3; // ... up
static final int DOWN = 4; // ... down
static final int EXPLODE = 5;// explode (only for endScroll)
// text styles:
static final int NORMAL = 0; // normal (default)
static final int NERVOUS = 1; // "nervous" text
static final int SINEWAVE = 2; // sine-wave text
// text draw styles:
static final int EMBOSS = 1;
static final int ENGRAVE = 2;
static final int SHADOW = 3;
// text line alignment
static final int CENTER = 0;
String msg = ""; // message line
String delimiters = "<>"; // used delimiters (default is "<>")
int startScroll = NONE; // start scroll style
int endScroll = NONE; // end scroll style
int showDelay = 0; // show delay
int endDelay = -1; // end delay
int style = NORMAL; // text style
int drawStyle = NONE; // text draw style
int align = CENTER; // text line alignment
String color = null; // text color
public FunScrollTextAttr(String line, String delim)
{
if (delim != null) {
// used specified delimiter
delimiters = delim;
}
parse(line);
}
public String msg()
{
return msg;
}
public int startScroll()
{
return startScroll;
}
public int endScroll()
{
return endScroll;
}
public int showDelay()
{
return showDelay;
}
public int endDelay()
{
return endDelay;
}
public int style()
{
return style;
}
public int align()
{
return align;
}
public int drawStyle()
{
return drawStyle;
}
public String color()
{
return color;
}
void parse(String line)
{
StringTokenizer st = new StringTokenizer(line, delimiters);
boolean gotText = false;
while (st.hasMoreTokens()) {
int scroll = -1;
String token = st.nextToken();
// get scroll style
if (token.equalsIgnoreCase("left"))
scroll = LEFT;
else if (token.equalsIgnoreCase("right"))
scroll = RIGHT;
else if (token.equalsIgnoreCase("up"))
scroll = UP;
else if (token.equalsIgnoreCase("down"))
scroll = DOWN;
else if (gotText && token.equalsIgnoreCase("explode"))
scroll = EXPLODE;
if (scroll >= 0) {
if (!gotText)
startScroll = scroll;
else
endScroll = scroll;
continue;
}
// get text style
if (token.equalsIgnoreCase("nervous")) {
style = NERVOUS;
continue;
}
if (token.equalsIgnoreCase("sine-wave")) {
style = SINEWAVE;
continue;
}
// get text draw style
if (token.equalsIgnoreCase("emboss")) {
drawStyle = EMBOSS;
continue;
}
if (token.equalsIgnoreCase("engrave")) {
drawStyle = ENGRAVE;
continue;
}
if (token.equalsIgnoreCase("shadow")) {
drawStyle = SHADOW;
continue;
}
// get color
if (token.length() > 6 &&
token.substring(0,6).equalsIgnoreCase("color=")) {
color = token.substring(6);
continue;
}
// get color
if (token.length() > 6 &&
token.substring(0,6).equalsIgnoreCase("align=")) {
String alignStr = token.substring(6);
if (alignStr.equalsIgnoreCase("left"))
align = LEFT;
else if (alignStr.equalsIgnoreCase("right"))
align = RIGHT;
else
align = CENTER;
continue;
}
// check if integer, if so assume delay value
boolean isInt = true;
for (int i=0; i<token.length(); i++) {
int digit = Character.digit(token.charAt(i), 10);
if (digit < 0) {
// not a digit
isInt = false;
break;
}
}
if (isInt) {
try {
if (!gotText)
showDelay = Integer.parseInt(token);
else
endDelay = Integer.parseInt(token);
} catch (NumberFormatException ne) {}
continue;
}
else {
// assume text string parsed
if (!gotText) {
msg = token;
gotText = true;
}
}
}
}
}