1 #!/usr/bin/env dub 2 /+ 3 dub.sdl: 4 name "snippet288" 5 dependency "dwt" path="../../../../../../" 6 libs \ 7 "atk-1.0" \ 8 "cairo" \ 9 "dl" \ 10 "fontconfig" \ 11 "gdk-x11-2.0" \ 12 "gdk_pixbuf-2.0" \ 13 "glib-2.0" \ 14 "gmodule-2.0" \ 15 "gnomeui-2" \ 16 "gnomevfs-2" \ 17 "gobject-2.0" \ 18 "gthread-2.0" \ 19 "gtk-x11-2.0" \ 20 "pango-1.0" \ 21 "pangocairo-1.0" \ 22 "X11" \ 23 "Xcomposite" \ 24 "Xcursor" \ 25 "Xdamage" \ 26 "Xext" \ 27 "Xfixes" \ 28 "Xi" \ 29 "Xinerama" \ 30 "Xrandr" \ 31 "Xrender" \ 32 "Xtst" \ 33 platform="linux" 34 +/ 35 36 /******************************************************************************* 37 * Copyright (c) 2008 IBM Corporation and others. 38 * All rights reserved. This program and the accompanying materials 39 * are made available under the terms of the Eclipse Public License v1.0 40 * which accompanies this distribution, and is available at 41 * http://www.eclipse.org/legal/epl-v10.html 42 * 43 * Contributors: 44 * IBM Corporation - initial API and implementation 45 *******************************************************************************/ 46 module org.eclipse.swt.snippets.Snippet288; 47 48 /* 49 * Create a ToolBar containing animated GIFs 50 * 51 * For a list of all SWT example snippets see 52 * http://www.eclipse.org/swt/snippets/ 53 */ 54 import org.eclipse.swt.SWT; 55 import org.eclipse.swt.SWTException; 56 import org.eclipse.swt.graphics.GC; 57 import org.eclipse.swt.graphics.Color; 58 import org.eclipse.swt.graphics.Image; 59 import org.eclipse.swt.graphics.ImageLoader; 60 import org.eclipse.swt.graphics.ImageData; 61 import org.eclipse.swt.widgets.Display; 62 import org.eclipse.swt.widgets.Shell; 63 import org.eclipse.swt.widgets.ToolBar; 64 import org.eclipse.swt.widgets.ToolItem; 65 import org.eclipse.swt.widgets.FileDialog; 66 67 import java.lang.all; 68 69 version(Tango){ 70 import tango.io.FilePath; 71 import tango.io.model.IFile; 72 //import tango.core.Thread; 73 import tango.io.Stdout; 74 import tango.util.Convert; 75 import tango.core.Exception; 76 } else { // Phobos 77 import std.path; 78 import std.stdio; 79 import std.conv; 80 import core.exception; 81 import core.thread : ThreadException; 82 struct FileConst { 83 static const PathSeparatorChar = dirSeparator; 84 } 85 } 86 87 mixin(gshared!(" 88 Display display; 89 Shell shell; 90 GC shellGC; 91 Color shellBackground; 92 ImageLoader[] loader; 93 ImageData[][] imageDataArray; 94 Thread[] animateThread; 95 Image[][] image; 96 ToolItem[] item; 97 ")); 98 const bool useGIFBackground = false; 99 100 void main () { 101 display = new Display(); 102 Shell shell = new Shell (display); 103 shellBackground = shell.getBackground(); 104 FileDialog dialog = new FileDialog(shell, SWT.OPEN | SWT.MULTI); 105 dialog.setText("Select Multiple Animated GIFs"); 106 dialog.setFilterExtensions(["*.gif"]); 107 String filename = dialog.open(); 108 String[] filenames = dialog.getFileNames(); 109 int numToolBarItems = cast(int)filenames.length; 110 if (numToolBarItems > 0) { 111 version(Tango){ 112 try { 113 loadAllImages((new FilePath(filename)).parent, filenames); 114 } catch (SWTException e) { 115 Stdout.print("There was an error loading an image.").newline; 116 e.printStackTrace(); 117 } 118 } else { // Phobos 119 try { 120 loadAllImages(filename.dirName, filenames); 121 } catch (SWTException e) { 122 writeln("There was an error loading an image."); 123 e.printStackTrace(); 124 } 125 } 126 ToolBar toolBar = new ToolBar (shell, SWT.FLAT | SWT.BORDER | SWT.WRAP); 127 item = new ToolItem[numToolBarItems]; 128 for (int i = 0; i < numToolBarItems; i++) { 129 item[i] = new ToolItem (toolBar, SWT.PUSH); 130 item[i].setImage(image[i][0]); 131 } 132 toolBar.pack (); 133 shell.open (); 134 135 startAnimationThreads(); 136 137 while (!shell.isDisposed()) { 138 if (!display.readAndDispatch ()) display.sleep (); 139 } 140 141 for (int i = 0; i < numToolBarItems; i++) { 142 for (int j = 0; j < image[i].length; j++) { 143 image[i][j].dispose(); 144 } 145 } 146 display.dispose (); 147 } 148 Thread.joinAll(); 149 } 150 151 void loadAllImages(String directory, String[] filenames) { 152 int numItems = cast(int)filenames.length; 153 loader.length = numItems; 154 imageDataArray.length = numItems; 155 image.length = numItems; 156 for (int i = 0; i < numItems; i++) { 157 loader[i] = new ImageLoader(); 158 int fullWidth = loader[i].logicalScreenWidth; 159 int fullHeight = loader[i].logicalScreenHeight; 160 imageDataArray[i] = loader[i].load(directory ~ FileConst.PathSeparatorChar ~ filenames[i]); 161 int numFramesOfAnimation = cast(int)imageDataArray[i].length; 162 image[i] = new Image[numFramesOfAnimation]; 163 for (int j = 0; j < numFramesOfAnimation; j++) { 164 if (j == 0) { 165 //for the first frame of animation, just draw the first frame 166 image[i][j] = new Image(display, imageDataArray[i][j]); 167 fullWidth = imageDataArray[i][j].width; 168 fullHeight = imageDataArray[i][j].height; 169 } 170 else { 171 //after the first frame of animation, draw the background or previous frame first, then the new image data 172 image[i][j] = new Image(display, fullWidth, fullHeight); 173 GC gc = new GC(image[i][j]); 174 gc.setBackground(shellBackground); 175 gc.fillRectangle(0, 0, fullWidth, fullHeight); 176 ImageData imageData = imageDataArray[i][j]; 177 switch (imageData.disposalMethod) { 178 case SWT.DM_FILL_BACKGROUND: 179 /* Fill with the background color before drawing. */ 180 Color bgColor = null; 181 if (useGIFBackground && loader[i].backgroundPixel != -1) { 182 bgColor = new Color(display, imageData.palette.getRGB(loader[i].backgroundPixel)); 183 } 184 gc.setBackground(bgColor !is null ? bgColor : shellBackground); 185 gc.fillRectangle(imageData.x, imageData.y, imageData.width, imageData.height); 186 if (bgColor !is null) bgColor.dispose(); 187 break; 188 default: 189 /* Restore the previous image before drawing. */ 190 gc.drawImage( 191 image[i][j-1], 192 0, 193 0, 194 fullWidth, 195 fullHeight, 196 0, 197 0, 198 fullWidth, 199 fullHeight); 200 break; 201 } 202 Image newFrame = new Image(display, imageData); 203 gc.drawImage(newFrame, 204 0, 205 0, 206 imageData.width, 207 imageData.height, 208 imageData.x, 209 imageData.y, 210 imageData.width, 211 imageData.height); 212 newFrame.dispose(); 213 gc.dispose(); 214 } 215 } 216 } 217 } 218 219 void startAnimationThreads() { 220 animateThread = new Thread[image.length]; 221 for (int ii = 0; ii < image.length; ii++) { 222 animateThread[ii] = new class(ii) Thread { 223 int imageDataIndex = 0; 224 int id = 0; 225 this(int _id) { 226 id = _id; 227 //name = "Animation "~to!(char[])(ii); 228 //isDaemon = true; 229 super(&run); 230 } 231 override 232 void run() { 233 try { 234 int repeatCount = loader[id].repeatCount; 235 while (loader[id].repeatCount == 0 || repeatCount > 0) { 236 imageDataIndex = (imageDataIndex + 1) % cast(int)imageDataArray[id].length; 237 if (!display.isDisposed()) { 238 display.asyncExec(new class Runnable { 239 public void run() { 240 if (!item[id].isDisposed()) 241 item[id].setImage(image[id][imageDataIndex]); 242 } 243 }); 244 } 245 246 /* Sleep for the specified delay time (adding commonly-used slow-down fudge factors). */ 247 try { 248 int ms = imageDataArray[id][imageDataIndex].delayTime * 10; 249 if (ms < 20) ms += 30; 250 if (ms < 30) ms += 10; 251 Thread.sleep(1 * ms); 252 } catch (ThreadException e) { 253 } 254 255 /* If we have just drawn the last image, decrement the repeat count and start again. */ 256 if (imageDataIndex == imageDataArray[id].length - 1) repeatCount--; 257 } 258 } catch (SWTException ex) { 259 version(Tango){ 260 Stdout.print("There was an error animating the GIF").newline; 261 } else { // Phobos 262 writeln("There was an error animating the GIF"); 263 } 264 ex.printStackTrace(); 265 } 266 } 267 }; 268 animateThread[ii].start(); 269 } 270 } 271