/******************************************************************************* * Copyright (c) 2003, 2016 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 *******************************************************************************/ package org.eclipse.ui.internal.browser; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; /** * An animated image to show busy status of the Web browser. */ public class BusyIndicator extends Canvas { protected Image[] images; protected Image image; protected Thread busyThread; protected boolean stop; /** * BusyWidget constructor comment. * @param parent org.eclipse.swt.widgets.Composite * @param style int */ public BusyIndicator(Composite parent, int style) { super(parent, style); images = ImageResource.getBusyImages(); addPaintListener(event -> onPaint(event)); image = images[0]; } @Override public Point computeSize(int wHint, int hHint, boolean changed) { return new Point(25, 25); } /** * Creates a thread to animate the image. */ protected synchronized void createBusyThread() { if (busyThread != null) return; stop = false; busyThread = new Thread() { protected int count; @Override public void run() { try { count = 1; while (!stop) { Display.getDefault().syncExec(() -> { if (!stop) { if (count < 13) setImage(images[count]); count++; if (count > 12) count = 1; } }); try { sleep(125); } catch (Exception e) { // ignore } } if (busyThread == null) Display.getDefault().syncExec(new Thread() { @Override public void run() { setImage(images[0]); } }); } catch (Exception e) { Trace.trace(Trace.WARNING, "Busy error", e); //$NON-NLS-1$ } } }; busyThread.setPriority(Thread.NORM_PRIORITY + 2); busyThread.setDaemon(true); busyThread.start(); } @Override public void dispose() { stop = 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 boolean */ public boolean isBusy() { return (busyThread != null); } /* * Process the paint event */ protected void onPaint(PaintEvent event) { Rectangle rect = getClientArea(); if (rect.width == 0 || rect.height == 0) return; GC gc = event.gc; if (image != null) gc.drawImage(image, 2, 2); } /** * Sets the indicators busy count up (true) or down (false) one. * * @param busy boolean */ public synchronized void setBusy(boolean busy) { if (busy) { if (busyThread == null) createBusyThread(); } else { if (busyThread != null) { stop = true; busyThread = null; } } } /** * Set the image. * The value <code>null</code> clears it. */ public void setImage(Image image) { if (image != this.image && !isDisposed()) { this.image = image; redraw(); } } }