Java tutorial
/****************************************************************************** * 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); } } }