import java.awt.image.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class VolatileImageTest4 extends JPanel {

    private MediaTracker tracker;

    private Image image;
    private int width;
    private int height;
    private boolean volatileFlag = true;

    private java.util.List sprites;
    private static final int SPRITE_NUMBER = 8;
    private static final String SPRITE_FILENAME = "javacup";
    private static final String SPRITE_FILESUFFIX = "gif";
    private int index;

    private int x;

    public VolatileImageTest4(){
        tracker = new MediaTracker(this);

        Toolkit toolkit = Toolkit.getDefaultToolkit();
        sprites = new java.util.ArrayList(8);
        for(int i = 0 ; i < SPRITE_NUMBER ; i++){
            Image tempImage = toolkit.getImage(SPRITE_FILENAME + i + "." + SPRITE_FILESUFFIX);
            sprites.add(tempImage);
            tracker.addImage(tempImage, 0);
        }
    }

    private void initVolatileImage(){
        if (image == null || width != getWidth() || height != getHeight()) {
            width = getWidth();
            height = getHeight();
            if(volatileFlag){
                image = createVolatileImage(width, height);
            }else{
                image = createImage(width, height);
            }
        }
    }

    private void validateVolatileImage() {
        GraphicsConfiguration gc = this.getGraphicsConfiguration();

        if (volatileFlag && ((VolatileImage)image).validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) {
            image = createVolatileImage(width, height);
        }
    }

    private void move(){
        x += 10;
        if(x > width){
            x = - ((Image)sprites.get(0)).getWidth(this);
        }
    }

    public void paint(Graphics g){
        initVolatileImage();
        if(tracker.statusAll(false) != MediaTracker.COMPLETE){
            return;
        }

        try{
            do {
                validateVolatileImage();
                Graphics gImage = image.getGraphics();
                gImage.setColor(Color.yellow);
                gImage.fillRect(0, 0, width, height);
                gImage.drawImage((Image)sprites.get(index), x, 0, this);
                gImage.dispose();
                g.drawImage(image, 0, 0, this);
            } while (volatileFlag && ((VolatileImage)image).contentsLost());
        }catch(NullPointerException ex){}
    }

    public void start(){
        try{
            tracker.waitForID(0);
        }catch(InterruptedException e){
            return;
        }
        
        JOptionPane.showMessageDialog(null, "VolatileImage");
        long volTime = startAnimation();
        image = null;
        volatileFlag = false;
        JOptionPane.showMessageDialog(null, "Non-VolatileImage");
        long nonVolTime = startAnimation();
        JOptionPane.showMessageDialog(null, 
                      "Volatime Image: " + volTime + "ms\n"
                      + "Non-Volatime Image: " + nonVolTime + "ms");
    }

    private long startAnimation(){
        index = 0;
        long startTime = System.currentTimeMillis();
        for(int i = 0 ; i < 500 ; i++){
            move();
            Graphics g = getGraphics();
            update(g);
            
            index++;
            if(index >= SPRITE_NUMBER){
                index = 0;
            }
        }
        long endTime = System.currentTimeMillis();
        return (endTime - startTime);
    }

    public static void main(String[] args){

        JFrame frame = new JFrame("VolatileImageTest4");
        frame.setBounds(100, 100, 800, 400);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });

        VolatileImageTest4 test = new VolatileImageTest4();

        frame.getContentPane().add(test);
        frame.setVisible(true);

        test.start();
        System.exit(0);
    }
}

