/******************************************************************************* * Copyright (c) 2012 xored software, Inc. All rights reserved. This program and the accompanying * materials are made available under the terms of the Eclipse Public License v1.0 which accompanies * this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: * xored software, Inc. - initial API and implementation (Yuri Strot) ******************************************************************************/ package com.xored.glance.internal.ui.panels; import com.xored.glance.internal.ui.GlancePlugin; import com.xored.glance.ui.utils.UIUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.ImageLoader; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import java.net.URL; public abstract class ImageAnimation extends Thread { private final ImageLoader loader = new ImageLoader(); private ImageData[] imageDataArray; private final Color bg; public ImageAnimation(URL url, Color bg) throws CoreException { setDaemon(true); this.bg = bg; try { imageDataArray = loader.load(url.openStream()); } catch (Exception e) { throw new CoreException(GlancePlugin.createStatus( "Can't read image '" + url.toString() + "'", e)); } if (imageDataArray == null || imageDataArray.length <= 1) { throw new CoreException(GlancePlugin.createStatus("Image '" + url.toString() + "' is not an animated image")); } } @Override public void run() { Display display = PlatformUI.getWorkbench().getDisplay(); /* * Create an off-screen image to draw on, and fill it with the shell background. */ final Image offScreenImage = new Image( display, loader.logicalScreenWidth, loader.logicalScreenHeight); GC offScreenImageGC = new GC(offScreenImage); offScreenImageGC.setBackground(bg); offScreenImageGC.fillRectangle(0, 0, loader.logicalScreenWidth, loader.logicalScreenHeight); Image image = null; try { /* Create the first image and draw it on the off-screen image. */ int imageDataIndex = 0; ImageData imageData = imageDataArray[imageDataIndex]; image = new Image(display, imageData); offScreenImageGC.drawImage( image, 0, 0, imageData.width, imageData.height, imageData.x, imageData.y, imageData.width, imageData.height); /* * Now loop through the images, creating and drawing each one on the off-screen image before * drawing it on the shell. */ int repeatCount = loader.repeatCount; while ((loader.repeatCount == 0 || repeatCount > 0) && !isTerminated()) { switch (imageData.disposalMethod) { case SWT.DM_FILL_BACKGROUND: /* Fill with the background color before drawing. */ offScreenImageGC.setBackground(bg); offScreenImageGC.fillRectangle( imageData.x, imageData.y, imageData.width, imageData.height); break; case SWT.DM_FILL_PREVIOUS: /* Restore the previous image before drawing. */ offScreenImageGC.drawImage( image, 0, 0, imageData.width, imageData.height, imageData.x, imageData.y, imageData.width, imageData.height); break; } imageDataIndex = (imageDataIndex + 1) % imageDataArray.length; imageData = imageDataArray[imageDataIndex]; image.dispose(); image = new Image(display, imageData); offScreenImageGC.drawImage( image, 0, 0, imageData.width, imageData.height, imageData.x, imageData.y, imageData.width, imageData.height); final Image newImage = image; UIUtils.syncExec(display, new Runnable() { @Override public void run() { updateImage(newImage); } }); /* * Sleep for the specified delay time (adding commonly-used slow-down fudge factors). */ try { int ms = imageData.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.length - 1) { repeatCount--; } } } catch (SWTException ex) { GlancePlugin.log("There was an error animating the GIF", ex); } finally { if (offScreenImage != null && !offScreenImage.isDisposed()) { offScreenImage.dispose(); } if (offScreenImageGC != null && !offScreenImageGC.isDisposed()) { offScreenImageGC.dispose(); } if (image != null && !image.isDisposed()) { image.dispose(); } } } protected abstract boolean isTerminated(); protected abstract void updateImage(Image image); }