diff dwtx/ui/internal/forms/widgets/BusyIndicator.d @ 75:5d489b9f966c

Fix continue porting
author Frank Benoit <benoit@tionex.de>
date Sat, 24 May 2008 05:11:16 +0200
parents
children e193036d82c9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/ui/internal/forms/widgets/BusyIndicator.d	Sat May 24 05:11:16 2008 +0200
@@ -0,0 +1,335 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *     Stefan Mucke - fix for Bug 156456
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module dwtx.ui.internal.forms.widgets.BusyIndicator;
+
+import dwtx.ui.internal.forms.widgets.FormUtil;
+
+import dwt.DWT;
+import dwt.events.PaintEvent;
+import dwt.events.PaintListener;
+import dwt.graphics.GC;
+import dwt.graphics.Image;
+import dwt.graphics.ImageData;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.widgets.Canvas;
+import dwt.widgets.Composite;
+import dwt.widgets.Display;
+import dwtx.jface.resource.ImageDescriptor;
+
+import dwt.dwthelper.utils;
+import dwt.dwthelper.Runnable;
+
+import tango.util.Convert;
+import tango.core.Thread;
+
+public final class BusyIndicator : Canvas {
+
+    class BusyThread : Thread {
+        Rectangle bounds;
+        Display display;
+        GC offScreenImageGC;
+        Image offScreenImage;
+        Image timage;
+        bool stop;
+
+        private this(Rectangle bounds, Display display, GC offScreenImageGC, Image offScreenImage) {
+            this.bounds = bounds;
+            this.display = display;
+            this.offScreenImageGC = offScreenImageGC;
+            this.offScreenImage = offScreenImage;
+        }
+
+        public void run() {
+            try {
+                /*
+                 * Create an off-screen image to draw on, and fill it with
+                 * the shell background.
+                 */
+                FormUtil.setAntialias(offScreenImageGC, DWT.ON);
+                display.syncExec(dgRunnable( {
+                        if (!isDisposed())
+                            drawBackground(offScreenImageGC, 0, 0,
+                                    bounds.width,
+                                    bounds.height);
+                }));
+                if (isDisposed())
+                    return;
+
+                /*
+                 * Create the first image and draw it on the off-screen
+                 * image.
+                 */
+                int imageDataIndex = 0;
+                ImageData imageData;
+                synchronized (this.outer) {
+                    timage = getImage(imageDataIndex);
+                    imageData = timage.getImageData();
+                    offScreenImageGC.drawImage(timage, 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.
+                 */
+                while (!stop && !isDisposed() && timage !is null) {
+
+                    /*
+                     * Fill with the background color before
+                     * drawing.
+                     */
+                    display.syncExec(dgRunnable( (ImageData fimageData){
+                        if (!isDisposed()) {
+                            drawBackground(offScreenImageGC, fimageData.x,
+                                    fimageData.y, fimageData.width,
+                                    fimageData.height);
+                        }
+                    }, imageData ));
+
+                    synchronized (this.outer) {
+                        imageDataIndex = (imageDataIndex + 1) % IMAGE_COUNT;
+                        timage = getImage(imageDataIndex);
+                        imageData = timage.getImageData();
+                        offScreenImageGC.drawImage(timage, 0, 0,
+                                imageData.width, imageData.height,
+                                imageData.x, imageData.y, imageData.width,
+                                imageData.height);
+                    }
+
+                    /* Draw the off-screen image to the shell. */
+                    animationImage = offScreenImage;
+                    display.syncExec(dgRunnable( {
+                        if (!isDisposed())
+                            redraw();
+                    }));
+                    /*
+                     * Sleep for the specified delay time
+                     */
+                    try {
+                        Thread.sleep(MILLISECONDS_OF_DELAY/1000.0);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+
+
+                }
+            } catch (Exception e) {
+            } finally {
+                display.syncExec(dgRunnable( {
+                    if (offScreenImage !is null
+                            && !offScreenImage.isDisposed())
+                        offScreenImage.dispose();
+                    if (offScreenImageGC !is null
+                            && !offScreenImageGC.isDisposed())
+                        offScreenImageGC.dispose();
+                }));
+                clearImages();
+            }
+            if (busyThread is null)
+                display.syncExec(dgRunnable( {
+                    animationImage = null;
+                    if (!isDisposed())
+                        redraw();
+                }));
+        }
+
+        public void setStop(bool stop) {
+            this.stop = stop;
+        }
+    }
+
+    private static const int MARGIN = 0;
+    private static const int IMAGE_COUNT = 8;
+    private static const int MILLISECONDS_OF_DELAY = 180;
+    private Image[] imageCache;
+    protected Image image;
+
+    protected Image animationImage;
+
+    protected BusyThread busyThread;
+
+    /**
+     * BusyWidget constructor comment.
+     *
+     * @param parent
+     *            dwt.widgets.Composite
+     * @param style
+     *            int
+     */
+    public this(Composite parent, int style) {
+        super(parent, style);
+
+        addPaintListener(new class PaintListener {
+            public void paintControl(PaintEvent event) {
+                onPaint(event);
+            }
+        });
+    }
+
+    public Point computeSize(int wHint, int hHint, bool changed) {
+        Point size = new Point(0, 0);
+        if (image !is null) {
+            Rectangle ibounds = image.getBounds();
+            size.x = ibounds.width;
+            size.y = ibounds.height;
+        }
+        if (isBusy()) {
+            Rectangle bounds = getImage(0).getBounds();
+            size.x = Math.max(size.x, bounds.width);
+            size.y = Math.max(size.y, bounds.height);
+        }
+        size.x += MARGIN + MARGIN;
+        size.y += MARGIN + MARGIN;
+        return size;
+    }
+
+    /* (non-Javadoc)
+     * @see dwt.widgets.Control#forceFocus()
+     */
+    public bool forceFocus() {
+        return false;
+    }
+
+    /**
+     * Creates a thread to animate the image.
+     */
+    protected synchronized void createBusyThread() {
+        if (busyThread !is null)
+            return;
+
+        Rectangle bounds = getImage(0).getBounds();
+        Display display = getDisplay();
+        Image offScreenImage = new Image(display, bounds.width, bounds.height);
+        GC offScreenImageGC = new GC(offScreenImage);
+        busyThread = new BusyThread(bounds, display, offScreenImageGC, offScreenImage);
+        busyThread.setPriority(Thread.NORM_PRIORITY + 2);
+        busyThread.setDaemon(true);
+        busyThread.start();
+    }
+
+    public void dispose() {
+        if (busyThread !is null) {
+            busyThread.setStop(true);
+            busyThread = null;
+        }
+        super.dispose();
+    }
+
+    /**
+     * Return the image or <code>null</code>.
+     */
+    public Image getImage() {
+        return image;
+    }
+
+    /**
+     * Returns true if it is currently busy.
+     *
+     * @return bool
+     */
+    public bool isBusy() {
+        return (busyThread !is null);
+    }
+
+    /*
+     * Process the paint event
+     */
+    protected void onPaint(PaintEvent event) {
+        if (animationImage !is null && animationImage.isDisposed()) {
+            animationImage = null;
+        }
+        Rectangle rect = getClientArea();
+        if (rect.width is 0 || rect.height is 0)
+            return;
+
+        GC gc = event.gc;
+        Image activeImage = animationImage !is null ? animationImage : image;
+        if (activeImage !is null) {
+            Rectangle ibounds = activeImage.getBounds();
+            gc.drawImage(activeImage, rect.width / 2 - ibounds.width / 2,
+                    rect.height / 2 - ibounds.height / 2);
+        }
+    }
+
+    /**
+     * Sets the indicators busy count up (true) or down (false) one.
+     *
+     * @param busy
+     *            bool
+     */
+    public synchronized void setBusy(bool busy) {
+        if (busy) {
+            if (busyThread is null)
+                createBusyThread();
+        } else {
+            if (busyThread !is null) {
+                busyThread.setStop(true);
+                busyThread = null;
+            }
+        }
+    }
+
+    /**
+     * Set the image. The value <code>null</code> clears it.
+     */
+    public void setImage(Image image) {
+        if (image !is this.image && !isDisposed()) {
+            this.image = image;
+            redraw();
+        }
+    }
+
+
+    private ImageDescriptor createImageDescriptor(String relativePath) {
+        //DWT_TODO
+//      Bundle bundle = Platform.getBundle("dwtx.ui.forms"); //$NON-NLS-1$
+//      URL url = FileLocator.find(bundle, new Path(relativePath),null);
+//      if (url is null) return null;
+//      try {
+//          url = FileLocator.resolve(url);
+//          return ImageDescriptor.createFromURL(url);
+//      } catch (IOException e) {
+//          return null;
+//      }
+        return null;
+    }
+
+    private synchronized Image getImage(int index) {
+        if (imageCache is null) {
+            imageCache = new Image[IMAGE_COUNT];
+        }
+        if (imageCache[index] is null){
+            ImageDescriptor descriptor = createImageDescriptor("$nl$/icons/progress/ani/" ~ to!(String)(index + 1) ~ ".png"); //$NON-NLS-1$ //$NON-NLS-2$
+            imageCache[index] = descriptor.createImage();
+        }
+        return imageCache[index];
+    }
+
+    private synchronized void clearImages() {
+        if (busyThread !is null)
+            return;
+        if (imageCache !is null) {
+            for (int index = 0; index < IMAGE_COUNT; index++) {
+                if (imageCache[index] !is null && !imageCache[index].isDisposed()) {
+                    imageCache[index].dispose();
+                    imageCache[index] = null;
+                }
+            }
+        }
+    }
+
+}