home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / code / ch07.txt < prev    next >
Text File  |  1998-12-14  |  43KB  |  2,170 lines

  1. ImageApp.java:
  2.  
  3. import java.awt.*;
  4. import java.awt.event.*;
  5. import java.applet.Applet;
  6.  
  7. /*
  8.  * display a series of images
  9.  */
  10. public class ImageApp extends Applet implements ActionListener
  11. {
  12.  
  13. /*
  14.  * the number of images to load
  15.  */
  16. final int NumImages = 6;
  17. Button button1;
  18.  
  19.  
  20. /*
  21.  * an array to hold the images
  22.  */
  23. Image imgs[] = new Image[NumImages];
  24.  
  25. /*
  26.  * which image is currently displayed
  27.  */
  28. int which = 0;
  29.  
  30. /*
  31.  * init method runs when applet is loaded or reloaded
  32.  */
  33. public void init() {
  34.  
  35.     setLayout(new BorderLayout());
  36.  
  37.     Panel p = new Panel ();
  38.     add("South", p);
  39.     button1 = new Button("Next Image");
  40.     p.add (button1);
  41.     button1.addActionListener(this);
  42.     for (int i=0; i < NumImages; i+=1) {
  43.         String name = "Globe"+(i+1)+".gif";
  44.         imgs[i] = getImage (getDocumentBase(),name); 
  45.     }
  46. }
  47.  
  48. /**
  49.  * paint method is called by update
  50.  * draw the current image
  51.  * @param g - destination graphics object
  52.  */
  53. public void paint (Graphics g) {
  54.  
  55.     g.drawImage (imgs[which], 10, 10, this);
  56. }
  57.  
  58. /**
  59.  * switch to next image when button is pressed
  60.  * @param evt - event object
  61.  * @param arg - target object
  62.  */
  63. public void actionPerformed(ActionEvent evt)
  64. {
  65.         which += 1;
  66.         which %= NumImages;    // wrap around to zero
  67.         repaint ();    // causes update as soon as possible
  68. }
  69. }
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79. ImageSize.java:
  80.  
  81. import java.awt.*;
  82. import java.awt.event.*;
  83. import java.applet.Applet;
  84.  
  85. /*
  86.  * an applet that allows an image to be resized
  87.  */
  88. public class ImageSize extends Applet implements ActionListener {
  89.  
  90. /*
  91.  * the image to draw
  92.  */
  93. Image img;
  94. Button btnSmaller;
  95. Button btnBigger;
  96.  
  97. /*
  98.  * the current width and height of the image
  99.  */
  100. double width, height;
  101.  
  102. /*
  103.  * the image size scale factor
  104.  */
  105. double scale = 1.0;
  106.  
  107.  
  108. /*
  109.  * called when the applet is loaded or reloaded
  110.  */
  111. public void init() {
  112.  
  113.     setLayout(new BorderLayout());
  114.     Panel p = new Panel ();
  115.     add("South", p);
  116.     btnSmaller = new Button("Smaller");
  117.     p.add (btnSmaller);
  118.       btnBigger = new Button("Bigger");
  119.     p.add (btnBigger);
  120.     btnSmaller.addActionListener(this);
  121.        btnBigger.addActionListener(this);
  122.  
  123.     MediaTracker tracker = new MediaTracker (this); 
  124.  
  125.     img = getImage (getDocumentBase(), "T1.gif");
  126.     tracker.addImage (img, 0);
  127.     showStatus ("Getting image: T1.gif");
  128.     try {
  129.         tracker.waitForID (0);
  130.     } catch (InterruptedException e) { }
  131.     width = img.getWidth (this);
  132.     height = img.getHeight (this);
  133. }
  134.  
  135. public void paint (Graphics g) {
  136.     double w, h;
  137.  
  138.  
  139.     w = scale * width;
  140.     h = scale * height;
  141.  
  142.     // if we don't have the size yet, we shouldn't draw
  143.     if (w < 0 || h < 0) { w=75; h=75; } //return;
  144.  
  145.     // explicitly specify width (w) and height (h)
  146.     g.drawImage (img, 10, 10, (int) w, (int) h, this);
  147. }
  148. public void actionPerformed(ActionEvent evt)
  149. {
  150.     Object object1 = evt.getSource();
  151.     if (object1 == btnSmaller)
  152.     {
  153.         scale *= 0.9;    // make it 10% smaller
  154.         repaint ();
  155.     }
  156.     if (object1 == btnBigger)
  157.     {
  158.         scale *= 1.1;    // make it 10% bigger
  159.         repaint ();
  160.     }
  161. }
  162.  
  163. }
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172. ImageMove.java:
  173.  
  174. import java.awt.*;
  175. import java.awt.event.*;
  176. import java.applet.Applet;
  177.  
  178. /*
  179.  * the applet class
  180.  */
  181. public class ImageMove extends Applet implementsσ
  182.  MouseListener, MouseMotionListener{
  183.  
  184. /*
  185.  * the image to be displayed
  186.  */
  187. Image img;
  188.  
  189. /*
  190.  * the width and height of the image
  191.  */
  192. int width, height;
  193.  
  194. /*
  195.  * xpos, ypos are the coordinates of the upper left of the image
  196.  */
  197. int xpos=10, ypos=10;
  198.  
  199. /*
  200.  * dx, dy are the deltas from the mouse point to xpos, ypos
  201.  */
  202. int dx, dy;
  203.  
  204. /*
  205.  * called when the applet is loaded
  206.  * load the image and use MediaTracker so that
  207.  * the width and height are available immediately
  208.  */
  209. public void init () {
  210.  
  211.     MediaTracker tracker = new MediaTracker (this); 
  212.  
  213.     img = getImage (getDocumentBase(), "T1.gif");
  214.     tracker.addImage (img, 0);
  215.     showStatus ("Getting image: T1.gif");
  216.     try {
  217.         tracker.waitForID (0);
  218.     } catch (InterruptedException e) { }
  219.     width = img.getWidth (this);
  220.     height = img.getHeight (this);
  221.     addMouseListener(this);
  222.     addMouseMotionListener(this); 
  223. }
  224.  
  225. /*
  226.  * paint the image in the new location
  227.  * @param g - destination graphics object
  228.  */
  229. public void paint (Graphics g) {
  230.  
  231.     g.setColor (Color.white);
  232.     g.drawImage (img, xpos, ypos, this);
  233. }
  234.  
  235.  
  236. /*
  237.  * adjust the new position and repaint the image
  238.  */
  239.  
  240. public void mouseClicked(MouseEvent e){}
  241. public void mouseEntered(MouseEvent e){}
  242. public void mouseExited(MouseEvent e){}
  243. public void mouseReleased(MouseEvent e){}
  244. public void mouseMoved(MouseEvent e){}
  245.  
  246. public void mousePressed(MouseEvent e)
  247. {
  248.     int x =e.getX();
  249.     int y =e.getY();
  250.  
  251.     dx = x - xpos;
  252.     dy = y - ypos;
  253. }
  254.  
  255. public void mouseDragged(MouseEvent e)
  256. {
  257.     int x =e.getX();
  258.     int y =e.getY();
  259.     if (dx < width && dx >= 0 && dy < height && dy >= 0)
  260.     {
  261.         xpos = x - dx;
  262.         ypos = y - dy;
  263.         repaint ();
  264.     }
  265. }
  266.  
  267. }
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276. Bounce.java:
  277.  
  278. import java.awt.*;
  279. import java.awt.event.*;
  280. import java.applet.Applet;
  281. import java.awt.image.ImageObserver;
  282.  
  283. /*
  284.  * a class describing a single ball
  285.  */
  286. class Ball {
  287.  
  288. /*
  289.  * the image for this ball
  290.  */
  291. Image img;
  292.  
  293. /*
  294.  * x position and velocity
  295.  */
  296. double x, dx;
  297.  
  298. /*
  299.  * y position and velocity
  300.  */
  301. double y, dy;
  302.  
  303. /*
  304.  * initialize the position and velocity
  305.  * to random values
  306.  */
  307. void random () {
  308.  
  309.     x = 10 + 380*Math.random ();
  310.     y = 10 + 200*Math.random ();
  311.     dx = 5 - 10*Math.random ();
  312.     dy = 5 - 10*Math.random ();
  313. }
  314.  
  315. /**
  316.  * calculate the next position of this ball
  317.  * and make sure it bounces off the edge of the panel
  318.  * @param d - dimension of the bounding panel
  319.  */
  320. void compute (Dimension d) {
  321.  
  322.     if (x <= 0 || x > d.width) dx = -dx;    // bounce horizontal
  323.     if (y <= 0 || y > d.height) dy = -dy;   // bounce vertical
  324.     x += dx;
  325.     y += dy; 
  326. }
  327.  
  328. /**
  329.  * draw the ball image
  330.  * @param g - destination graphics object
  331.  * @param obs - parent image observer
  332.  */
  333. public void paint (Graphics g, ImageObserver obs) {
  334.     g.drawImage (img, (int) x-10, (int) y-10, obs); 
  335. }
  336. }
  337.  
  338. /*
  339.  * the panel containing the bouncing balls
  340.  */
  341. class BouncePanel extends Panel implements Runnable {
  342.  
  343. /*
  344.  * the number of balls
  345.  */
  346. final int nballs = 4;
  347.  
  348. /*
  349.  * the array holding all the balls
  350.  */
  351. Ball balls[] = new Ball[10];
  352.  
  353. /*
  354.  * offscreen image
  355.  */
  356. Image offimg;
  357.  
  358. /*
  359.  * size of offscreen image
  360.  */
  361. Dimension offsize;
  362.  
  363. /*
  364.  * graphics object associated with offscreen image
  365.  */
  366. Graphics offg;
  367.  
  368. /*
  369.  * thread for periodic updating
  370.  */
  371. Thread thread; 
  372.  
  373. /*
  374.  * the thread recalculates each ball position and
  375.  * redraws them
  376.  */
  377. public void run() {
  378.  
  379.     offsize = getSize();
  380.     offimg = createImage (offsize.width, offsize.height); 
  381.     offg = offimg.getGraphics();
  382.     while (true) {
  383.         for (int i=0; i<nballs; i+=1) {
  384.             balls[i].compute (offsize);
  385.         }
  386.         repaint ();
  387.         try {
  388.             Thread.sleep (25);
  389.         } catch (InterruptedException e) {
  390.             break;
  391.         }
  392.     }
  393. }
  394.  
  395. /**
  396.  * override update to avoid erase flicker
  397.  * @param g - destination graphics object
  398.  */
  399. public synchronized void update (Graphics g) {
  400.  
  401.     offg.setColor (Color.lightGray);
  402.     offg.fillRect (0, 0, offsize.width, offsize.height);
  403.  
  404.     for (int i = 0 ; i < nballs ; i++)
  405.         balls[i].paint (offg, this);
  406.     offg.setColor (Color.black);
  407.     offg.drawRect (0, 0, offsize.width-1, offsize.height-1); 
  408.     g.drawImage(offimg, 0, 0, this);
  409. }
  410.  
  411. /*
  412.  * start the update thread
  413.  */
  414. public void start() {
  415.  
  416.     thread = new Thread(this);
  417.     thread.start();
  418. }
  419.  
  420. /*
  421.  * stop the update thread
  422.  */
  423. public void stop() {
  424.  
  425.     if (thread != null) 
  426.     {
  427.         thread = null;
  428.     }
  429. }
  430. }
  431.  
  432. /*
  433.  * the applet proper
  434.  */
  435. public class Bounce extends Applet implements ActionListener {
  436.  
  437. /*
  438.  * instance of BouncePanel
  439.  */
  440. BouncePanel panel;
  441. Button button1;
  442. /*
  443.  * an array containing the images for the balls
  444.  */
  445. Image img[] = new Image[4];
  446.  
  447. /*
  448.  * called when the applet is loaded
  449.  * create an instance of bounce panel and add the Start button
  450.  * and load images
  451.  */
  452. public void init() {
  453.  
  454.     setLayout(new BorderLayout());
  455.  
  456.     panel = new BouncePanel ();
  457.     add ("Center", panel);
  458.     Panel p = new Panel ();
  459.     add ("South", p);
  460.  
  461.     button1 = new Button("Start");
  462.     p.add (button1);
  463.     button1.addActionListener(this);
  464.  
  465.     img[0] = getImage (getDocumentBase(), "whiteball.gif");
  466.     img[1] = getImage (getDocumentBase(), "redball.gif");
  467.     img[2] = getImage (getDocumentBase(), "blueball.gif");
  468.     img[3] = getImage (getDocumentBase(), "greenball.gif");
  469.     for (int i=0; i<panel.nballs; i+=1) {
  470.         panel.balls[i] = new Ball ();
  471.         panel.balls[i].img = img[i & 3]; 
  472.     }
  473. }
  474.  
  475. /*
  476.  * called when the applet is started
  477.  * just start the bounce panel update thread
  478.  */
  479. public void start() {
  480.  
  481.     panel.start();
  482. }
  483.  
  484. /*
  485.  * called when the applet is stopped
  486.  */
  487. public void stop() {
  488.  
  489.     panel.stop();
  490. }
  491.  
  492. /*
  493.  * handle Start button press by randomizing balls
  494.  * @param evt - event object
  495.  * @param arg - target object
  496.  */
  497.  
  498. public void actionPerformed(ActionEvent evt)
  499. {
  500.         for (int i=0; i<panel.nballs; i+=1)
  501.             panel.balls[i].random ();
  502. }
  503.  
  504. }
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515. LayerApp.java:
  516.  
  517. import java.awt.*;
  518. import java.awt.event.*;
  519. import java.applet.Applet;
  520. import java.awt.image.*;
  521.  
  522. /*
  523.  * class for handling one image
  524.  */
  525. class Picture {
  526.  
  527. /*
  528.  * position of the image
  529.  */
  530. int xpos, ypos;
  531.  
  532. /*
  533.  * width and height of the image
  534.  */
  535. int width, height;
  536.  
  537. /*
  538.  * the image itself
  539.  */
  540. Image image;
  541. ImageObserver obs;
  542.  
  543. /**
  544.  * constructor saves arguments
  545.  * @param img - the image
  546.  * @param x, y - initial position
  547.  * @param o - imageObserver of parent
  548.  */
  549. public Picture (Image img, int x, int y, ImageObserver o) {
  550.  
  551.     image = img;
  552.     xpos = x;
  553.     ypos = y;
  554.     obs = o;
  555.     width = image.getWidth (obs);
  556.     height = image.getHeight (obs);
  557. }
  558.  
  559. /**
  560.  * determine whether the point is inside this image
  561.  * @param x, y - coordinate of point
  562.  */
  563. boolean inside (int x, int y) {
  564.  
  565.     if (x < xpos || x > (xpos+width)) return false;
  566.     if (y < ypos || y > (ypos+height)) return false;
  567.     return true; 
  568. }
  569.  
  570. /**
  571.  * set the current position of the image
  572.  * @param x, y - position to set
  573.  */
  574. void setPosition (int x, int y) {
  575.  
  576.     xpos = x;
  577.     ypos = y;
  578. }
  579.  
  580. /**
  581.  * draw the image
  582.  * draw a green border around the image if
  583.  * highlight is true
  584.  * @param g - destination graphics object
  585.  * @param highlight - draw border
  586.  */
  587. void paint (Graphics g, boolean highlight) {
  588.  
  589.     if (highlight) {
  590.         g.setColor (Color.green);
  591.         g.fillRect (xpos-5, ypos-5, width+10, height+10);
  592.     }
  593.     g.drawImage (image, xpos, ypos, obs);
  594. }
  595. }
  596.  
  597. /*
  598.  * the applet
  599.  */
  600. public class LayerApp extends Applet implements MouseListener,
  601.         MouseMotionListener, ActionListener
  602. {
  603.  
  604. /*
  605.  * the number of picture objects
  606.  */
  607. final int NPictures = 4;
  608.  
  609. /*
  610.  * an array containing the picture objects
  611.  */
  612. Picture pictures[] = new Picture[NPictures];
  613.  
  614. /*
  615.  * the user-selected picture
  616.  */
  617. int selectedPic = -1;
  618.  
  619. /*
  620.  * offsets from mouse to image origin
  621.  */
  622. int dx, dy; 
  623.  
  624. /*
  625.  * offscreen image for double-buffering
  626.  */
  627. Image offimg;
  628. Button btnBring;
  629. Button btnSend;
  630.  
  631. /*
  632.  * offscreen graphics context associated with
  633.  * offscreen image
  634.  */
  635. Graphics offg;
  636.  
  637. /*
  638.  * dimension of offscreen image
  639.  */
  640. Dimension offsize;
  641.  
  642. /*
  643.  * called when the applet is loaded
  644.  */
  645. public void init() {
  646.  
  647.     setLayout(new BorderLayout());
  648.  
  649.     Panel p = new Panel ();
  650.     add ("South", p);
  651.     btnBring = new Button("Bring to front");
  652.     btnSend = new Button("Send to back");
  653.     p.add(btnBring);
  654.     p.add(btnSend);
  655.     addMouseListener(this);
  656.     addMouseMotionListener(this);
  657.     btnBring.addActionListener(this);
  658.     btnSend.addActionListener(this);
  659.  
  660.     int i;
  661.     Image img;
  662.     String name;
  663.     MediaTracker tracker = new MediaTracker (this);
  664.  
  665.     offsize = getSize();
  666.     offimg = createImage (offsize.width, offsize.height);
  667.     offg = offimg.getGraphics();
  668.  
  669.     for (i=0; i<NPictures; i+=1) {
  670.                 if (i < 2) name = "T"+(i+1)+".jpg";
  671.                 else name = "T"+(i+1)+".gif";
  672.         img = getImage (getDocumentBase(), name);
  673.         tracker.addImage (img, i);
  674.         showStatus ("Getting image: "+name);
  675.         try {
  676.             tracker.waitForID (i);
  677.         } catch (InterruptedException e) { }
  678.         pictures[i] = new Picture (img, i*10, i*20, this);
  679.     }
  680. }
  681.  
  682. /**
  683.  * reverse the order of update for efficiency
  684.  * @param g - destination graphics object
  685.  */
  686. public void paint (Graphics g) {
  687.  
  688.     update (g);
  689. }
  690.  
  691. /**
  692.  * override update to avoid erase flicker
  693.  * @param g - destination graphics object
  694.  */
  695. public void update (Graphics g) {
  696.  
  697.     int i;
  698.  
  699.     offg.setColor (Color.black);
  700.     offg.fillRect (0, 0, offsize.width, offsize.height);
  701.     for (i=0; i<NPictures; i+=1) {
  702.         if (i == selectedPic) pictures[i].paint (offg, true);
  703.         else pictures[i].paint (offg, false);
  704.     }
  705.     g.drawImage(offimg, 0, 0, this);
  706. }
  707.  
  708. /**
  709.  * determine which image the user clicked 
  710.  * @param evt - event object
  711.  * @param x, y - mouse position
  712.  */
  713. public void mouseClicked(MouseEvent e){}
  714. public void mouseEntered(MouseEvent e){}
  715. public void mouseExited(MouseEvent e){} 
  716.  
  717. public void mouseReleased(MouseEvent e)
  718. {
  719.     repaint ();
  720. }
  721.  
  722. public void mouseMoved(MouseEvent e){}
  723.  
  724. public void mousePressed(MouseEvent e)
  725. {
  726.     int x =e.getX();
  727.     int y =e.getY();
  728.  
  729.     int i;
  730.  
  731.     selectedPic = -1;
  732.     for (i=NPictures-1; i>=0; i-=1)
  733.     {
  734.         if (pictures[i].inside (x, y))
  735.         {
  736.             selectedPic = i;
  737.             dx = x - pictures[i].xpos;
  738.             dy = y - pictures[i].ypos;
  739.             break;
  740.         }
  741.     }
  742. }
  743.  
  744. public void mouseDragged(MouseEvent e)
  745. {
  746.     int x =e.getX();
  747.     int y =e.getY();
  748.     int i;
  749.  
  750.     if (selectedPic < 0) return;
  751.     /* for (i=NPictures-1; i>=0; i-=1)
  752.     {
  753.  
  754.         pictures[selectedPic].setPosition (x - dx, y - dy);
  755.         repaint ();
  756.     } */
  757.  
  758. }
  759. /**
  760.  * reorder the images depending on which button is pressed
  761.  * @param evt - event object
  762.  * @param arg - target object
  763.  */
  764. public void actionPerformed(ActionEvent evt)
  765. {
  766.     Object object1 = evt.getSource();
  767.     int i;
  768.     Picture temp;
  769.  
  770.  
  771.     if (object1 == btnBring) {
  772.         if (selectedPic < 0) return;
  773.         temp = pictures[selectedPic];
  774.         for (i=selectedPic; i<NPictures-1; i+=1)
  775.         {
  776.             pictures[i] = pictures[i+1];
  777.         }
  778.         pictures[NPictures-1] = temp;
  779.         selectedPic = NPictures - 1;
  780.         repaint ();
  781.         return;
  782.     }
  783.     if (object1 == btnSend)
  784.     {
  785.         if (selectedPic < 0) return;
  786.         temp = pictures[selectedPic];
  787.         for (i=selectedPic; i>0; i-=1) 
  788.         {
  789.             pictures[i] = pictures[i-1];
  790.         }
  791.         pictures[0] = temp;
  792.         selectedPic = 0;
  793.         repaint ();
  794.         return;
  795.     }
  796. }
  797. }
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805. Advertiser.java:
  806.  
  807. import java.util.*;
  808. import java.awt.*;
  809. import java.applet.Applet;
  810.  
  811. /*
  812.  * A class that performs the banner animation
  813.  */
  814. class Banner extends Panel implements Runnable {
  815.  
  816. /*
  817.  * an instance of the applet for
  818.  * invoking methods from the Advertiser class
  819.  */
  820. Advertiser advertiser;
  821.  
  822. /*
  823.  * instance of thread used for animation
  824.  */
  825. Thread thread;
  826.  
  827. /*
  828.  * the next banner image to be displayed
  829.  */
  830. Image theImage;
  831.  
  832. /*
  833.  * width and height of the new banner image
  834.  */
  835. int img_width, img_height;
  836.  
  837. /*
  838.  * offscreen image for double-buffering
  839.  */
  840. Image offscreen;
  841.  
  842. /*
  843.  * offg1 is the graphics object associated with
  844.  * offscreen image. offg2 is the clipped version
  845.  * of offg1
  846.  */
  847. Graphics offg1, offg2; 
  848.  
  849. /*
  850.  * xstart, ystart - x and y coordinate of clipping rectangle
  851.  * width, height - width and height of clipping rectangle
  852.  * effect_type - the effect type applied to the next image
  853.  */
  854. int xstart, ystart, width, height, effect_type; 
  855.  
  856. /**
  857.  * constructor just saves instance of the applet
  858.  * @param advertiser - instance of advertiser applet
  859.  */
  860. Banner (Advertiser advertiser) {
  861.  
  862.     this.advertiser = advertiser;
  863. }
  864.  
  865. /*
  866.  * thread that calls repaint() every 25ms
  867.  * to effect animation
  868.  */
  869. public void run() {
  870.  
  871.     Dimension d = getSize();
  872.     offscreen = createImage (d.width, d.height);
  873.     offg1 = offscreen.getGraphics ();
  874.     offg1.setFont (getFont ());
  875.     offg1.setColor (Color.gray);
  876.     offg1.fillRect (0, 0, d.width, d.height);
  877.     while (true) {
  878.         repaint ();
  879.         try {
  880.             Thread.sleep (25);
  881.         } catch (InterruptedException e) {
  882.             break;
  883.         }
  884.     }
  885. }
  886.  
  887. /**
  888.  * override update() method to avoid erase flicker
  889.  * this is where the drawing is done
  890.  * @param g - destination graphics object
  891.  */
  892. public synchronized void update(Graphics g) {
  893.  
  894.     int i, x, y, w, h;
  895.     switch (effect_type) {
  896.         case 0:
  897.         offg1.drawImage (theImage, 0, 0, null);
  898.         break;
  899.  
  900.         case 1:        // barn-door open
  901.         if (xstart > 0) {
  902.             xstart -= 5;
  903.             width += 10;
  904.             offg2 = offg1.create (xstart, 0, width, height);
  905.             offg2.drawImage (theImage, -xstart, 0, null);
  906.         } else offg1.drawImage (theImage, 0, 0, null); 
  907.         break;
  908.  
  909.         case 2:        // venetian blind
  910.         if (height < 10) {
  911.             height += 1;
  912.             for (y=0; y<img_height; y+=10) {
  913.                 offg2 = offg1.create (0, y, width, height);
  914.                 offg2.drawImage (theImage, 0, -y, null);
  915.             }
  916.         } else offg1.drawImage (theImage, 0, 0, null);
  917.         break;
  918.  
  919.         case 3:        // checkerboard
  920.         if (width <= 20) {
  921.             if (width <= 10) {
  922.                 i = 0;
  923.                 for (y=0; y<img_height; y+=10) {
  924.                     for (x=(i&1)*10; x<img_width; x+=20) {
  925.                         offg2 = offg1.create (x, y, width, 10);
  926.                         offg2.drawImage (theImage, -x, -y,σ
  927.  null);
  928.                     }
  929.                     i += 1;
  930.                 }
  931.             } else {
  932.                 i = 1;
  933.                 for (y=0; y<img_height; y+=10) {
  934.                     for (x=(i&1)*10; x<img_width; x+=20) {
  935.                         offg2 = offg1.create (x, y,[cc]
  936.  width-10, 10);
  937.                         offg2.drawImage (theImage,σ
  938.  -x, -y, null);
  939.                     }
  940.                     i += 1; 
  941.                 }
  942.             }
  943.             width += 5;
  944.         } else offg1.drawImage (theImage, 0, 0, null);
  945.         break;
  946.     }
  947.     g.drawImage (offscreen, 0, 0, null);
  948. }
  949.  
  950. /**
  951.  * initialize variables for clipping rectangle
  952.  * depending on effect type
  953.  * @param which - the effect type for next image
  954.  * @param img - the next image
  955.  */
  956. public void effect (int which, Image img) {
  957.  
  958.     img_width = img.getWidth (null);
  959.     img_height = img.getHeight (null); 
  960.     theImage = img;
  961.     switch (which) {
  962.         case 0:
  963.         break;
  964.  
  965.         case 1:        // barn door
  966.         xstart = img_width >> 1;
  967.         width = 0;
  968.         height = img_height;
  969.         break;
  970.  
  971.         case 2:
  972.         width = img_width;
  973.         height = 0;
  974.         break;
  975.  
  976.         case 3:
  977.         width = 0;
  978.         break;
  979.     }
  980.     effect_type = which;
  981. }
  982.  
  983. /*
  984.  * start the repaint thread
  985.  */
  986. public void start() {
  987.  
  988.     thread = new Thread(this);
  989.     thread.start();
  990. }
  991.  
  992. /*
  993.  * stop the repaint thread
  994.  */
  995. public void stop() {
  996.  
  997.     if (thread != null)
  998.         thread = null;
  999. }
  1000. }
  1001.  
  1002. /*
  1003.  * the Advertiser class proper
  1004.  */
  1005. public class Advertiser extends Applet implements Runnable {
  1006.  
  1007. /*
  1008.  * instance of Banner
  1009.  */
  1010. Banner panel;
  1011.  
  1012. /*
  1013.  * instance of thread for cycling effects
  1014.  * for each new image
  1015.  */
  1016. Thread thread;
  1017.  
  1018. /*
  1019.  * the total number of images
  1020.  */
  1021. int NBanners; 
  1022.  
  1023. /*
  1024.  * the array of images
  1025.  */
  1026. Image img[] = new Image[10];
  1027.  
  1028. /*
  1029.  * the delay (dwell) time in milliseconds for each image
  1030.  */
  1031. int delay[] = new int[10];
  1032.  
  1033. /*
  1034.  * the effect type for each image
  1035.  */
  1036. int effect[] = new int[10];
  1037.  
  1038. /*
  1039.  * called when applet is loaded
  1040.  * add the banner panel, load images, and parse applet
  1041.  * parameters
  1042.  */
  1043. public void init() {
  1044.  
  1045.     int i;
  1046.     setLayout(new BorderLayout());
  1047.  
  1048.     panel = new Banner (this);
  1049.     add("Center", panel);
  1050.     NBanners = 0;
  1051.     MediaTracker tracker = new MediaTracker (this);
  1052.  
  1053.     for (i=1; i<=10; i+=1) {
  1054.         String param, token;
  1055.         int j, next;
  1056.  
  1057.         param = getParameter ("T"+i);
  1058.         if (param == null) break;
  1059.  
  1060.         StringTokenizer st = new StringTokenizer (param, " ,");
  1061.  
  1062.         token = st.nextToken ();
  1063.         img[NBanners] = getImage (getDocumentBase(), token);
  1064.         tracker.addImage (img[NBanners], i);
  1065.         showStatus ("Getting image: "+token);
  1066.         try {
  1067.             tracker.waitForID (i);
  1068.         } catch (InterruptedException e) { }
  1069.  
  1070.         token = st.nextToken ();
  1071.         delay[NBanners] = Integer.parseInt (token);
  1072.  
  1073.         token = st.nextToken ();
  1074.         effect[NBanners] = Integer.parseInt (token);
  1075.  
  1076.         NBanners += 1;
  1077.     }
  1078. }
  1079.  
  1080. /*
  1081.  * thread that starts the next image transition
  1082.  */
  1083. public void run () {
  1084.  
  1085.     int current = 0;
  1086.  
  1087.     while (true) {
  1088.         panel.effect (effect[current], img[current]);
  1089.         try {
  1090.             Thread.sleep (delay[current]);
  1091.         } catch (InterruptedException e) { }
  1092.         current += 1;
  1093.         current %= NBanners; 
  1094.     }
  1095. }
  1096.  
  1097. /*
  1098.  * called when applet is started
  1099.  * start both threads
  1100.  */
  1101. public void start() {
  1102.  
  1103.     panel.start();
  1104.     thread = new Thread(this);
  1105.     thread.start();
  1106. }
  1107.  
  1108. /*
  1109.  * called when applet is stopped
  1110.  * stops all threads
  1111.  */
  1112. public void stop() {
  1113.  
  1114.     panel.stop();
  1115.  
  1116.     if (panel != null)
  1117.         panel = null;
  1118.  
  1119.     if (thread != null)
  1120.         thread = null;
  1121. }
  1122. }
  1123.  
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131. Mandelbrot.java:
  1132.  
  1133. import java.applet.Applet;
  1134. import java.awt.*;
  1135. import java.awt.event.*;
  1136. import java.awt.image.*;
  1137.  
  1138. /*
  1139.  * a class for generating and displaying the
  1140.  * Mandelbrot set
  1141.  */
  1142. public class Mandelbrot extends Applet implements MouseListener,
  1143.                         MouseMotionListener, ActionListener
  1144. {
  1145.  
  1146. /*
  1147.  * the maximum number of colors for
  1148.  * each pixel
  1149.  */
  1150. final int MaxColors = 256;
  1151.  
  1152. /*
  1153.  * the width and height of the image
  1154.  */
  1155. int mWidth, mHeight;
  1156.  
  1157. /*
  1158.  * the array of pixel values
  1159.  */
  1160. int pixels[];
  1161.  
  1162. /*
  1163.  * the set values
  1164.  */
  1165. int mandelSet[];
  1166.  
  1167. /*
  1168.  * the image produce by the set
  1169.  */
  1170. Image theImage = null;
  1171.  
  1172. /*
  1173.  * the mapping function from set values to pixel values
  1174.  */
  1175. int pixMap[] = new int[MaxColors];
  1176.  
  1177. /*
  1178.  * a flag used for recalculating
  1179.  */
  1180. boolean startCalculate = false;
  1181.  
  1182. /*
  1183.  * instance of MandelRect class
  1184.  */
  1185. MandelRect mandelRect;
  1186.  
  1187. /*
  1188.  * the control buttons
  1189.  */
  1190. Button startButton;
  1191. Button zoomButton;
  1192.  
  1193. /*
  1194.  * called when the applet is loaded
  1195.  * initialize the pixmap array and add user interface
  1196.  */
  1197. public void init () {
  1198.  
  1199.     mWidth = 100;
  1200.     mHeight = 100;
  1201.     pixels = new int [mWidth * mHeight];
  1202.     mandelSet = new int [mWidth * mHeight];
  1203.  
  1204.     mandelRect = new MandelRect (mWidth, mHeight);
  1205.  
  1206.     int red, green, blue;
  1207.     int i;
  1208.  
  1209.     pixMap[0] = 0xffffffff;
  1210.     for (i=1; i<MaxColors-1; i+=1) {
  1211.         red = i;
  1212.         green = (i<128) ? i << 1 : 255-(i<<1);
  1213.         blue = MaxColors-i;
  1214.         pixMap[i] = (255 << 24) | (red << 16) | (green << 8) | blue;
  1215.     }
  1216.     pixMap[MaxColors-1] = 0xff000000;
  1217.  
  1218.     setLayout(new BorderLayout());
  1219.  
  1220.     startButton = new Button ("Start over");
  1221.     zoomButton = new Button ("Zoom in");
  1222.     startButton.addActionListener(this);
  1223.     zoomButton.addActionListener(this);
  1224.     addMouseListener(this);
  1225.     addMouseMotionListener(this);
  1226.  
  1227.     Panel p = new Panel ();
  1228.     p.setLayout (new FlowLayout ());
  1229.     p.add (startButton);
  1230.     p.add (zoomButton);
  1231.     add ("South", p);
  1232. }
  1233.  
  1234. /*
  1235.  * called when the applet is started
  1236.  * forces a recalculation of the set
  1237.  */
  1238. public void start () {
  1239.  
  1240.     startCalculate = true;
  1241.     repaint ();
  1242. }
  1243.  
  1244. /*
  1245.  * call update for efficiency
  1246.  * @param g - destination graphics object
  1247.  */
  1248. public void paint (Graphics g) {
  1249.  
  1250.     update (g);
  1251. }
  1252.  
  1253. /**
  1254.  * override default update() method to avoid erase flicker
  1255.  * @param g - destination graphics object
  1256.  */
  1257. public void update (Graphics g) {
  1258.  
  1259.     if (startCalculate) {
  1260.         calculate ();
  1261.         startCalculate = false;
  1262.     }
  1263.     if (theImage != null) g.drawImage (theImage, 0, 0, this);
  1264.     else repaint (1000);
  1265.     mandelRect.paint (g);
  1266. }
  1267.  
  1268. /*
  1269.  * perform the actual set calculation
  1270.  */
  1271. void calculate () {
  1272.  
  1273.     int i, index;
  1274.     double width, height;
  1275.     double row, col;
  1276.     double zr, zi, cr, ci, tzr, tzi;
  1277.     double hFactor, vFactor;
  1278.     double x, y;
  1279.  
  1280.     theImage = null;
  1281.  
  1282.     x = mandelRect.mandelX;
  1283.     y = mandelRect.mandelY;
  1284.     width = (double) mandelRect.imgWidth;
  1285.     height = (double) mandelRect.imgHeight;
  1286.     hFactor = mandelRect.mandelWidth/width;
  1287.     vFactor = mandelRect.mandelHeight/height;
  1288.  
  1289.     index = 0;
  1290.     for (row=0; row<height; row+=1) {
  1291.         for (col=0; col<width; col+=1) {
  1292.             zr = 0;
  1293.             zi = 0;
  1294.             cr = x + col * hFactor;
  1295.             ci = y + row * vFactor;
  1296.             for (i=1; i<64; i+=1) {
  1297.                 tzr = zr*zr - zi*zi + cr;
  1298.                 tzi = 2*zr*zi + ci;
  1299.                 zr = tzr;
  1300.                 zi = tzi;
  1301.                 if (zr*zr + zi*zi > 4.0) break;
  1302.             }
  1303.             mandelSet[index++] = (i << 2)-1;
  1304.         }
  1305.     }
  1306.  
  1307.     for (i=0; i<mWidth*mHeight; i+=1) {
  1308.         pixels[i] = pixMap[mandelSet[i]];
  1309.     }
  1310.  
  1311.     theImage = createImage (
  1312.         new MemoryImageSource(mWidth, mHeight, pixels, 0, mWidth));
  1313. }
  1314.  
  1315. public void mouseClicked(MouseEvent e){}
  1316. public void mouseEntered(MouseEvent e){}
  1317. public void mouseExited(MouseEvent e){}
  1318.  
  1319. public void mouseReleased(MouseEvent e)
  1320. {
  1321.     int x =e.getX();
  1322.     int y =e.getY();
  1323.  
  1324.     mandelRect.setWidthHeight (x, y);
  1325.     mandelRect.setPaintRect (true);
  1326.     repaint ();
  1327. }
  1328.  
  1329. public void mouseMoved(MouseEvent e){}
  1330.  
  1331. public void mousePressed(MouseEvent e)
  1332. {
  1333.     int x =e.getX();
  1334.     int y =e.getY();
  1335.  
  1336.     mandelRect.setXY (x, y);
  1337. }
  1338.  
  1339. public void mouseDragged(MouseEvent e)
  1340. {
  1341.     int x =e.getX();
  1342.     int y =e.getY();
  1343.  
  1344.     mandelRect.setWidthHeight (x, y);
  1345.     mandelRect.setPaintRect (true);
  1346.     repaint ();
  1347.  
  1348. }
  1349. /**
  1350.  * reorder the images, depending on which button is pressed
  1351.  * @param evt - event object
  1352.  * @param arg - target object
  1353.  */
  1354. public void actionPerformed(ActionEvent evt)
  1355. {
  1356.     Object object1 = evt.getSource();
  1357.  
  1358.     if (object1 == startButton) {
  1359.         mandelRect = new MandelRect (mWidth, mHeight);
  1360.         startCalculate = true;
  1361.         repaint ();
  1362.     }
  1363.     if (object1 == zoomButton)
  1364.     {
  1365.         startCalculate = true;
  1366.         mandelRect.setPaintRect (false);
  1367.         mandelRect.scaleSet ();
  1368.         repaint ();
  1369.     }
  1370. }
  1371.  
  1372. /**
  1373.  * application entry point
  1374.  * create window and new set
  1375.  * @param args - command-line arguments
  1376.  */
  1377. public static void main (String args[]) {
  1378.  
  1379.     Frame f = new Frame ("Mandelbrot set");
  1380.     Mandelbrot mandel = new Mandelbrot ();
  1381.  
  1382.     mandel.init ();
  1383.     f.setSize (210, 275);
  1384.     f.add ("Center", mandel);
  1385.     f.show ();
  1386.     f.addWindowListener(new WindowCloser());
  1387.  
  1388.     mandel.start ();
  1389. }
  1390. }
  1391.  
  1392. class WindowCloser extends WindowAdapter
  1393. {
  1394.     public void windowClosing(WindowEvent e)
  1395.     {
  1396.         Window win = e.getWindow();
  1397.         win.setVisible(false);
  1398.         win.dispose();
  1399.         System.exit(0);
  1400.     }
  1401. }
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408.  
  1409. MandelRect.java:
  1410.  
  1411. import java.awt.*;
  1412.  
  1413. /*
  1414.  * a helper class to manage the zoom rectangle
  1415.  */
  1416. public class MandelRect {
  1417.  
  1418. /*
  1419.  * the coordinates of the zoom rectangle
  1420.  * in screen space
  1421.  */
  1422. int x;
  1423. int y;
  1424. int width;
  1425. int height;
  1426.  
  1427. /*
  1428.  * the final image width and height
  1429.  */
  1430. int imgWidth;
  1431. int imgHeight;
  1432.  
  1433. /*
  1434.  * the coordinates of the zoom rectangle
  1435.  * in set space
  1436.  */
  1437. double mandelX;
  1438. double mandelY;
  1439. double mandelWidth;
  1440. double mandelHeight;
  1441.  
  1442. /*
  1443.  * set to true if the zoom rectangle should be painted
  1444.  */
  1445. boolean paintRect;
  1446.  
  1447. /**
  1448.  * constructor initializes variables
  1449.  * @param iW - final image width
  1450.  * @param iH - final image height
  1451.  */
  1452. public MandelRect (int iW, int iH) {
  1453.  
  1454.     imgWidth = iW;
  1455.     imgHeight = iH;
  1456.     paintRect = false;
  1457.  
  1458.     mandelX = -1.75;
  1459.     mandelY = -1.125;
  1460.     mandelWidth = 2.25;
  1461.     mandelHeight = 2.25; 
  1462. }
  1463.  
  1464. /**
  1465.  * set the top left of the zoom rectangle in screen space
  1466.  * @param ix, iy - top-left corner of zoom rectangle
  1467.  */
  1468. void setXY (int ix, int iy) {
  1469.  
  1470.     x = ix;
  1471.     y = iy;
  1472. }
  1473.  
  1474. /**
  1475.  * set the width, height of the zoom rectangle in screen space
  1476.  * @param ix, iy - bottom-right corner of zoom rectangle
  1477.  */
  1478. void setWidthHeight (int ix, int iy) {
  1479.  
  1480.     width = ix - x;
  1481.     height = iy - y; 
  1482. }
  1483.  
  1484. /*
  1485.  * translate screen coordinates to set coordinates
  1486.  */
  1487. void scaleSet () {
  1488.  
  1489.     int tx, ty, tw, th;
  1490.  
  1491.     tx = x;
  1492.     ty = y;
  1493.     tw = width;
  1494.     th = height;
  1495.     if (tw < 0) {
  1496.         tw = -width;
  1497.         tx = x-tw;
  1498.     }
  1499.     if (th < 0) {
  1500.         th = -height;
  1501.         ty = y-th;
  1502.     }
  1503.     mandelX = mandelX + (mandelWidth) * ((double) tx)/((double) imgWidth);
  1504.     mandelY = mandelY + (mandelHeight) * ((double) ty)/((double) imgHeight);
  1505.     mandelWidth = mandelWidth * ((double) tw)/((double)imgWidth);
  1506.     mandelHeight = mandelHeight * ((double) th)/((double)imgHeight);
  1507. }
  1508.  
  1509. /**
  1510.  * set the paintRect flag
  1511.  * @param p - true means zoom rectangle should be painted
  1512.  */
  1513. void setPaintRect (boolean p) {
  1514.  
  1515.     paintRect = p;
  1516. }
  1517.  
  1518. /**
  1519.  * paint the zoom rectangle if necessary
  1520.  * @param g - destination graphics object
  1521.  */
  1522. void paint (Graphics g) {
  1523.  
  1524.     if (paintRect == false) return;
  1525.  
  1526.     int tx, ty, tw, th;
  1527.  
  1528.     tx = x;
  1529.     ty = y;
  1530.     tw = width;
  1531.     th = height;
  1532.     if (tw < 0) {
  1533.         tw = -width;
  1534.         tx = x-tw;
  1535.     }
  1536.     if (th < 0) {
  1537.         th = -height;
  1538.         ty = y-th;
  1539.     }
  1540.     g.setColor (Color.white);
  1541.     g.drawRect (tx, ty, tw, th);
  1542. }
  1543. }
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552. LifeApp.java:
  1553.  
  1554. import java.util.*;
  1555. import java.awt.*;
  1556. import java.awt.event.*;
  1557. import java.awt.image.ImageObserver;
  1558. import java.awt.image.PixelGrabber;
  1559.  
  1560. /*
  1561.  * class that manages a generation
  1562.  */
  1563. class LifeGenerator {
  1564.  
  1565. /*
  1566.  * array containing packed cells
  1567.  * n - number of elements in the CellList array
  1568.  */
  1569. int CellList[], n;
  1570. int a[];
  1571. int b[];
  1572. int c[];
  1573.  
  1574. /*
  1575.  * the current generation number
  1576.  */
  1577. int generations;
  1578.  
  1579. /*
  1580.  * background and foreground colors
  1581.  */
  1582. Color background;
  1583. Color foreground;
  1584.  
  1585. int statusheight;
  1586. int displaywidth;
  1587. int displayheight;
  1588.  
  1589. int originx;
  1590. int originy;
  1591.  
  1592. int maxcells;
  1593.  
  1594. static int countmsk=0x1f;
  1595. static int posmsk=0x7fffffe0;
  1596. static int maxval=0x7fffffff;
  1597.  
  1598. String statusLine;
  1599. String loading;
  1600.  
  1601. int scroll;
  1602.  
  1603. /*
  1604.  * the rules of life
  1605.  */
  1606. static boolean rules[]={
  1607.     false, false,
  1608.     false, false,
  1609.     false, true,
  1610.     true,  true,
  1611.     false, false,
  1612.     false, false,
  1613.     false, false,
  1614.     false, false, 
  1615.     false, false
  1616. };
  1617.  
  1618. /*
  1619.  * constructor initializes variables
  1620.  */
  1621. public LifeGenerator() {
  1622.  
  1623.     n=0;
  1624.     generations=0;
  1625.     maxcells=0;
  1626.     background=Color.white;
  1627.     foreground=Color.black;
  1628.  
  1629.     originx=0;
  1630.     originy=0;
  1631.  
  1632.     loading=null;
  1633.     scroll=10;
  1634.  
  1635.     statusLine=new String("");
  1636. }
  1637.  
  1638. public void loading(String init_loading) {
  1639.  
  1640.     loading=init_loading;
  1641. }
  1642.  
  1643. public void setScroll(int init_scroll) {
  1644.  
  1645.     scroll=init_scroll;
  1646. }
  1647.  
  1648. public void setColors(Color init_background,Color init_foreground) {
  1649.  
  1650.     background=init_background;
  1651.     foreground=init_foreground;
  1652. }
  1653.  
  1654. public void setDisplaySize(int width, int height) {
  1655.  
  1656.     statusheight=35;
  1657.  
  1658.     displaywidth=width;
  1659.     displayheight=height-statusheight; 
  1660. }
  1661.  
  1662. /**
  1663.  * translate the origin
  1664.  * @param dx, dy - offsets to translate
  1665.  */
  1666. public void translate(int dx, int dy) {
  1667.  
  1668.     originx+=dx;
  1669.     originy+=dy;
  1670. }
  1671.  
  1672. public void recenter(int x, int y) {
  1673.  
  1674.     translate(displaywidth/2-x, displayheight/2-y);
  1675. }
  1676.  
  1677. public void approachcenter(int x, int y) {
  1678.  
  1679.     translate((displaywidth/2-x)/scroll,
  1680.         (displayheight/2-y)/scroll);
  1681. }
  1682.  
  1683. public void findPattern() {
  1684.  
  1685.     if (n>0) {
  1686.         int packed=CellList[n/2];
  1687.         int plotx=(((packed>>5)&0x1fff)-(1<<12))*2+originx;
  1688.         int ploty=((packed>>18)-(1<<12))*2+originy;
  1689.         recenter(plotx, ploty);
  1690.     }
  1691. }
  1692.  
  1693. /**
  1694.  * print status message
  1695.  * @param g - destination graphics object
  1696.  */
  1697. public void updateStatusLine(Graphics g) {
  1698.  
  1699.     g.setColor(background);
  1700.     g.drawString(statusLine,0,displayheight+15);
  1701.  
  1702.     if (loading!=null) {
  1703.         statusLine="Loading: " + loading;
  1704.     } else {
  1705.         statusLine="Generations: " + generations + "  Cells: " + n;
  1706.     }
  1707.     g.setColor(foreground);
  1708.     g.drawString(statusLine,0,displayheight+15);
  1709. }
  1710.  
  1711. void resizeIfNeeded(int cellcount) {
  1712.  
  1713.     int tmp[];
  1714.     int i;
  1715.  
  1716.     if (cellcount>maxcells) {
  1717.  
  1718.         int newsize=2*cellcount;
  1719.  
  1720.         tmp=new int[newsize];
  1721.         for (i=0; i<maxcells; i++) tmp[i]=CellList[i];
  1722.         CellList=tmp;
  1723.  
  1724.         tmp=new int[newsize];
  1725.         for (i=0; i<maxcells; i++) tmp[i]=a[i];
  1726.         a=tmp;
  1727.  
  1728.         tmp=new int[newsize];
  1729.         for (i=0; i<maxcells; i++) tmp[i]=b[i];
  1730.         b=tmp;
  1731.  
  1732.         tmp=new int[newsize];
  1733.         for (i=0; i<maxcells; i++) tmp[i]=c[i];
  1734.         c=tmp;
  1735.  
  1736.         maxcells=newsize;
  1737.     }
  1738. }
  1739.  
  1740. static int combineLists(int a[], int na, int b[], int nb,int c[]) {
  1741.  
  1742.     int i,j,nc;
  1743.     i=0; j=0; nc=0;
  1744.     a[na]=maxval;
  1745.     b[nb]=maxval;
  1746.     while (i<na || j<nb) {
  1747.         if ((a[i]^b[j])<=countmsk) {
  1748.             c[nc++]=(a[i++]&countmsk)+b[j++];
  1749.         } else if (a[i]<b[j]) {
  1750.             c[nc++]=a[i++];
  1751.         } else {
  1752.             c[nc++]=b[j++];
  1753.         }
  1754.     }
  1755.     return nc;
  1756. }
  1757.  
  1758. static void extractCenterCells(int list[], int n, int counts[]) {
  1759.  
  1760.     int i=0, j=0; 
  1761.  
  1762.     while (i<n) {
  1763.         if ((list[i]^counts[j])<=countmsk) {
  1764.             counts[j]-;
  1765.             i++;
  1766.             j++;
  1767.         } else j++;
  1768.     }
  1769. }
  1770.  
  1771. static int Cell(int x, int y, int value) {
  1772.  
  1773.     return ((y+(1<<12))<<18) +((x+(1<<12))<<5) + value;
  1774. }
  1775.  
  1776. /**
  1777.  * plot an individual cell
  1778.  * @param packed - a set of packed cells
  1779.  * @param g - destination graphics object
  1780.  */
  1781. void plotCell(int packed, Graphics g) {
  1782.  
  1783.     int plotx=(((packed>>5)&0x1fff)-(1<<12))*2+originx;
  1784.     int ploty=((packed>>18)-(1<<12))*2+originy;
  1785.  
  1786.     if (plotx > 3 && plotx < displaywidth-5 &&
  1787.         ploty > 3 && ploty < displayheight-5 ) {
  1788.         g.fillRect(plotx, ploty, 2, 2);
  1789.     }
  1790. }
  1791.  
  1792. /**
  1793.  * paint the current generation
  1794.  * @param g - destination graphics object
  1795.  */
  1796. public void paintAll(Graphics g) {
  1797.  
  1798.     g.clearRect(0,0,displaywidth, displayheight+statusheight);
  1799.     g.drawRect(0,0,displaywidth-1, displayheight-1);
  1800.  
  1801.     g.setColor(foreground);
  1802.     for (int i=0; i<n; i++) {
  1803.         plotCell(CellList[i],g);
  1804.     }
  1805.     updateStatusLine(g);
  1806. }
  1807.  
  1808. int nextGen(int counts[], int ncounts, int list[], Graphics g) {
  1809.  
  1810.     int nlist=0;
  1811.     for (int i=0; i<ncounts; i++) {
  1812.         int count=counts[i]&countmsk;
  1813.         if (rules[count]) {
  1814.             list[nlist++]=(counts[i]&posmsk)+2;
  1815.             if ((count&1)==0) {
  1816.                 g.setColor(foreground);
  1817.                 plotCell(counts[i],g);
  1818.             }
  1819.         } else {
  1820.             if ((count&1)==1) {
  1821.                 g.setColor(background);
  1822.                 plotCell(counts[i],g); 
  1823.             }
  1824.         }
  1825.     }
  1826.     return nlist;
  1827. }
  1828.  
  1829. public void generate(Graphics g) {
  1830.  
  1831.     int na, nb, nc; 
  1832.  
  1833.     for (na=0; na<n; na++) a[na]=CellList[na]-(1<<18);
  1834.     resizeIfNeeded(n+na);
  1835.     nb=combineLists(CellList,n,a,na,b);
  1836.  
  1837.     for (na=0; na<n; na++) a[na]=CellList[na]+(1<<18);
  1838.     resizeIfNeeded(na+nb);
  1839.     nc=combineLists(a,na,b,nb,c);
  1840.  
  1841.     for (na=0; na<nc; na++) a[na]=c[na]-(1<<5);
  1842.     resizeIfNeeded(na+nc);
  1843.     nb=combineLists(a,na,c,nc,b);
  1844.  
  1845.     for (na=0; na<nc; na++) a[na]=c[na]+(1<<5);
  1846.     resizeIfNeeded(na+nb);
  1847.     nc=combineLists(a,na,b,nb,c);
  1848.  
  1849.     extractCenterCells(CellList, n, c);
  1850.  
  1851.     n=nextGen(c, nc, CellList, g);
  1852.  
  1853.     generations++;
  1854. }
  1855.  
  1856. /**
  1857.  * load a new initial image
  1858.  * @param img - the image to load
  1859.  * @param imgobs - the image observer
  1860.  */
  1861. public boolean loadLifePattern(Image img, ImageObserver imgobs) {
  1862.  
  1863.     int w=img.getWidth(imgobs);
  1864.     int h=img.getHeight(imgobs);
  1865.  
  1866.     if (w<0 || h<0) return false;
  1867.  
  1868.     originx= (displaywidth-w*2)/2;
  1869.     originy= (displayheight-h*2)/2;
  1870.  
  1871.     int[] pixels = new int[w * h];
  1872.  
  1873.     PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pixels, 0, w);
  1874.  
  1875.     try {
  1876.         pg.grabPixels();
  1877.     } catch (InterruptedException e) {
  1878.         return false;
  1879.     }
  1880.  
  1881.     int i,j;
  1882.  
  1883.     int pix0= pixels[0];
  1884.     int pix1= -1;
  1885.     int count1= 0;
  1886.  
  1887.     for (i=0; i<h; i++) {
  1888.         for (j=0; j<w; j++) {
  1889.             if (pixels[i*w+j]!=pix0) {
  1890.                 pix1= pixels[i*w+j]; 
  1891.                 count1++;
  1892.             }
  1893.         }
  1894.     }
  1895.  
  1896.    /* figure out which pixel color denotes a live cell */
  1897.  
  1898.     if (pix0==0xffffff) {}
  1899.     else if (pix1==0xffffff || count1 > w*h-count1) {
  1900.         pix1=pix0;
  1901.         count1=w*h-count1; 
  1902.     }
  1903.  
  1904.     resizeIfNeeded(count1);
  1905.  
  1906.     n=0;
  1907.     for (i=0; i<h; i++) {
  1908.         for (j=0; j<w; j++) {
  1909.             if (pixels[i*w+j]==pix1) {
  1910.                 CellList[n++]=Cell(j,i,2);
  1911.             }
  1912.         }
  1913.     }
  1914.  
  1915.     return true;
  1916. }
  1917. }
  1918.  
  1919. /*
  1920.  * the applet class
  1921.  */
  1922. public class LifeApp extends java.applet.Applet implements MouseListener,
  1923.                     ActionListener, Runnable {
  1924.  
  1925. LifeGenerator LifeList;
  1926.  
  1927. /*
  1928.  * the thread controlling generations
  1929.  */
  1930. Thread killme=null;
  1931. int speed=50;
  1932. boolean neverPainted=true;
  1933. int count=0;
  1934.  
  1935. /*
  1936.  * the image name text field
  1937.  */
  1938. TextField patfield;
  1939. Button pausebutton;
  1940. Button stepbutton;
  1941. Button recenterbutton;
  1942. Button loadbutton;
  1943. boolean generating=false;
  1944. int stepsleft=0;
  1945. int scrollfraction=5;
  1946.  
  1947. /*
  1948.  * called when applet is loaded
  1949.  * create user interface and parse applet parameters
  1950.  */
  1951. public void init() {
  1952.  
  1953.     setLayout(new FlowLayout(FlowLayout.RIGHT, 0, getSize().height-30));
  1954.     add(pausebutton=new Button("Start"));
  1955.     add(stepbutton = new Button("Step"));
  1956.     add(recenterbutton = new Button("Recenter"));
  1957.     add(loadbutton = new Button("Load:"));
  1958.  
  1959.     pausebutton.addActionListener(this);
  1960.     stepbutton.addActionListener(this);
  1961.     recenterbutton.addActionListener(this);
  1962.     loadbutton.addActionListener(this);
  1963.  
  1964.     addMouseListener(this);
  1965.  
  1966.     String patname=getParameter("pattern");
  1967.     if (patname==null) patname="gun30";
  1968.  
  1969.     if (getParameter("started")!=null) {
  1970.         pausebutton.setLabel("Stop");
  1971.         generating=true; 
  1972.     }
  1973.  
  1974.     String pstring;
  1975.  
  1976.     if ((pstring=getParameter("speed"))!=null) {
  1977.         speed=Integer.valueOf(pstring).intValue();
  1978.     }
  1979.  
  1980.     if ((pstring=getParameter("scrollfraction"))!=null) {
  1981.         scrollfraction=Integer.valueOf(pstring).intValue();
  1982.     }
  1983.  
  1984.     add(patfield=new TextField(patname,8));
  1985.  
  1986.     LifeList=null;
  1987. }
  1988.  
  1989. /*
  1990.  * called when applet is started
  1991.  * start the life thread
  1992.  */
  1993. public void start() {
  1994.  
  1995.     if (killme==null) {
  1996.         killme=new Thread(this);
  1997.         killme.start();
  1998.     }
  1999. }
  2000.  
  2001. /*
  2002.  * called when the applet is stopped
  2003.  * stop the life thread
  2004.  */
  2005. public void stop() {
  2006.  
  2007.  
  2008.     killme=null;
  2009. }
  2010.  
  2011.  
  2012. //********************************************************
  2013. public void mouseClicked(MouseEvent e){}
  2014. public void mouseEntered(MouseEvent e){}
  2015. public void mouseExited(MouseEvent e){}
  2016.  
  2017. public void mouseReleased(MouseEvent e)
  2018. {
  2019. }
  2020.  
  2021. public void mousePressed(MouseEvent e)
  2022. {
  2023.     int x =e.getX();
  2024.     int y =e.getY();
  2025.  
  2026.     LifeList.approachcenter(x,y);
  2027.     LifeList.paintAll(getGraphics());
  2028. }
  2029.  
  2030. /**
  2031.  * reorder the images, depending on which button is clicked
  2032.  * @param evt - event object
  2033.  * @param arg - target object
  2034.  */
  2035. public void actionPerformed(ActionEvent evt)
  2036. {
  2037.     boolean acted=true;
  2038.     boolean damage=true;
  2039.  
  2040.     Object object1 = evt.getSource();
  2041.  
  2042.     if (object1 == pausebutton)
  2043.     {
  2044.         String label= pausebutton.getLabel();
  2045.         if (label == "Stop")
  2046.         {
  2047.             pausebutton.setLabel("Start");
  2048.             generating=false;
  2049.         } else if (label == "Start")
  2050.         {
  2051.             pausebutton.setLabel("Stop");
  2052.             generating=true;
  2053.         }
  2054.     }
  2055.  
  2056.     if (object1 == stepbutton)
  2057.     {
  2058.         stepsleft=1;
  2059.         if (generating)
  2060.         {
  2061.             pausebutton.setLabel("Start");
  2062.             generating=false;
  2063.         }
  2064.     }
  2065.     if (object1 == recenterbutton)
  2066.     {
  2067.         LifeList.findPattern();
  2068.     }
  2069.     if (object1 == loadbutton)
  2070.     {
  2071.         stop();
  2072.         LifeList=null;
  2073.         start();
  2074.     }
  2075.     if (acted && damage) LifeList.paintAll(getGraphics());
  2076.  
  2077. }
  2078.  
  2079.  
  2080. //***********************************************************
  2081.  
  2082.  
  2083. /**
  2084.  * add .gif to the filename
  2085.  * @param patname - base filename
  2086.  */
  2087. static String makeGifName(String patname) {
  2088.  
  2089.     int i=patname.indexOf(".");
  2090.     String base=(i<0)?patname:patname.substring(0,i);
  2091.     return base.concat(".gif");
  2092. }
  2093.  
  2094. /**
  2095.  * load new image file
  2096.  * @parame patname - name of image file
  2097.  */
  2098. void loadNew(String patname) {
  2099.  
  2100.     Image img=getImage(getCodeBase(), makeGifName(patname));
  2101.     LifeList.loading(patname);
  2102.     LifeList.paintAll(getGraphics());
  2103.  
  2104.     while(killme!=null && !LifeList.loadLifePattern(img,
  2105. σthis)) {
  2106.         try {
  2107.             Thread.sleep(200);
  2108.         } catch (InterruptedException e) {}
  2109.     }
  2110.  
  2111.     LifeList.loading(null);
  2112.     LifeList.paintAll(getGraphics());
  2113. }
  2114.  
  2115. /*
  2116.  * life thread
  2117.  * causes new generations to be created
  2118.  */
  2119. public void run() {
  2120.  
  2121.     Graphics g=getGraphics();
  2122.  
  2123.     if (LifeList==null) {
  2124.         LifeList = new LifeGenerator();
  2125.         LifeList.setColors(getBackground(), Color.black); 
  2126.         LifeList.setScroll(scrollfraction);
  2127.         LifeList.setDisplaySize(getSize().width, getSize().height);
  2128.         loadNew(patfield.getText());
  2129.     }
  2130.  
  2131.     while (killme != null) {
  2132.         try {
  2133.             Thread.sleep(speed);
  2134.         } catch (InterruptedException e) {}
  2135.         repaint();
  2136.     }
  2137.     killme=null;
  2138. }
  2139.  
  2140. /**
  2141.  * paint the current generation
  2142.  * @param g - destination graphics object
  2143.  */
  2144. public void paint(Graphics g) {
  2145.  
  2146.     LifeList.paintAll(g);
  2147. }
  2148.  
  2149. /**
  2150.  * override update to avoid erase flicker
  2151.  * @param g - destination graphics object
  2152.  */
  2153. public void update(Graphics g) {
  2154.  
  2155.     if (generating || stepsleft- > 0) {
  2156.         LifeList.generate(g);
  2157.         LifeList.updateStatusLine(g);
  2158.     }
  2159. }
  2160. }
  2161.  
  2162.  
  2163.  
  2164.  
  2165.  
  2166.  
  2167.  
  2168.  
  2169.  
  2170.