import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class RippleApplet extends Applet { public static final Color FG_DEFAULT = Color.black; public static final Color BG_DEFAULT = Color.white; private RippleCanvas rc; public String getAppletInfo() { return "RippleApplet v.0.1, by Keunwoo Lee; copy and share at will."; } public void init() { // Set fg & bg colors. Note that we use the getParameter // method inherited from java.awt.Applet. Color fg, bg; String fgParam = getParameter("FGCOLOR"); String bgParam = getParameter("BGCOLOR"); if (fgParam == null) { fg = FG_DEFAULT; } else { char[] fgArray = fgParam.toCharArray(); int fgRed = Integer.parseInt(new String(fgArray,0,2), 16); int fgBlue = Integer.parseInt(new String(fgArray,2,2), 16); int fgGreen = Integer.parseInt(new String(fgArray,4,2), 16); fg = new Color(fgRed, fgBlue, fgGreen); } if (bgParam == null) { bg = BG_DEFAULT; } else { char[] bgArray = bgParam.toCharArray(); int bgRed = Integer.parseInt(new String(bgArray,0,2), 16); int bgBlue = Integer.parseInt(new String(bgArray,2,2), 16); int bgGreen = Integer.parseInt(new String(bgArray,4,2), 16); bg = new Color(bgRed, bgBlue, bgGreen); } // create a RippleCanvas, then load (we don't, strictly // speaking, have to set BorderLayout, since there's only one // object, but this demonstrates how to use it), and go. rc = new RippleCanvas(fg, bg); setLayout(new BorderLayout()); add(rc, BorderLayout.CENTER); } public void start() { rc.start(); } public void stop() { rc.stop(); } /** Inner class no. 1: this is the actual component that does the animation work. It would be reasonable to make this a non-inner class, actually, and probably better style. */ public static class RippleCanvas extends BufferedCanvas { public static final int INIT_RADIUS = 4; public static final int EXPAND_INTERVAL_MILLIS = 8; public static final int MIN_NEWCIRCLE_INTERVAL = 80; public static final long AGE_OF_DEATH = 1000; private Vector c = new Vector(); private Color fgColor, bgColor; public RippleCanvas(Color foreground, Color background) { super(); this.fgColor = foreground; this.bgColor = background; MouseHandler m = new MouseHandler(this); addMouseListener(m); addMouseMotionListener(m); } public void render(Graphics g) { g.setColor(bgColor); g.fillRect(0, 0, getBounds().width, getBounds().height); g.setColor(fgColor); Circle current = null; long now = System.currentTimeMillis(); for (int i=0; i MIN_NEWCIRCLE_INTERVAL)) { // Basically, all the fanciness above just makes // sure we don't add more than a certain number of // circles per time increment. c.addElement(new Circle(e.getX(), e.getY())); } master.repaint(); } } } }