org.eclipse.swt.snippets.Snippet288.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.swt.snippets.Snippet288.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.snippets;

/*
 * Create a ToolBar containing animated GIFs
 *
 * For a list of all SWT example snippets see
 * http://www.eclipse.org/swt/snippets/
 */
import java.io.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

public class Snippet288 {

    static Display display;
    static Shell shell;
    static GC shellGC;
    static Color shellBackground;
    static ImageLoader[] loader;
    static ImageData[][] imageDataArray;
    static Thread animateThread[];
    static Image[][] image;
    private static ToolItem item[];
    static final boolean useGIFBackground = false;

    public static void main(String[] args) {
        display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Snippet 288");
        shellBackground = shell.getBackground();
        FileDialog dialog = new FileDialog(shell, SWT.OPEN | SWT.MULTI);
        dialog.setText("Select Multiple Animated GIFs");
        dialog.setFilterExtensions(new String[] { "*.gif" });
        String filename = dialog.open();
        String filenames[] = dialog.getFileNames();
        int numToolBarItems = filenames.length;
        if (numToolBarItems > 0) {
            try {
                loadAllImages(new File(filename).getParent(), filenames);
            } catch (SWTException e) {
                System.err.println("There was an error loading an image.");
                e.printStackTrace();
            }
            ToolBar toolBar = new ToolBar(shell, SWT.FLAT | SWT.BORDER | SWT.WRAP);
            item = new ToolItem[numToolBarItems];
            for (int i = 0; i < numToolBarItems; i++) {
                item[i] = new ToolItem(toolBar, SWT.PUSH);
                item[i].setImage(image[i][0]);
            }
            toolBar.pack();
            shell.open();

            startAnimationThreads();

            while (!shell.isDisposed()) {
                if (!display.readAndDispatch())
                    display.sleep();
            }

            for (int i = 0; i < numToolBarItems; i++) {
                for (int j = 0; j < image[i].length; j++) {
                    image[i][j].dispose();
                }
            }
        }
        display.dispose();
    }

    private static void loadAllImages(String directory, String[] filenames) throws SWTException {
        int numItems = filenames.length;
        loader = new ImageLoader[numItems];
        imageDataArray = new ImageData[numItems][];
        image = new Image[numItems][];
        for (int i = 0; i < numItems; i++) {
            loader[i] = new ImageLoader();
            int fullWidth = loader[i].logicalScreenWidth;
            int fullHeight = loader[i].logicalScreenHeight;
            imageDataArray[i] = loader[i].load(directory + File.separator + filenames[i]);
            int numFramesOfAnimation = imageDataArray[i].length;
            image[i] = new Image[numFramesOfAnimation];
            for (int j = 0; j < numFramesOfAnimation; j++) {
                if (j == 0) {
                    //for the first frame of animation, just draw the first frame
                    image[i][j] = new Image(display, imageDataArray[i][j]);
                    fullWidth = imageDataArray[i][j].width;
                    fullHeight = imageDataArray[i][j].height;
                } else {
                    //after the first frame of animation, draw the background or previous frame first, then the new image data
                    image[i][j] = new Image(display, fullWidth, fullHeight);
                    GC gc = new GC(image[i][j]);
                    gc.setBackground(shellBackground);
                    gc.fillRectangle(0, 0, fullWidth, fullHeight);
                    ImageData imageData = imageDataArray[i][j];
                    switch (imageData.disposalMethod) {
                    case SWT.DM_FILL_BACKGROUND:
                        /* Fill with the background color before drawing. */
                        Color bgColor = null;
                        if (useGIFBackground && loader[i].backgroundPixel != -1) {
                            bgColor = new Color(display, imageData.palette.getRGB(loader[i].backgroundPixel));
                        }
                        gc.setBackground(bgColor != null ? bgColor : shellBackground);
                        gc.fillRectangle(imageData.x, imageData.y, imageData.width, imageData.height);
                        if (bgColor != null)
                            bgColor.dispose();
                        break;
                    default:
                        /* Restore the previous image before drawing. */
                        gc.drawImage(image[i][j - 1], 0, 0, fullWidth, fullHeight, 0, 0, fullWidth, fullHeight);
                        break;
                    }
                    Image newFrame = new Image(display, imageData);
                    gc.drawImage(newFrame, 0, 0, imageData.width, imageData.height, imageData.x, imageData.y,
                            imageData.width, imageData.height);
                    newFrame.dispose();
                    gc.dispose();
                }
            }
        }
    }

    private static void startAnimationThreads() {
        animateThread = new Thread[image.length];
        for (int ii = 0; ii < image.length; ii++) {
            final int i = ii;
            animateThread[i] = new Thread("Animation " + i) {
                int imageDataIndex = 0;

                @Override
                public void run() {
                    try {
                        int repeatCount = loader[i].repeatCount;
                        while (loader[i].repeatCount == 0 || repeatCount > 0) {
                            imageDataIndex = (imageDataIndex + 1) % imageDataArray[i].length;
                            if (!display.isDisposed()) {
                                display.asyncExec(() -> {
                                    if (!item[i].isDisposed())
                                        item[i].setImage(image[i][imageDataIndex]);
                                });
                            } else {
                                break;
                            }

                            /* Sleep for the specified delay time (adding commonly-used slow-down fudge factors). */
                            try {
                                int ms = imageDataArray[i][imageDataIndex].delayTime * 10;
                                if (ms < 20)
                                    ms += 30;
                                if (ms < 30)
                                    ms += 10;
                                Thread.sleep(ms);
                            } catch (InterruptedException e) {
                            }

                            /* If we have just drawn the last image, decrement the repeat count and start again. */
                            if (imageDataIndex == imageDataArray[i].length - 1)
                                repeatCount--;
                        }
                    } catch (SWTException ex) {
                        System.out.println("There was an error animating the GIF");
                        ex.printStackTrace();
                    }
                }
            };
            animateThread[i].setDaemon(true);
            animateThread[i].start();
        }
    }
}