Mercurial > projects > dwt-addons
annotate dwtx/ui/internal/forms/widgets/BusyIndicator.d @ 167:862b05e0334a
Add a wrapper for Thread
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 09 Sep 2008 15:59:16 +0200 |
parents | 7ffeace6c47f |
children |
rev | line source |
---|---|
75 | 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 * Stefan Mucke - fix for Bug 156456 | |
11 * Port to the D programming language: | |
12 * Frank Benoit <benoit@tionex.de> | |
13 *******************************************************************************/ | |
14 module dwtx.ui.internal.forms.widgets.BusyIndicator; | |
15 | |
16 import dwtx.ui.internal.forms.widgets.FormUtil; | |
17 | |
18 import dwt.DWT; | |
19 import dwt.events.PaintEvent; | |
20 import dwt.events.PaintListener; | |
21 import dwt.graphics.GC; | |
22 import dwt.graphics.Image; | |
23 import dwt.graphics.ImageData; | |
24 import dwt.graphics.Point; | |
25 import dwt.graphics.Rectangle; | |
26 import dwt.widgets.Canvas; | |
27 import dwt.widgets.Composite; | |
28 import dwt.widgets.Display; | |
90 | 29 // import dwtx.core.runtime.FileLocator; |
30 // import dwtx.core.runtime.Path; | |
31 // import dwtx.core.runtime.Platform; | |
75 | 32 import dwtx.jface.resource.ImageDescriptor; |
33 | |
34 import dwt.dwthelper.utils; | |
35 import dwt.dwthelper.Runnable; | |
36 | |
37 import tango.util.Convert; | |
167 | 38 import dwtx.dwtxhelper.JThread; |
75 | 39 |
40 public final class BusyIndicator : Canvas { | |
41 | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
76
diff
changeset
|
42 alias Canvas.computeSize computeSize; |
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
76
diff
changeset
|
43 |
167 | 44 class BusyThread : JThread { |
75 | 45 Rectangle bounds; |
46 Display display; | |
47 GC offScreenImageGC; | |
48 Image offScreenImage; | |
49 Image timage; | |
50 bool stop; | |
51 | |
52 private this(Rectangle bounds, Display display, GC offScreenImageGC, Image offScreenImage) { | |
53 this.bounds = bounds; | |
54 this.display = display; | |
55 this.offScreenImageGC = offScreenImageGC; | |
56 this.offScreenImage = offScreenImage; | |
57 } | |
58 | |
167 | 59 public override void run() { |
75 | 60 try { |
61 /* | |
62 * Create an off-screen image to draw on, and fill it with | |
63 * the shell background. | |
64 */ | |
65 FormUtil.setAntialias(offScreenImageGC, DWT.ON); | |
66 display.syncExec(dgRunnable( { | |
67 if (!isDisposed()) | |
68 drawBackground(offScreenImageGC, 0, 0, | |
69 bounds.width, | |
70 bounds.height); | |
71 })); | |
72 if (isDisposed()) | |
73 return; | |
74 | |
75 /* | |
76 * Create the first image and draw it on the off-screen | |
77 * image. | |
78 */ | |
79 int imageDataIndex = 0; | |
80 ImageData imageData; | |
81 synchronized (this.outer) { | |
82 timage = getImage(imageDataIndex); | |
83 imageData = timage.getImageData(); | |
84 offScreenImageGC.drawImage(timage, 0, 0, | |
85 imageData.width, imageData.height, imageData.x, | |
86 imageData.y, imageData.width, imageData.height); | |
87 } | |
88 | |
89 /* | |
90 * Now loop through the images, creating and drawing | |
91 * each one on the off-screen image before drawing it on | |
92 * the shell. | |
93 */ | |
94 while (!stop && !isDisposed() && timage !is null) { | |
95 | |
96 /* | |
97 * Fill with the background color before | |
98 * drawing. | |
99 */ | |
100 display.syncExec(dgRunnable( (ImageData fimageData){ | |
101 if (!isDisposed()) { | |
102 drawBackground(offScreenImageGC, fimageData.x, | |
103 fimageData.y, fimageData.width, | |
104 fimageData.height); | |
105 } | |
106 }, imageData )); | |
107 | |
108 synchronized (this.outer) { | |
109 imageDataIndex = (imageDataIndex + 1) % IMAGE_COUNT; | |
110 timage = getImage(imageDataIndex); | |
111 imageData = timage.getImageData(); | |
112 offScreenImageGC.drawImage(timage, 0, 0, | |
113 imageData.width, imageData.height, | |
114 imageData.x, imageData.y, imageData.width, | |
115 imageData.height); | |
116 } | |
117 | |
118 /* Draw the off-screen image to the shell. */ | |
119 animationImage = offScreenImage; | |
120 display.syncExec(dgRunnable( { | |
121 if (!isDisposed()) | |
122 redraw(); | |
123 })); | |
124 /* | |
125 * Sleep for the specified delay time | |
126 */ | |
127 try { | |
167 | 128 JThread.sleep(MILLISECONDS_OF_DELAY); |
75 | 129 } catch (InterruptedException e) { |
76 | 130 ExceptionPrintStackTrace(e); |
75 | 131 } |
132 | |
133 | |
134 } | |
135 } catch (Exception e) { | |
136 } finally { | |
137 display.syncExec(dgRunnable( { | |
138 if (offScreenImage !is null | |
139 && !offScreenImage.isDisposed()) | |
140 offScreenImage.dispose(); | |
141 if (offScreenImageGC !is null | |
142 && !offScreenImageGC.isDisposed()) | |
143 offScreenImageGC.dispose(); | |
144 })); | |
145 clearImages(); | |
146 } | |
147 if (busyThread is null) | |
148 display.syncExec(dgRunnable( { | |
149 animationImage = null; | |
150 if (!isDisposed()) | |
151 redraw(); | |
152 })); | |
153 } | |
154 | |
155 public void setStop(bool stop) { | |
156 this.stop = stop; | |
157 } | |
158 } | |
159 | |
160 private static const int MARGIN = 0; | |
161 private static const int IMAGE_COUNT = 8; | |
162 private static const int MILLISECONDS_OF_DELAY = 180; | |
163 private Image[] imageCache; | |
164 protected Image image; | |
165 | |
166 protected Image animationImage; | |
167 | |
168 protected BusyThread busyThread; | |
169 | |
170 /** | |
171 * BusyWidget constructor comment. | |
172 * | |
173 * @param parent | |
174 * dwt.widgets.Composite | |
175 * @param style | |
176 * int | |
177 */ | |
178 public this(Composite parent, int style) { | |
179 super(parent, style); | |
180 | |
181 addPaintListener(new class PaintListener { | |
182 public void paintControl(PaintEvent event) { | |
183 onPaint(event); | |
184 } | |
185 }); | |
186 } | |
187 | |
188 public Point computeSize(int wHint, int hHint, bool changed) { | |
189 Point size = new Point(0, 0); | |
190 if (image !is null) { | |
191 Rectangle ibounds = image.getBounds(); | |
192 size.x = ibounds.width; | |
193 size.y = ibounds.height; | |
194 } | |
195 if (isBusy()) { | |
196 Rectangle bounds = getImage(0).getBounds(); | |
197 size.x = Math.max(size.x, bounds.width); | |
198 size.y = Math.max(size.y, bounds.height); | |
199 } | |
200 size.x += MARGIN + MARGIN; | |
201 size.y += MARGIN + MARGIN; | |
202 return size; | |
203 } | |
204 | |
205 /* (non-Javadoc) | |
206 * @see dwt.widgets.Control#forceFocus() | |
207 */ | |
208 public bool forceFocus() { | |
209 return false; | |
210 } | |
211 | |
212 /** | |
213 * Creates a thread to animate the image. | |
214 */ | |
215 protected synchronized void createBusyThread() { | |
216 if (busyThread !is null) | |
217 return; | |
218 | |
219 Rectangle bounds = getImage(0).getBounds(); | |
220 Display display = getDisplay(); | |
221 Image offScreenImage = new Image(display, bounds.width, bounds.height); | |
222 GC offScreenImageGC = new GC(offScreenImage); | |
223 busyThread = new BusyThread(bounds, display, offScreenImageGC, offScreenImage); | |
167 | 224 busyThread.setPriority(JThread.NORM_PRIORITY + 2); |
225 busyThread.setDaemon(true); | |
75 | 226 busyThread.start(); |
227 } | |
228 | |
229 public void dispose() { | |
230 if (busyThread !is null) { | |
231 busyThread.setStop(true); | |
232 busyThread = null; | |
233 } | |
234 super.dispose(); | |
235 } | |
236 | |
237 /** | |
238 * Return the image or <code>null</code>. | |
239 */ | |
240 public Image getImage() { | |
241 return image; | |
242 } | |
243 | |
244 /** | |
245 * Returns true if it is currently busy. | |
246 * | |
247 * @return bool | |
248 */ | |
249 public bool isBusy() { | |
250 return (busyThread !is null); | |
251 } | |
252 | |
253 /* | |
254 * Process the paint event | |
255 */ | |
256 protected void onPaint(PaintEvent event) { | |
257 if (animationImage !is null && animationImage.isDisposed()) { | |
258 animationImage = null; | |
259 } | |
260 Rectangle rect = getClientArea(); | |
261 if (rect.width is 0 || rect.height is 0) | |
262 return; | |
263 | |
264 GC gc = event.gc; | |
265 Image activeImage = animationImage !is null ? animationImage : image; | |
266 if (activeImage !is null) { | |
267 Rectangle ibounds = activeImage.getBounds(); | |
268 gc.drawImage(activeImage, rect.width / 2 - ibounds.width / 2, | |
269 rect.height / 2 - ibounds.height / 2); | |
270 } | |
271 } | |
272 | |
273 /** | |
274 * Sets the indicators busy count up (true) or down (false) one. | |
275 * | |
276 * @param busy | |
277 * bool | |
278 */ | |
279 public synchronized void setBusy(bool busy) { | |
280 if (busy) { | |
281 if (busyThread is null) | |
282 createBusyThread(); | |
283 } else { | |
284 if (busyThread !is null) { | |
285 busyThread.setStop(true); | |
286 busyThread = null; | |
287 } | |
288 } | |
289 } | |
290 | |
291 /** | |
292 * Set the image. The value <code>null</code> clears it. | |
293 */ | |
294 public void setImage(Image image) { | |
295 if (image !is this.image && !isDisposed()) { | |
296 this.image = image; | |
297 redraw(); | |
298 } | |
299 } | |
300 | |
301 | |
302 private ImageDescriptor createImageDescriptor(String relativePath) { | |
90 | 303 // Bundle bundle = Platform.getBundle("dwtx.ui.forms"); //$NON-NLS-1$ |
304 // URL url = FileLocator.find(bundle, new Path(relativePath),null); | |
305 // if (url is null) return null; | |
306 // try { | |
307 // url = FileLocator.resolve(url); | |
308 // return ImageDescriptor.createFromURL(url); | |
309 // } catch (IOException e) { | |
310 // return null; | |
311 // } | |
75 | 312 return null; |
313 } | |
314 | |
315 private synchronized Image getImage(int index) { | |
316 if (imageCache is null) { | |
317 imageCache = new Image[IMAGE_COUNT]; | |
318 } | |
319 if (imageCache[index] is null){ | |
320 ImageDescriptor descriptor = createImageDescriptor("$nl$/icons/progress/ani/" ~ to!(String)(index + 1) ~ ".png"); //$NON-NLS-1$ //$NON-NLS-2$ | |
321 imageCache[index] = descriptor.createImage(); | |
322 } | |
323 return imageCache[index]; | |
324 } | |
325 | |
326 private synchronized void clearImages() { | |
327 if (busyThread !is null) | |
328 return; | |
329 if (imageCache !is null) { | |
330 for (int index = 0; index < IMAGE_COUNT; index++) { | |
331 if (imageCache[index] !is null && !imageCache[index].isDisposed()) { | |
332 imageCache[index].dispose(); | |
333 imageCache[index] = null; | |
334 } | |
335 } | |
336 } | |
337 } | |
338 | |
339 } |