KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > forms > widgets > BusyIndicator


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.forms.widgets;
12
13 import java.io.IOException JavaDoc;
14 import java.io.InputStream JavaDoc;
15 import java.net.URL JavaDoc;
16
17 import org.eclipse.core.runtime.FileLocator;
18 import org.eclipse.core.runtime.Path;
19 import org.eclipse.core.runtime.Platform;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.PaintEvent;
22 import org.eclipse.swt.events.PaintListener;
23 import org.eclipse.swt.graphics.GC;
24 import org.eclipse.swt.graphics.Image;
25 import org.eclipse.swt.graphics.ImageData;
26 import org.eclipse.swt.graphics.ImageLoader;
27 import org.eclipse.swt.graphics.Point;
28 import org.eclipse.swt.graphics.Rectangle;
29 import org.eclipse.swt.widgets.Canvas;
30 import org.eclipse.swt.widgets.Composite;
31 import org.eclipse.swt.widgets.Display;
32 import org.osgi.framework.Bundle;
33
34 public class BusyIndicator extends Canvas {
35     private static final int MARGIN = 0;
36
37     private ImageData[] progressData;
38
39     protected ImageLoader loader;
40
41     protected Image image;
42
43     protected Image animationImage;
44
45     protected Thread JavaDoc busyThread;
46
47     protected boolean stop;
48
49     /**
50      * BusyWidget constructor comment.
51      *
52      * @param parent
53      * org.eclipse.swt.widgets.Composite
54      * @param style
55      * int
56      */

57     public BusyIndicator(Composite parent, int style) {
58         super(parent, style);
59
60         loadProgressImage();
61
62         addPaintListener(new PaintListener() {
63             public void paintControl(PaintEvent event) {
64                 onPaint(event);
65             }
66         });
67     }
68
69     private void loadProgressImage() {
70         InputStream JavaDoc is = null;
71         Bundle bundle = Platform.getBundle("org.eclipse.ui.forms"); //$NON-NLS-1$
72
URL JavaDoc url = FileLocator.find(bundle, new Path("$nl$/icons/progress/ani/progress.gif"),null); //$NON-NLS-1$
73
if (url != null) {
74             try {
75                 url = FileLocator.resolve(url);
76                 is = url.openStream();
77             } catch (IOException JavaDoc e) {
78                 is = null;
79             }
80         }
81         if (is != null) {
82             loader = new ImageLoader();
83             try {
84                 progressData = loader.load(is);
85             } catch (IllegalArgumentException JavaDoc e) {
86             }
87             try {
88                 is.close();
89             } catch (IOException JavaDoc e) {
90             }
91         }
92     }
93
94     public Point computeSize(int wHint, int hHint, boolean changed) {
95         Point size = new Point(0, 0);
96         if (image != null) {
97             Rectangle ibounds = image.getBounds();
98             size.x = ibounds.width;
99             size.y = ibounds.height;
100         }
101         if (loader != null && isBusy()) {
102             size.x = Math.max(size.x, loader.logicalScreenWidth);
103             size.y = Math.max(size.y, loader.logicalScreenHeight);
104         }
105         size.x += MARGIN + MARGIN;
106         size.y += MARGIN + MARGIN;
107         return size;
108     }
109
110     /**
111      * Creates a thread to animate the image.
112      */

113     protected synchronized void createBusyThread() {
114         if (busyThread != null)
115             return;
116
117         stop = false;
118         final Display display = getDisplay();
119         final Image offScreenImage = new Image(display,
120                 loader.logicalScreenWidth,
121                 loader.logicalScreenHeight);
122         final GC offScreenImageGC = new GC(offScreenImage);
123         busyThread = new Thread JavaDoc() {
124             private Image timage;
125
126             public void run() {
127                 try {
128                     /*
129                      * Create an off-screen image to draw on, and fill it with
130                      * the shell background.
131                      */

132                     FormUtil.setAntialias(offScreenImageGC, SWT.ON);
133                     display.syncExec(new Runnable JavaDoc() {
134                         public void run() {
135                             if (!isDisposed())
136                                 drawBackground(offScreenImageGC, 0, 0,
137                                         loader.logicalScreenWidth,
138                                         loader.logicalScreenHeight);
139                         }
140                     });
141                     if (isDisposed())
142                         return;
143
144                     /*
145                      * Create the first image and draw it on the off-screen
146                      * image.
147                      */

148                     int imageDataIndex = 0;
149                     ImageData imageData = progressData[imageDataIndex];
150                     if (timage != null && !timage.isDisposed())
151                         timage.dispose();
152                     timage = new Image(display, imageData);
153                     offScreenImageGC.drawImage(timage, 0, 0,
154                             imageData.width, imageData.height, imageData.x,
155                             imageData.y, imageData.width, imageData.height);
156
157                     /*
158                      * Now loop through the images, creating and drawing
159                      * each one on the off-screen image before drawing it on
160                      * the shell.
161                      */

162                     int repeatCount = loader.repeatCount;
163                     while (loader.repeatCount == 0 || repeatCount > 0) {
164                         if (stop || isDisposed())
165                             break;
166                         switch (imageData.disposalMethod) {
167                         case SWT.DM_FILL_BACKGROUND:
168                             /*
169                              * Fill with the background color before
170                              * drawing.
171                              */

172                             /*
173                              * offScreenImageGC.fillRectangle(imageData.x,
174                              * imageData.y, imageData.width,
175                              * imageData.height);
176                              */

177                             final ImageData fimageData = imageData;
178                             display.syncExec(new Runnable JavaDoc() {
179                                 public void run() {
180                                     if (!isDisposed()) {
181                                         drawBackground(offScreenImageGC, fimageData.x,
182                                                 fimageData.y, fimageData.width,
183                                                 fimageData.height);
184                                     }
185                                 }
186                             });
187                             break;
188                         case SWT.DM_FILL_PREVIOUS:
189                             /* Restore the previous image before drawing. */
190                             offScreenImageGC.drawImage(timage, 0, 0,
191                                     imageData.width, imageData.height,
192                                     imageData.x, imageData.y,
193                                     imageData.width, imageData.height);
194                             break;
195                         }
196
197                         imageDataIndex = (imageDataIndex + 1)
198                                 % progressData.length;
199                         imageData = progressData[imageDataIndex];
200                         timage.dispose();
201                         timage = new Image(display, imageData);
202                         offScreenImageGC.drawImage(timage, 0, 0,
203                                 imageData.width, imageData.height,
204                                 imageData.x, imageData.y, imageData.width,
205                                 imageData.height);
206
207                         /* Draw the off-screen image to the shell. */
208                         animationImage = offScreenImage;
209                         display.syncExec(new Runnable JavaDoc() {
210                             public void run() {
211                                 if (!isDisposed())
212                                     redraw();
213                             }
214                         });
215                         /*
216                          * Sleep for the specified delay time (adding
217                          * commonly-used slow-down fudge factors).
218                          */

219                         try {
220                             int ms = imageData.delayTime * 10;
221                             if (ms < 20)
222                                 ms += 50;
223                             if (ms < 30)
224                                 ms += 20;
225                             Thread.sleep(ms);
226                         } catch (InterruptedException JavaDoc e) {
227                         }
228
229                         /*
230                          * If we have just drawn the last image, decrement
231                          * the repeat count and start again.
232                          */

233                         if (imageDataIndex == progressData.length - 1)
234                             repeatCount--;
235                     }
236                 } catch (Exception JavaDoc e) {
237                     // Trace.trace(Trace.WARNING, "Busy error", e);
238
// //$NON-NLS-1$
239
} finally {
240                     display.syncExec(new Runnable JavaDoc() {
241                         public void run() {
242                             if (offScreenImage != null
243                                     && !offScreenImage.isDisposed())
244                                 offScreenImage.dispose();
245                             if (offScreenImageGC != null
246                                     && !offScreenImageGC.isDisposed())
247                                 offScreenImageGC.dispose();
248                         }
249                     });
250                     if (timage != null && !timage.isDisposed())
251                         timage.dispose();
252                 }
253                 if (busyThread == null)
254                     display.syncExec(new Runnable JavaDoc() {
255                         public void run() {
256                             animationImage = null;
257                             if (!isDisposed())
258                                 redraw();
259                         }
260                     });
261             }
262         };
263         busyThread.setPriority(Thread.NORM_PRIORITY + 2);
264         busyThread.setDaemon(true);
265         busyThread.start();
266     }
267
268     public void dispose() {
269         stop = true;
270         busyThread = null;
271         super.dispose();
272     }
273
274     /**
275      * Return the image or <code>null</code>.
276      */

277     public Image getImage() {
278         return image;
279     }
280
281     /**
282      * Returns true if it is currently busy.
283      *
284      * @return boolean
285      */

286     public boolean isBusy() {
287         return (busyThread != null);
288     }
289
290     /*
291      * Process the paint event
292      */

293     protected void onPaint(PaintEvent event) {
294         if (animationImage != null && animationImage.isDisposed()) {
295             animationImage = null;
296         }
297         Rectangle rect = getClientArea();
298         if (rect.width == 0 || rect.height == 0)
299             return;
300
301         GC gc = event.gc;
302         Image activeImage = animationImage != null ? animationImage : image;
303         if (activeImage != null) {
304             Rectangle ibounds = activeImage.getBounds();
305             gc.drawImage(activeImage, rect.width / 2 - ibounds.width / 2,
306                     rect.height / 2 - ibounds.height / 2);
307         }
308     }
309
310     /**
311      * Sets the indicators busy count up (true) or down (false) one.
312      *
313      * @param busy
314      * boolean
315      */

316     public synchronized void setBusy(boolean busy) {
317         if (busy) {
318             if (busyThread == null)
319                 createBusyThread();
320         } else {
321             if (busyThread != null) {
322                 stop = true;
323                 busyThread = null;
324             }
325         }
326     }
327
328     /**
329      * Set the image. The value <code>null</code> clears it.
330      */

331     public void setImage(Image image) {
332         if (image != this.image && !isDisposed()) {
333             this.image = image;
334             redraw();
335         }
336     }
337 }
338
Popular Tags