import java.awt.*; import java.util.Vector; import java.applet.*; import java.net.URL; import WordBubble; /** * Display an image with word bubbles that change * periodically and/or randomly. This applet uses the helper class * WordBubble to draw the bubbles. This applet accepts a large number * of HTML parameter arguments, to help make it more * flexible. Note that this applet is deliberately * coded with very few defensive measures against * user error, in an effort to keep it small! * * Here are the parameters: * * imageURL absolute URL for image to display (no scaling!) * * cycles how many messages to show, 0 for * running forever. * * runmessage message to showStatus during running * * cycleTimeMin minimum show time in seconds or millis * * cycleTimeMax maximum show time in seconds or millis * * spaceTimeMin min time between shows in seconds or millis * * spaceTimeMax max time between shows in seconds or millis * * fontName name of font to use for messages, * default is "Helvetica" * * defFontSize default size of font to use, * default is 10. * * randomize whether to randomize selection * of point pairs and messages, or * go in order. * * wordbackground hex specification for background color * (default is white) * * background hex specification for background of * whole applet. (default is 0xC0C0C0) * * * wordforeground hex specification for line/text color * (default is black) * * endpointN end point no. N * (a point in the coordinate space of the * image where the end of a word bubble * should go.) * * centerpointN center point no. N * (a point in the coordinate space of the * image where the center of a word bubble * should go.) * * messageN message text no. N * * sizeN font size for message text no. N * (if not given, then use default font) * * * In this version, the image is always positioned to the south * center of the available applet extent. */ public class TalkImageApplet extends Applet implements Runnable { String imageURLString; URL imageURL; Image image; int cycles; int cycleMinMillis; int cycleMaxMillis; int spaceMinMillis; int spaceMaxMillis; String fontName; String runmessage; Font defaultFont; int defFontSize; boolean randomize; Color bubbleBackground; Color bubbleForeground; Vector endpoints; Vector centerpoints; Vector wordbubbles; Vector fontSizes; Rectangle imageRect; WordBubble currentbubble = null; int currentMessageIndex = 0; Thread animator = null; MediaTracker mt1; protected int randint(int lo, int hi) { if (lo == hi) return lo; else return lo + (int)(Math.floor(Math.random() * (double)(hi - lo))); } /** * initialize this darn applet, including calling readParams * to set up the parameters. This does NOT start the animation * thread. */ public void init() { /* set initial values */ imageURLString = null; imageURL = null; image = null; cycles = 0; cycleMinMillis = 1500; cycleMaxMillis = 5000; spaceMinMillis = 250; spaceMaxMillis = 1500; fontName = "Helvetica"; defFontSize = 10; defaultFont= null; randomize = true; bubbleBackground = Color.white; bubbleForeground = Color.black; endpoints = new Vector(); centerpoints = new Vector(); wordbubbles = new Vector(); fontSizes = new Vector(); currentbubble = null; currentMessageIndex = -1; animator = null; imageRect = null; /* read the parameters */ readParams(); /* load the image */ try { imageURL = new URL(imageURLString); image = getImage(imageURL); if (image == null) { System.out.println("\nCouldn't load image!" + imageURL); } mt1 = new MediaTracker(this); mt1.addImage(image, 1); if (mt1.isErrorAny()) { System.out.println("Media error occurred 1."); image=null; } mt1.waitForAll(); if (mt1.isErrorAny()) { System.out.println("Media error occurred 2."); image = null; } } catch (Exception e) { mt1 = null; System.out.println("Could not do image!"); image = null; } /* do the default font */ defaultFont = new Font(fontName, Font.PLAIN, defFontSize); System.out.println("Font itself is " + defaultFont); /* show the applet */ show(); } /** * This waits for the image to load, then starts the * animator thread. */ public void start() { System.out.println("In start..."); /* configure all the WordBubble objects */ int ix; for(ix = 0; ix < wordbubbles.size(); ix++) { WordBubble w1 = (WordBubble)(wordbubbles.elementAt(ix)); w1.setParent(this); w1.setTextFont(defaultFont); if (fontSizes.elementAt(ix) != null) { int fs1 = Integer.parseInt((String)(fontSizes.elementAt(ix))); if (fs1 > 2 && fs1 < 40) { Font f1 = new Font(fontName, Font.PLAIN, fs1); w1.setTextFont(f1); // System.out.println("Font for " + ix + " is " + f1); } } w1.background = bubbleBackground; w1.foreground = bubbleForeground; } if (image != null) { imageRect = new Rectangle(0,0, image.getWidth(this), image.getHeight(this)); imageRect.translate((size().width - imageRect.width)/2, (size().height - imageRect.height)); } repaint(); animator = new Thread(this); animator.start(); showStatus(runmessage); } /** * stop the animator thread */ public void stop() { // System.out.println("In stop."); if (animator != null && animator.isAlive()) { animator.stop(); } animator = null; showStatus("Applet done."); } /** * return some info about this little applet */ public String getAppletInfo() { return "Talking Image Applet v1.0 (28 Dec 1997), by Neal Ziring"; } /** * on destroy remember to stop the thread * if it still exists. */ public void destroy() { if (animator != null) { animator.stop(); } } /** * run the animation */ public void run() { Point p1, p2; Point endpnt, ctrpnt; int nextmsgindex; int nextptindex; // System.out.println("In run()"); try { Thread.sleep(spaceMaxMillis); } catch (Exception e) { } Graphics g1 = getGraphics(); if (image != null) do { if (randomize) { int tmpindex; nextptindex = randint(0, endpoints.size()); do { nextmsgindex = randint(0, wordbubbles.size()); } while (currentMessageIndex == nextmsgindex); } else { nextptindex = (currentMessageIndex + 1) % wordbubbles.size(); nextmsgindex = (currentMessageIndex + 1) % wordbubbles.size(); } p1 = (Point)(endpoints.elementAt(nextptindex % endpoints.size())); if (p1 == null) p1 = (Point)(endpoints.elementAt(0)); endpnt = new Point(p1.x + imageRect.x, p1.y + imageRect.y); p2 = (Point)(centerpoints.elementAt(nextptindex % centerpoints.size())); if (p2 == null) p2 = (Point)(centerpoints.elementAt(0)); ctrpnt = new Point(p2.x + imageRect.x, p2.y + imageRect.y); // System.out.println("In loop, p1="+endpnt+" and p2="+ctrpnt+" and nextmsgindex=" + nextmsgindex); currentbubble = (WordBubble)(wordbubbles.elementAt(nextmsgindex)); currentMessageIndex = nextmsgindex; currentbubble.setEndpoint(endpnt); currentbubble.setCenterpoint(ctrpnt); currentbubble.draw(g1); try { Thread.sleep(randint(cycleMinMillis,cycleMaxMillis)); } catch (Exception e) { } currentbubble.undraw(g1); currentbubble = null; try { Thread.sleep(randint(spaceMinMillis,spaceMaxMillis)); } catch (Exception e) { } cycles -= 1; } while (cycles != 0); g1.dispose(); } /** * no need for anything special, just paint */ public void update(Graphics g) { paint(g); } /** * paint the image and current bubble if necessary */ public void paint(Graphics g) { // System.out.println("Hey, in paint, size = " + size() + " and color is " + getBackground()); int wid = size().width; int hgt = size().height; g.setColor(getBackground()); /* avoid image flash by only drawing around the sides */ g.fillRect(0,0, wid, imageRect.y); g.fillRect(0,0, imageRect.x, hgt); if (image != null ) { g.fillRect(0,0, wid, imageRect.y); g.fillRect(0,0, imageRect.x, hgt); g.fillRect(imageRect.x + imageRect.width, imageRect.y, wid, hgt); g.drawImage(image, imageRect.x, imageRect.y, this); if (currentbubble != null) { currentbubble.draw(g); } } else { g.fillRect(0,0, wid, hgt); } } public String getparm(String parm, String def) { String ret = getParameter(parm); if (ret != null) return ret; else return def; } /** * read our many parameters and create our wordbubble objects */ void readParams() { // read unnumered params first imageURLString = getParameter("imageURL"); cycles = Integer.parseInt(getparm("cycles","0")); runmessage = getparm("runmessage", getAppletInfo()); cycleMinMillis = Integer.parseInt(getparm("cycleTimeMin","1500")); if (cycleMinMillis < 50) cycleMinMillis *= 1000; cycleMaxMillis = Integer.parseInt(getparm("cycleTimeMax","10000")); if (cycleMaxMillis < 250) cycleMaxMillis *= 1000; spaceMinMillis = Integer.parseInt(getparm("spaceTimeMin","250")); if (spaceMinMillis < 50) spaceMinMillis *= 1000; spaceMaxMillis = Integer.parseInt(getparm("spaceTimeMax","1500")); if (spaceMaxMillis < 150) spaceMaxMillis *= 1000; fontName = getparm("fontName", "Helvetica"); randomize = Boolean.valueOf(getparm("randomize", "true")).booleanValue(); defFontSize = Integer.parseInt(getparm("defFontSize", "11")); bubbleBackground = new Color(Integer.parseInt(getparm("wordbackground","ffffff"),16)); bubbleForeground = new Color(Integer.parseInt(getparm("wordforeground","0"),16)); setBackground(new Color(Integer.parseInt(getparm("background","C0C0C0"),16))); // System.out.println("New bg color is " + getBackground()); /* now handled the numbered ones */ boolean gotone = true; String tmpval, tmpparm; int ix; for(ix = 0; gotone; ix++) { gotone = false; tmpparm = "message" + ix; tmpval = getParameter(tmpparm); if (tmpval != null) { wordbubbles.addElement(new WordBubble(tmpval,this)); gotone = true; tmpparm = "size" + ix; tmpval = getParameter(tmpparm); if (tmpval != null) fontSizes.addElement(tmpval); else fontSizes.addElement("0"); } tmpparm = "endpoint" + ix; tmpval = getParameter(tmpparm); if (tmpval != null) { endpoints.addElement(pointFromString(tmpval)); gotone = true; } tmpparm = "centerpoint" + ix; tmpval = getParameter(tmpparm); if (tmpval != null) { centerpoints.addElement(pointFromString(tmpval)); gotone = true; } } return; } Point pointFromString(String str) { int xval = 0; int yval = 0; int cp = str.indexOf(','); if (cp > 0) { xval = Integer.parseInt(str.substring(0,cp).trim()); yval = Integer.parseInt(str.substring(cp + 1).trim()); } // System.out.println("In pointFromString, str=" + str + " and xval=" + xval + " and yval=" + yval); return(new Point(xval, yval)); } }