/*

Java class to implement a double buffered applet

      by Ken Perlin @ NYU, 1998.

You have my permission to use freely, as long as you keep the attribution. - Ken Perlin

Note: this BufferedApplet.html file also works as a legal BufferedApplet.java file. If you save the source under that name, you can just run javac on it.

*/
import java.awt.*;

public abstract class BufferedApplet extends java.applet.Applet implements Runnable
{
   public boolean damage = true; //Flag advising app. program to rerender
   public boolean animating = false;
   public abstract void render(Graphics g); //App. defines render method

   Image bufferImage = null;            //Image for the double buffer
   private Graphics bufferGraphics = null;  //Canvas for double buffer
   private Thread t;                    //Background thread for rendering
   private Rectangle r = new Rectangle(0,0,0,0); //Double buffer bounds

   //Extend the start,stop,run methods to implement double buffering.

   public void start() { if (t == null) { t = new Thread(this); t.start(); } }
   public void stop()  { if (t != null) { t.stop(); t = null; } }
   public void run() {
      try {
         while (true) { repaint(); t.sleep(30); } //Repaint each 30 msecs
      }
      catch(InterruptedException e){}; //Catch interruptions of sleep().
   }

   //Update(Graphics) is called by repaint() - the system adds canvas.
   //Extend update method to create a double buffer whenever necessary.

   public void update(Graphics g) {
      if (r.width != bounds().width || r.height != bounds().height) {
         bufferImage    = createImage(bounds().width, bounds().height);
         bufferGraphics = bufferImage.getGraphics(); //Applet size change
         r = bounds();                               //Make double buffer
         damage = true;                              //Tell application.
      }
      if (damage)
         render(bufferGraphics); //Ask application to render to buffer,
      damage = animating;        //
      paint(g);                  //paste buffered image onto the applet.
   }

   //Separate paint method for application to extend if needed.

   public void paint(Graphics g) {
      if (bufferImage != null)              //
         g.drawImage(bufferImage,0,0,this); //Paste result of render().
   }
}