/*
* MarqueeLights.java
* A java program to attach blinking lights around an image
* Usage:
*
* The modes can be selected through
* : Forward, reverse, blink
* The value string can contain
* f=forward chase, r=reverse chase, F,R use multicolors
* c,C=clear sequence, s,S=set sequence, C,S are random
* y=yes (all on), n=no (all off)
* b=blink, 1=one, +=additive
*
* Ken Shirriff ken.shirriff@eng.sun.com
*
* Copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* SUN 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. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* Please refer to the file "license.txt"
* for further important copyright and licensing information.
*/
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.applet.Applet;
// A class to hold an image and an "ok" flag. For the chase lights, stride
// images are used, with the appropriate lights lit in each one. If the
// image is still being loaded, ok will be set to false. imgs[stride]
// is a general image buffer.
class Img {
Image image;
Graphics graphics;
boolean ok;
};
public class MarqueeLights extends java.applet.Applet implements Runnable, ImageObserver {
Thread marquee = null;
Image outbuf;
Img imgs[];
Image gif;
final int ON=1;
final int OFF=5;
int width = 100;
int height = 40;
int border = 10; // The total width of the image border
int stride = 3; // Number of bulbs in the chase sequence
int delay = 150; // Delay between steps
int newdelay = 150; // Fudged delay
int bulb = 3; // Pixel size of a bulb
boolean stale = true; // Image has been updated
String status = ""; // For mouse entry
URL url = null; // For mouse click
String mode = "frbF"; // Default mode sequence
int mg = 0; // Margin
int gap = 1; // Gap between bulbs
int wb, hb, nb; // width in bulbs, height in bulbs, number of bulbs
boolean error = false;
Point bulbs[];
boolean statusflag = false;
// Asynchronous update of image size. Print error if size is wrong.
// Set the stale flag so images are updated.
public boolean imageUpdate(Image img, int infoflags, int x, int
y, int inwidth, int inheight) {
if ((infoflags & (WIDTH|HEIGHT)) != 0) {
if (width != inwidth+2*border || height != inheight+2*border) {
System.out.println("MarqueeLights: dimensions should be width="+(inwidth+2*border)+" height="+(inheight+2*border));
}
}
stale = true;
return true;
}
// Compute the size of everything
// wb = width in bulbs, hb = height in bulbs, nb = number of bulbs
public void sizeit() {
wb = (width-2*mg+gap)/(bulb+gap);
hb = (height-2*bulb-2*gap+gap)/(bulb+gap);
nb = 2*wb+2*hb;
bulbs = new Point[nb];
int i;
for (i=0;i=mode.length()) {
idx=0;
}
n=0;
initMode(modec);
}
if (stale) {
// Redraw the images
int i;
for (i=0;i=stride) {
rval=0;
}
} else {
rval = n-1;
if (rval<0) {
rval=stride-1;
}
}
cnt--;
if (cnt<=0 && (rval%2)==0) {
rval = -1;
}
} else if (mode == '+') {
n++;
rval = n;
if (n < tot) {
light(imgs[stride].graphics,n-1,OFF);
light(imgs[stride].graphics,n-1+nb/2,OFF);
} else {
tot--;
n=0;
rval = 0;
if (tot==0) {
rval = -1;
}
}
light(imgs[stride].graphics,n,ON);
light(imgs[stride].graphics,n+nb/2,ON);
} else if (mode == '1') {
light(imgs[stride].graphics,n,OFF);
rval = n+1;
if (rval>=nb) {
rval = -1;
} else {
light(imgs[stride].graphics,rval,ON);
}
} else if (mode == 'S' || mode=='C') {
light(imgs[stride].graphics,randseq[n],mode=='S'?ON:OFF);
rval = n+1;
if (rval>=nb) {
rval = -1;
}
} else if (mode == 's' || mode=='c') {
light(imgs[stride].graphics,n,mode=='s'?ON:OFF);
rval = n+1;
if (rval>=nb) {
rval = -1;
}
} else if (mode=='b') {
for (i=0;i=6) {
rval = -1;
}
} else if (mode=='y' || mode=='n') {
rval = -1;
}
if (imgs[bnum].ok == false) {
imgs[bnum].ok = true;
imgs[bnum].image.getGraphics().drawImage(gif,border,border,width-2*border, height-2*border,this);
}
return rval;
}
public String getAppletInfo() {
return "MarqueeLights by Ken Shirriff shirriff@eng.sun.com";
}
public String[][] getParameterInfo() {
String [][] info = {
{"image ","URL ", "image (Required)"},
{"width ","int ", "image width"},
{"height ","int ", "image height"},
{"delay ","int ", "delay, default=50"},
{"bulb ","int ", "bulb size, default=10"},
{"gap ","int ", "bulb gap, default=1"},
{"border ","int ", "border width, default=10"},
{"stride ","int ", "chase stride"},
{"url ","URL ", "click url"},
{"mode ","string ", "flash mode"}
};
return info;
}
public void start() {
if (marquee == null) {
marquee = new Thread(this);
marquee.start();
}
}
public boolean mouseDown(java.awt.Event evt, int x, int y) {
if (url !=null) {
getAppletContext().showDocument(url);
}
return true;
}
public boolean mouseEnter(java.awt.Event evt, int x, int y) {
statusflag = !statusflag;
if (statusflag) {
showStatus(status);
} else {
showStatus("MarqueeLights by Ken Shirriff");
}
return true;
}
public boolean mouseExit(java.awt.Event evt, int x, int y) {
showStatus(" ");
return true;
}
// Compute the position of bulb n
public void pos(int n, Point p) {
int x=0,y=0;
int excess;
if (nwidth) {
x=width-bulb;
}
y = (bulb+gap)*(n-wb)+excess/2;
} else if (n-wb-hbheight) {
y=height-bulb;
}
} else if (n-2*wb-hb=5) {
g.fillOval(bulbs[n].x, bulbs[n].y,bulb,bulb);
} else {
g.fillRect(bulbs[n].x, bulbs[n].y,bulb,bulb);
}
}
// Clear the image to have no bulbs on
public void resetImg(Graphics g) {
g.setColor(Color.black);
g.fillRect(0,0,width,height);
g.drawImage(gif,border,border,width-2*border, height-2*border,this);
}
} // MarqueeLights