import javax.swing.ImageIcon; import javax.swing.JApplet; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.Timer; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedInputStream; /** * @author jag * @author mem * @author kwalrath * @author ir71389 */ /* * TumbleItem.java requires these files: * all the images in the images/tumble directory * (or, if specified in the applet tag, another directory [dir] * with images named T1.gif ... Tx.gif, where x is the total * number of images [nimgs]) * the appropriate code to specify that the applet be executed, * such as the HTML code in TumbleItem.html or TumbleItem.atag, * or the JNLP code in TumbleItem.jnlp * */ public class TumbleItem extends JApplet implements ActionListener { int loopslot = -1; //the current frame number String dir; //the directory relative to the codebase //from which the images are loaded Timer timer; //the timer animating the images int pause; //the length of the pause between revs int offset; //how much to offset between loops int off; //the current offset int speed; //animation speed int nimgs; //number of images to animate int width; //width of the applet's content pane Animator animator; //the applet's content pane ImageIcon imgs[]; //the images int maxWidth; //width of widest image JLabel statusLabel; //Called by init. protected void loadAppletParameters() { //Get the applet parameters. String at = getParameter("img"); dir = (at != null) ? at : "images/tumble"; at = getParameter("pause"); pause = (at != null) ? Integer.valueOf(at).intValue() : 1900; at = getParameter("offset"); offset = (at != null) ? Integer.valueOf(at).intValue() : 0; at = getParameter("speed"); speed = (at != null) ? (1000 / Integer.valueOf(at).intValue()) : 100; at = getParameter("nimgs"); nimgs = (at != null) ? Integer.valueOf(at).intValue() : 16; at = getParameter("maxwidth"); maxWidth = (at != null) ? Integer.valueOf(at).intValue() : 0; } /** * Create the GUI. For thread safety, this method should * be invoked from the event-dispatching thread. */ private void createGUI() { //Animate from right to left if offset is negative. width = getSize().width; if (offset < 0) { off = width - maxWidth; } //Custom component to draw the current image //at a particular offset. animator = new Animator(); animator.setOpaque(true); animator.setBackground(Color.white); setContentPane(animator); //Put a "Loading Images..." label in the middle of //the content pane. To center the label's text in //the applet, put it in the center part of a //BorderLayout-controlled container, and center-align //the label's text. statusLabel = new JLabel("Loading Images...", JLabel.CENTER); animator.add(statusLabel, BorderLayout.CENTER); } //Background task for loading images. SwingWorker worker = new SwingWorker() { @Override public ImageIcon[] doInBackground() { final ImageIcon[] innerImgs = new ImageIcon[nimgs]; for (int i = 0; i < nimgs; i++) { innerImgs[i] = loadImage(i + 1); } return innerImgs; } @Override public void done() { //Remove the "Loading images" label. animator.removeAll(); loopslot = -1; try { imgs = get(); } catch (InterruptedException ignore) {} catch (java.util.concurrent.ExecutionException e) { String why = null; Throwable cause = e.getCause(); if (cause != null) { why = cause.getMessage(); } else { why = e.getMessage(); } System.err.println("Error retrieving file: " + why); } } }; //Called when this applet is loaded into the browser. public void init() { loadAppletParameters(); //Execute a job on the event-dispatching thread: //creating this applet's GUI. try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { createGUI(); } }); } catch (Exception e) { System.err.println("createGUI didn't successfully complete"); } //Set up timer to drive animation events. timer = new Timer(speed, this); timer.setInitialDelay(pause); timer.start(); //Start loading the images in the background. worker.execute(); } //The component that actually presents the GUI. public class Animator extends JPanel { public Animator() { super(new BorderLayout()); } protected void paintComponent(Graphics g) { super.paintComponent(g); if (worker.isDone() && (loopslot > -1) && (loopslot < nimgs)) { if (imgs != null && imgs[loopslot] != null) { imgs[loopslot].paintIcon(this, g, off, 0); } } } } //Handle timer event. Update the loopslot (frame number) and the //offset. If it's the last frame, restart the timer to get a long //pause between loops. public void actionPerformed(ActionEvent e) { //If still loading, can't animate. if (!worker.isDone()) { return; } loopslot++; if (loopslot >= nimgs) { loopslot = 0; off += offset; if (off < 0) { off = width - maxWidth; } else if (off + maxWidth > width) { off = 0; } } animator.repaint(); if (loopslot == nimgs - 1) { timer.restart(); } } public void start() { if (worker.isDone() && (nimgs > 1)) { timer.restart(); } } public void stop() { timer.stop(); } /** * Load the image for the specified frame of animation. Since * this runs as an applet, we use getResourceAsStream for * efficiency and so it'll work in older versions of Java Plug-in. */ protected ImageIcon loadImage(int imageNum) { String path = dir + "/T" + imageNum + ".gif"; int MAX_IMAGE_SIZE = 2400; //Change this to the size of //your biggest image, in bytes. int count = 0; BufferedInputStream imgStream = new BufferedInputStream( this.getClass().getResourceAsStream(path)); if (imgStream != null) { byte buf[] = new byte[MAX_IMAGE_SIZE]; try { count = imgStream.read(buf); imgStream.close(); } catch (java.io.IOException ioe) { System.err.println("Couldn't read stream from file: " + path); return null; } if (count <= 0) { System.err.println("Empty file: " + path); return null; } return new ImageIcon(Toolkit.getDefaultToolkit().createImage(buf)); } else { System.err.println("Couldn't find file: " + path); return null; } } public String getAppletInfo() { return "Title: TumbleItem v1.2, 23 Jul 1997\n" + "Author: James Gosling\n" + "A simple Item class to play an image loop."; } public String[][] getParameterInfo() { String[][] info = { {"img", "string", "the directory containing the images to loop"}, {"pause", "int", "pause between complete loops; default is 3900"}, {"offset", "int", "offset of each image to simulate left (-) or " + "right (+) motion; default is 0 (no motion)"}, {"speed", "int", "the speed at which the frames are looped; " + "default is 100"}, {"nimgs", "int", "the number of images to be looped; default is 16"}, {"maxwidth", "int", "the maximum width of any image in the loop; " + "default is 0"} }; return info; } }