All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.schlichtherle.swing.AnimatedImageIcon Maven / Gradle / Ivy

Go to download

Provides an internationalized wizard dialog used to install, verify and uninstall license keys.

The newest version!
/*
 * Copyright (C) 2005-2015 Schlichtherle IT Services.
 * All rights reserved. Use is subject to license terms.
 */
package de.schlichtherle.swing;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.ImageObserver;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.Timer;

/**
 * @author Christian Schlichtherle
 */
public class AnimatedImageIcon extends ImageIcon {

    private static final String CLASS_NAME
            = "de/schlichtherle/swing/AnimatedImageIcon".replace('/', '.'); // beware of code obfuscation!
    private static final Logger logger = Logger.getLogger(CLASS_NAME);

    private static final Level CALLING = Level.FINE;
    private static final Level FAILED = Level.WARNING;
    private static final Level RETURNED = Level.FINER;
    private static final long serialVersionUID = 1L;

    private int delay;
    private Image[] frames;

    private final Timer timer = new Timer(0, new Animator());

    /**
     * Constructs a new {@code AnimatedImageIcon}.
     */
    public AnimatedImageIcon() {
    }

    /**
     * Constructs a new {@code AnimatedImageIcon}.
     *
     * @param rate The animation rate in frames per second.
     * @param frames The array of image frames for this animation.
     */
    public AnimatedImageIcon(int rate, Image[] frames) {
        super(frames[0]);
        setRateImpl(rate);
        setFramesImpl(frames);
    }

    /**
     * Returns the effective animation rate in frames per second.
     * This may slightly differ from the value provided to the constructor
     * or {@link #setRate} due to rounding flaws.
     */
    public int getRate() {
        return 1000 / delay;
    }

    /**
     * Set the rate for this animation.
     *
     * @param rate The animation rate in frames per second.
     */
    public void setRate(int rate) {
        setRateImpl(rate);
    }

    private void setRateImpl(int rate) {
        delay = 1000 / rate;
        timer.setDelay(delay);
    }

    /**
     * Returns a clone of the array which holds the image frames for this animation.
     */
    public Image[] getFrames() {
        return (Image[]) frames.clone();
    }

    /**
     * Sets the image frames for this animation.
     *
     * @param frames The array of image frames for this animation.
     */
    public void setFrames(Image[] frames) {
        setFramesImpl(frames);
    }

    private void setFramesImpl(final Image[] frames) {
        this.frames = frames;
        /*for (int i = 0, l = frames.length; i < l; i++)
            loadImage(frames[i]);*/
        setImage(frames[0]);
    }

    public void paintIcon(
            final Component c, final Graphics g,
            final int x, final int y) {
        logger.log(CALLING, System.identityHashCode(this) + "(c=" + System.identityHashCode(c) + ", g=" + System.identityHashCode(g) + ", x=" + x + ", y=" + y + ")");
        try {
            // Get frame image to paint.
            // Check that it's not null, which may happen if this object
            // was initialized with the nullary constructor.
            final Image image = getImage();
            if (image == null)
                return; // may happen when initialized from a nullary constructor

            // Pass null as the image observer in order to suppress any
            // image updates from the frame image.
            // This is a safe optimization because setImage(Image) has already
            // ensured that the frame image is loaded and may help in case
            // the frame image is actually an animated GIF
            // (which you shouldn't use with this class anyway).
            g.drawImage(image, x, y, null);

            // Rememember component for animation updates and start timer,
            // if it's not already started.
            setImageObserver(c);
            timer.start();

            logger.log(RETURNED, System.identityHashCode(this) + "(...)");
        } catch (Throwable throwable) {
            logger.log(FAILED, System.identityHashCode(this) + "(...)");
            rethrow(throwable);
        }
    }
    
    private static void rethrow(Throwable throwable) {
        if (throwable instanceof RuntimeException)
            throw (RuntimeException) throwable;
        else if (throwable instanceof Error)
            throw (Error) throwable;
        else
            throw new UndeclaredThrowableException(throwable);
    }

    private class Animator implements ActionListener {
        private int current;

        public void actionPerformed(final ActionEvent evt) {
            final ImageObserver observer = getImageObserver();
            current = (current + 1) % frames.length;
            boolean ret = imageUpdate(observer, frames[current]);
            if (!ret) {
                current = 0;
                ret = imageUpdate(observer, frames[current]);
                timer.stop();
                setImageObserver(null);
                assert !ret : "The image observer should not be interested in updates anymore!";
            }
        }
        
        private boolean imageUpdate(final ImageObserver observer, final Image image) {
            logger.log(CALLING, System.identityHashCode(this) + "(observer=" + System.identityHashCode(observer) + ", image=" + image + ")");
            try {
                setImage(image);
                final int width = image.getWidth(observer);
                assert width == getIconWidth();
                final int height = image.getHeight(observer);
                assert height == getIconHeight();
                final boolean ret = observer.imageUpdate(
                        image, ImageObserver.FRAMEBITS, 0, 0, width, height);

                logger.log(RETURNED, System.identityHashCode(this) + "(...)=" + ret);
                return ret;
            } catch (Throwable throwable) {
                logger.log(FAILED, System.identityHashCode(this) + "(...)");
                rethrow(throwable);
                return false; // unreachable
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy