eu.geclipse.ui.providers.ProgressTreeNode.java Source code

Java tutorial

Introduction

Here is the source code for eu.geclipse.ui.providers.ProgressTreeNode.java

Source

/******************************************************************************
 * Copyright (c) 2008 g-Eclipse consortium 
 * 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
 *
 * Initial development of the original code was made for
 * project g-Eclipse founded by European Union
 * project number: FP6-IST-034327  http://www.geclipse.eu/
 *
 * Contributor(s):
 *     Mathias Stuempert - initial API and implementation
 *****************************************************************************/

package eu.geclipse.ui.providers;

import java.net.URL;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

import eu.geclipse.ui.internal.Activator;

public class ProgressTreeNode implements IProgressMonitor, Listener {

    /**
     * Internal class that handles UI updates.
     */
    private static class ProgressNodeUpdater implements Runnable {

        /**
         * The progress tree node used to show the progress.
         */
        private ProgressTreeNode node;

        /**
         * The last progress string.
         */
        private String lastProgress;

        private boolean wasAlreadyDone;

        /**
         * Construct a new updater for the specified {@link ProgressTreeNode}.
         * 
         * @param node The progress tree node showing the progress.
         */
        public ProgressNodeUpdater(final ProgressTreeNode node) {
            this.node = node;
            this.wasAlreadyDone = false;
        }

        /* (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        public void run() {
            String progress = this.node.toString();
            if ((progress != null) && !progress.equals(this.lastProgress)) {
                this.lastProgress = progress;
                this.node.getViewer().update(this.node, null);
            } else if (this.node.isDone() && !this.wasAlreadyDone) {
                this.wasAlreadyDone = true;
                this.node.getViewer().getTree().redraw();
            }
        }

        /**
         * Reset the progress.
         */
        public void reset() {
            this.lastProgress = null;
        }

    }

    private static Image emptyProgress;

    private static Image fullProgress;

    static {
        URL emptyURL = Activator.getDefault().getBundle().getEntry("icons/extras/progress_bar_empty.gif"); //$NON-NLS-1$
        emptyProgress = ImageDescriptor.createFromURL(emptyURL).createImage();
        URL fullURL = Activator.getDefault().getBundle().getEntry("icons/extras/progress_bar_full.gif"); //$NON-NLS-1$
        fullProgress = ImageDescriptor.createFromURL(fullURL).createImage();
    }

    protected boolean done;

    private int tWork;

    private double worked;

    private String taskName;

    private boolean canceled;

    private TreeViewer viewer;

    private ProgressNodeUpdater updater;

    public ProgressTreeNode(final TreeViewer viewer) {

        this.tWork = 100;
        this.worked = 0;
        this.done = false;
        this.canceled = false;
        this.taskName = "Pending...";
        this.updater = new ProgressNodeUpdater(this);
        this.viewer = viewer;

        final Tree tree = viewer.getTree();
        if (!tree.isDisposed()) {
            Display display = tree.getDisplay();
            display.syncExec(new Runnable() {
                public void run() {
                    if (!tree.isDisposed()) {
                        tree.addListener(SWT.MeasureItem, ProgressTreeNode.this);
                        tree.addListener(SWT.EraseItem, ProgressTreeNode.this);
                        tree.addListener(SWT.PaintItem, ProgressTreeNode.this);
                    }
                }
            });
        }

    }

    public void beginTask(final String name, final int totalWork) {
        this.taskName = name;
        this.tWork = totalWork;
        this.worked = 0;
        this.done = false;
        this.canceled = false;
        update();
    }

    public void done() {
        this.worked = this.tWork;
        this.done = true;
        update();
    }

    public TreeViewer getViewer() {
        return this.viewer;
    }

    public void handleEvent(final Event event) {
        if ((event.item instanceof TreeItem) && (event.index == 0)) {
            Object data = ((TreeItem) event.item).getData();
            if (data == this) {
                switch (event.type) {
                case SWT.MeasureItem:
                    measureItem(event);
                    break;
                case SWT.EraseItem:
                    eraseItem(event);
                    break;
                case SWT.PaintItem:
                    paintItem(event);
                    break;
                }
            }
        }
    }

    public void internalWorked(final double work) {
        this.worked += work;
        update();
    }

    public boolean isCanceled() {
        return this.canceled;
    }

    /**
     * Determine if the job is done.
     * 
     * @return True if the job is done.
     */
    public boolean isDone() {
        return this.done;
    }

    public void setCanceled(final boolean value) {
        this.canceled = value;
        update();
    }

    public void setTaskName(final String name) {
        this.taskName = name;
        update();
    }

    @Override
    public String toString() {
        String resultString = this.taskName + " (" //$NON-NLS-1$
                + String.valueOf(getProgressPercent()) + ")"; //$NON-NLS-1$
        return resultString;
    }

    public void subTask(final String name) {
        setTaskName(name);
    }

    public void worked(final int work) {
        internalWorked(work);
    }

    /**
     * Get the current progress in percent.
     * 
     * @return The current progress.
     */
    private int getProgressPercent() {
        return (int) Math.round(100. * this.worked / this.tWork);
    }

    /**
     * Convenience method for the SWT.EraseItem event.
     * 
     * @param event The event triggering this erasure.
     */
    private void eraseItem(@SuppressWarnings("unused") final Event event) {
        // empty implementation
    }

    /**
     * Convenience method for the SWT.MeasureItem event.
     * 
     * @param event The event triggering this measurement.
     */
    private void measureItem(final Event event) {

        int textHeight = event.gc.getFontMetrics().getHeight();
        int imageWidth = emptyProgress.getBounds().width;
        int imageHeight = emptyProgress.getBounds().height;
        int textWidth = this.taskName == null ? 0 : event.gc.textExtent(this.taskName).x;

        event.height = Math.max(textHeight, imageHeight);
        event.width = textWidth + imageWidth + 2;

    }

    /**
     * Convenience method for the SWT.PaintItem event.
     * 
     * @param event The event triggering this paint.
     */
    protected void paintItem(final Event event) {

        Display display = this.viewer.getTree().getDisplay();
        Color black = display.getSystemColor(SWT.COLOR_BLACK);
        event.gc.fillRectangle(event.x, event.y, event.width, event.height);

        Color white = display.getSystemColor(SWT.COLOR_WHITE);

        int progress = getProgressPercent();

        int barwidth = fullProgress.getBounds().width;
        int barheight = fullProgress.getBounds().height;
        int bary = event.y + (event.height - barheight) / 2;
        int barp = barwidth * progress / 100;

        event.gc.drawImage(emptyProgress, barp, 0, barwidth - barp, barheight, event.x + barp + 2, bary,
                barwidth - barp, barheight);
        event.gc.drawImage(fullProgress, 0, 0, barp, barheight, event.x + 2, bary, barp, barheight);

        String progressString = String.valueOf(progress) + "%"; //$NON-NLS-1$ //$NON-NLS-2$
        Point textExtend = event.gc.textExtent(progressString);
        int progressX = event.x + 2 + (barwidth - textExtend.x) / 2;
        event.gc.setForeground(white);
        event.gc.drawText(progressString, progressX + 1, event.y + 2, true);
        event.gc.setForeground(black);
        event.gc.drawText(progressString, progressX, event.y + 1, true);

        int textX = event.x + 6 + barwidth;
        if (this.taskName != null) {
            event.gc.setForeground(black);
            event.gc.drawText(this.taskName, textX, event.y + 1, true);
        }

    }

    /**
     * Update the tree in order to repaint this node.
     */
    protected void update() {
        Tree tree = getViewer().getTree();
        if (!tree.isDisposed()) {
            Display display = tree.getDisplay();
            display.asyncExec(this.updater);
        }
    }

}