| /******************************************************************************* |
| * Copyright (c) 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.progress; |
| |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.lang.reflect.InvocationTargetException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IProgressMonitorWithBlocking; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.IJobChangeEvent; |
| import org.eclipse.core.runtime.jobs.IJobChangeListener; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.core.runtime.jobs.JobChangeAdapter; |
| import org.eclipse.core.runtime.jobs.ProgressProvider; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.ImageData; |
| import org.eclipse.swt.graphics.ImageLoader; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.internal.Workbench; |
| import org.eclipse.ui.progress.IProgressService; |
| import org.eclipse.ui.progress.UIJob; |
| |
| /** |
| * JobProgressManager provides the progress monitor to the job manager and |
| * informs any ProgressContentProviders of changes. |
| */ |
| public class ProgressManager extends ProgressProvider implements IProgressService { |
| |
| private static ProgressManager singleton; |
| private Map jobs = Collections.synchronizedMap(new HashMap()); |
| private Collection listeners = Collections.synchronizedList(new ArrayList()); |
| Object listenerKey = new Object(); |
| private WorkbenchMonitorProvider monitorProvider; |
| private ProgressFeedbackManager feedbackManager = new ProgressFeedbackManager(); |
| IJobChangeListener changeListener; |
| |
| static final String PROGRESS_VIEW_NAME = "org.eclipse.ui.views.ProgressView"; //$NON-NLS-1$ |
| static final String PROGRESS_FOLDER = "icons/full/progress/"; //$NON-NLS-1$ |
| |
| private static final String PROGRESS_20 = "progress20.gif"; //$NON-NLS-1$ |
| private static final String PROGRESS_40 = "progress40.gif"; //$NON-NLS-1$ |
| private static final String PROGRESS_60 = "progress60.gif"; //$NON-NLS-1$ |
| private static final String PROGRESS_80 = "progress80.gif"; //$NON-NLS-1$ |
| private static final String PROGRESS_100 = "progress100.gif"; //$NON-NLS-1$ |
| |
| private static final String SLEEPING_JOB = "sleeping.gif"; //$NON-NLS-1$ |
| private static final String WAITING_JOB = "waiting.gif"; //$NON-NLS-1$ |
| private static final String ERROR_JOB = "errorstate.gif"; //$NON-NLS-1$ |
| private static final String BLOCKED_JOB = "lockedstate.gif"; //$NON-NLS-1$ |
| |
| private static final String PROGRESS_20_KEY = "PROGRESS_20"; //$NON-NLS-1$ |
| private static final String PROGRESS_40_KEY = "PROGRESS_40"; //$NON-NLS-1$ |
| private static final String PROGRESS_60_KEY = "PROGRESS_60"; //$NON-NLS-1$ |
| private static final String PROGRESS_80_KEY = "PROGRESS_80"; //$NON-NLS-1$ |
| private static final String PROGRESS_100_KEY = "PROGRESS_100"; //$NON-NLS-1$ |
| |
| private static final String SLEEPING_JOB_KEY = "SLEEPING_JOB"; //$NON-NLS-1$ |
| private static final String WAITING_JOB_KEY = "WAITING_JOB"; //$NON-NLS-1$ |
| private static final String ERROR_JOB_KEY = "ERROR_JOB"; //$NON-NLS-1$ |
| private static final String BLOCKED_JOB_KEY = "LOCKED_JOB"; //$NON-NLS-1$ |
| |
| //A list of keys for looking up the images in the image registry |
| static String[] keys = new String[] { PROGRESS_20_KEY, PROGRESS_40_KEY, PROGRESS_60_KEY, PROGRESS_80_KEY, PROGRESS_100_KEY }; |
| |
| Hashtable runnableMonitors = new Hashtable(); |
| |
| |
| /** |
| * Get the progress manager currently in use. |
| * |
| * @return JobProgressManager |
| */ |
| public static ProgressManager getInstance() { |
| if (singleton == null) |
| singleton = new ProgressManager(); |
| return singleton; |
| } |
| |
| /** |
| * The JobMonitor is the inner class that handles the IProgressMonitor |
| * integration with the ProgressMonitor. |
| */ |
| private class JobMonitor implements IProgressMonitorWithBlocking { |
| Job job; |
| IProgressMonitor workbenchMonitor; |
| String currentTaskName; |
| |
| /** |
| * Create a monitor on the supplied job. |
| * |
| * @param newJob |
| */ |
| JobMonitor(Job newJob) { |
| job = newJob; |
| workbenchMonitor = monitorProvider.getMonitor(job); |
| } |
| |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String, |
| * int) |
| */ |
| public void beginTask(String taskName, int totalWork) { |
| JobInfo info = getJobInfo(job); |
| info.beginTask(taskName, totalWork); |
| refresh(info); |
| currentTaskName = taskName; |
| workbenchMonitor.beginTask(taskName, totalWork); |
| } |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#done() |
| */ |
| public void done() { |
| JobInfo info = getJobInfo(job); |
| info.clearTaskInfo(); |
| info.clearChildren(); |
| workbenchMonitor.done(); |
| runnableMonitors.remove(this); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double) |
| */ |
| public void internalWorked(double work) { |
| JobInfo info = getJobInfo(job); |
| if (info.hasTaskInfo()) { |
| info.addWork(work); |
| refresh(info); |
| } |
| workbenchMonitor.internalWorked(work); |
| } |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled() |
| */ |
| public boolean isCanceled() { |
| JobInfo info = getJobInfo(job); |
| return info.isCanceled(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean) |
| */ |
| public void setCanceled(boolean value) { |
| workbenchMonitor.setCanceled(value); |
| JobInfo info = getJobInfo(job); |
| |
| //Don't bother cancelling twice |
| if (value && !info.isCanceled()) |
| info.cancel(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String) |
| */ |
| public void setTaskName(String taskName) { |
| |
| JobInfo info = getJobInfo(job); |
| if (info.hasTaskInfo()) |
| info.setTaskName(taskName); |
| else { |
| beginTask(taskName, 100); |
| return; |
| } |
| |
| info.clearChildren(); |
| refresh(info); |
| currentTaskName = taskName; |
| workbenchMonitor.setTaskName(taskName); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String) |
| */ |
| public void subTask(String name) { |
| |
| if (name.length() == 0) |
| return; |
| JobInfo info = getJobInfo(job); |
| |
| info.clearChildren(); |
| info.addSubTask(name); |
| refresh(info); |
| workbenchMonitor.subTask(name); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#worked(int) |
| */ |
| public void worked(int work) { |
| internalWorked(work); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked() |
| */ |
| public void clearBlocked() { |
| JobInfo info = getJobInfo(job); |
| info.setBlockedStatus(null); |
| refresh(info); |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus) |
| */ |
| public void setBlocked(IStatus reason) { |
| JobInfo info = getJobInfo(job); |
| info.setBlockedStatus(null); |
| refresh(info); |
| } |
| } |
| |
| /** |
| * Create a new instance of the receiver. |
| */ |
| ProgressManager() { |
| Platform.getJobManager().setProgressProvider(this); |
| createChangeListener(); |
| Platform.getJobManager().addJobChangeListener(this.changeListener); |
| monitorProvider = new WorkbenchMonitorProvider(); |
| URL iconsRoot = Platform.getPlugin(PlatformUI.PLUGIN_ID).find(new Path(ProgressManager.PROGRESS_FOLDER)); |
| |
| try { |
| setUpImage(iconsRoot, PROGRESS_20, PROGRESS_20_KEY); |
| setUpImage(iconsRoot, PROGRESS_40, PROGRESS_40_KEY); |
| setUpImage(iconsRoot, PROGRESS_60, PROGRESS_60_KEY); |
| setUpImage(iconsRoot, PROGRESS_80, PROGRESS_80_KEY); |
| setUpImage(iconsRoot, PROGRESS_100, PROGRESS_100_KEY); |
| |
| setUpImage(iconsRoot, SLEEPING_JOB, SLEEPING_JOB_KEY); |
| setUpImage(iconsRoot, WAITING_JOB, WAITING_JOB_KEY); |
| setUpImage(iconsRoot, ERROR_JOB, ERROR_JOB_KEY); |
| setUpImage(iconsRoot, BLOCKED_JOB, BLOCKED_JOB_KEY); |
| |
| } catch (MalformedURLException e) { |
| ProgressManagerUtil.logException(e); |
| } |
| |
| } |
| |
| /** |
| * Return the IJobChangeListener registered with the Job manager. |
| * @return IJobChangeListener |
| */ |
| private void createChangeListener(){ |
| |
| changeListener = |
| new JobChangeAdapter(){ |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#aboutToRun(org.eclipse.core.runtime.jobs.IJobChangeEvent) |
| */ |
| public void aboutToRun(IJobChangeEvent event) { |
| JobInfo info = getJobInfo(event.getJob()); |
| refresh(info); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.runtime.jobs.IJobChangeEvent) |
| */ |
| public void done(IJobChangeEvent event) { |
| if(!PlatformUI.isWorkbenchRunning()) |
| return; |
| JobInfo info = getJobInfo(event.getJob()); |
| if (event.getResult().getSeverity() == IStatus.ERROR) { |
| info.setError(event.getResult()); |
| UIJob job = new UIJob(ProgressMessages.getString("JobProgressManager.OpenProgressJob")) {//$NON-NLS-1$ |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| |
| IWorkbench workbench = PlatformUI.getWorkbench(); |
| |
| //Abort on shutdown |
| if (workbench instanceof Workbench && ((Workbench) workbench).isClosing()) |
| return Status.CANCEL_STATUS; |
| IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); |
| |
| if (window == null) |
| return Status.CANCEL_STATUS; |
| ProgressManagerUtil.openProgressView(window); |
| return Status.OK_STATUS; |
| } |
| }; |
| job.schedule(); |
| refresh(info); |
| |
| } else { |
| jobs.remove(event.getJob()); |
| //Only refresh if we are showing it |
| remove(info); |
| |
| //If there are no more left then refresh all on the last displayed one |
| if (hasNoRegularJobInfos() |
| && !isNonDisplayableJob(event.getJob(),false)) |
| refreshAll(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#scheduled(org.eclipse.core.runtime.jobs.IJobChangeEvent) |
| */ |
| public void scheduled(IJobChangeEvent event) { |
| if (isNeverDisplayedJob(event.getJob())) |
| return; |
| |
| if (jobs.containsKey(event.getJob())) |
| refresh(getJobInfo(event.getJob())); |
| else { |
| JobInfo info = new JobInfo(event.getJob()); |
| jobs.put(event.getJob(), info); |
| add(info); |
| } |
| } |
| |
| }; |
| } |
| |
| /** |
| * Set up the image in the image regsitry. |
| * |
| * @param iconsRoot |
| * @param fileName |
| * @param key |
| * @throws MalformedURLException |
| */ |
| private void setUpImage(URL iconsRoot, String fileName, String key) throws MalformedURLException { |
| JFaceResources.getImageRegistry().put(key, ImageDescriptor.createFromURL(new URL(iconsRoot, fileName))); |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.jobs.IProgressProvider#createMonitor(org.eclipse.core.runtime.jobs.Job) |
| */ |
| public IProgressMonitor createMonitor(Job job) { |
| return progressFor(job); |
| } |
| |
| /** |
| * Return a monitor for the job. Check if we cached a monitor for this job |
| * previously for a long operation timeout check. |
| * |
| * @param job |
| * @return IProgressMonitor |
| */ |
| private JobMonitor progressFor(Job job) { |
| if (runnableMonitors.containsKey(job)) |
| return (JobMonitor) runnableMonitors.get(job); |
| else |
| return new JobMonitor(job); |
| } |
| |
| /** |
| * Add an IJobProgressManagerListener to listen to the changes. |
| * |
| * @param listener |
| */ |
| void addListener(IJobProgressManagerListener listener) { |
| synchronized (listenerKey) { |
| listeners.add(listener); |
| } |
| } |
| |
| /** |
| * Remove the supplied IJobProgressManagerListener from the list of |
| * listeners. |
| * |
| * @param listener |
| */ |
| void removeListener(IJobProgressManagerListener listener) { |
| synchronized (listenerKey) { |
| listeners.remove(listener); |
| } |
| |
| } |
| |
| |
| /** |
| * Get the JobInfo for the job. If it does not exist create it. |
| * |
| * @param job |
| * @return |
| */ |
| JobInfo getJobInfo(Job job) { |
| JobInfo info = (JobInfo) jobs.get(job); |
| if (info == null) { |
| info = new JobInfo(job); |
| jobs.put(job, info); |
| } |
| return info; |
| } |
| |
| /** |
| * Refresh the IJobProgressManagerListeners as a result of a change in |
| * info. |
| * |
| * @param info |
| */ |
| public void refresh(JobInfo info) { |
| |
| synchronized (listenerKey) { |
| Iterator iterator = listeners.iterator(); |
| while (iterator.hasNext()) { |
| IJobProgressManagerListener listener = (IJobProgressManagerListener) iterator.next(); |
| if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) |
| listener.refresh(info); |
| } |
| } |
| } |
| |
| /** |
| * Refresh all the IJobProgressManagerListener as a result of a change in |
| * the whole model. |
| * |
| * @param info |
| */ |
| public void refreshAll() { |
| synchronized (listenerKey) { |
| Iterator iterator = listeners.iterator(); |
| while (iterator.hasNext()) { |
| IJobProgressManagerListener listener = (IJobProgressManagerListener) iterator.next(); |
| listener.refreshAll(); |
| } |
| } |
| |
| } |
| |
| /** |
| * Refresh the content providers as a result of a deletion of info. |
| * |
| * @param info |
| */ |
| public void remove(JobInfo info) { |
| |
| synchronized (listenerKey) { |
| Iterator iterator = listeners.iterator(); |
| while (iterator.hasNext()) { |
| IJobProgressManagerListener listener = (IJobProgressManagerListener) iterator.next(); |
| if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) |
| listener.remove(info); |
| } |
| } |
| } |
| |
| /** |
| * Refresh the content providers as a result of an addition of info. |
| * |
| * @param info |
| */ |
| public void add(JobInfo info) { |
| synchronized (listenerKey) { |
| Iterator iterator = listeners.iterator(); |
| while (iterator.hasNext()) { |
| IJobProgressManagerListener listener = (IJobProgressManagerListener) iterator.next(); |
| if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) |
| listener.add(info); |
| } |
| } |
| |
| } |
| |
| /** |
| * Return whether or not this job is currently displayable. |
| * |
| * @param job |
| * @param debug |
| * If the listener is in debug mode. |
| * @return |
| */ |
| boolean isNonDisplayableJob(Job job, boolean debug) { |
| if (isNeverDisplayedJob(job)) |
| return true; |
| if (debug) //Always display in debug mode |
| return false; |
| else |
| return job.isSystem() || job.getState() == Job.SLEEPING; |
| } |
| |
| /** |
| * Return whether or not this job is ever displayable. |
| * |
| * @param job |
| * @return |
| */ |
| private boolean isNeverDisplayedJob(Job job) { |
| return job == null; |
| } |
| |
| /** |
| * Return the current job infos filtered on debug mode. |
| * @param debug |
| * @return |
| */ |
| public JobInfo[] getJobInfos(boolean debug) { |
| synchronized (jobs) { |
| Iterator iterator = jobs.keySet().iterator(); |
| Collection result = new ArrayList(); |
| while (iterator.hasNext()) { |
| Job next = (Job) iterator.next(); |
| if(!isNonDisplayableJob(next,debug)) |
| result.add(jobs.get(next)); |
| } |
| JobInfo[] infos = new JobInfo[result.size()]; |
| result.toArray(infos); |
| return infos; |
| } |
| } |
| |
| /** |
| * Return whether or not there are any jobs being displayed. |
| * |
| * @return boolean |
| */ |
| public boolean hasJobInfos() { |
| synchronized (jobs) { |
| Iterator iterator = jobs.keySet().iterator(); |
| while (iterator.hasNext()) { |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| /** |
| * Return true if there are no jobs or they are all debug. |
| * |
| * @return boolean |
| */ |
| private boolean hasNoRegularJobInfos() { |
| synchronized (jobs) { |
| |
| Iterator iterator = jobs.keySet().iterator(); |
| while (iterator.hasNext()) { |
| Job next = (Job) iterator.next(); |
| if (!isNonDisplayableJob(next, false)) |
| return false; |
| } |
| return true; |
| } |
| } |
| |
| /** |
| * Clear the job out of the list of those being displayed. Only do this for |
| * jobs that are an error. |
| * |
| * @param job |
| */ |
| void clearJob(Job job) { |
| JobInfo info = (JobInfo) jobs.get(job); |
| if (info != null && info.getErrorStatus() != null) { |
| jobs.remove(job); |
| remove(info); |
| } |
| } |
| |
| /** |
| * Clear all of the errors from the list. |
| */ |
| void clearAllErrors() { |
| Collection jobsToDelete = new ArrayList(); |
| synchronized (jobs) { |
| Iterator keySet = jobs.keySet().iterator(); |
| while (keySet.hasNext()) { |
| Object job = keySet.next(); |
| JobInfo info = (JobInfo) jobs.get(job); |
| if (info.getErrorStatus() != null) |
| jobsToDelete.add(job); |
| } |
| } |
| |
| Iterator deleteSet = jobsToDelete.iterator(); |
| while (deleteSet.hasNext()) { |
| jobs.remove(deleteSet.next()); |
| } |
| refreshAll(); |
| } |
| |
| /** |
| * Return whether or not there are any errors displayed. |
| * |
| * @return |
| */ |
| boolean hasErrorsDisplayed() { |
| |
| synchronized (jobs) { |
| Iterator keySet = jobs.keySet().iterator(); |
| while (keySet.hasNext()) { |
| Object job = keySet.next(); |
| JobInfo info = (JobInfo) jobs.get(job); |
| if (info.getErrorStatus() != null) |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Returns the image descriptor with the given relative path. |
| * |
| * @param source |
| * @return Image |
| */ |
| Image getImage(ImageData source) { |
| ImageData mask = source.getTransparencyMask(); |
| return new Image(null, source, mask); |
| } |
| |
| /** |
| * Returns the image descriptor with the given relative path. |
| * |
| * @param fileSystemPath |
| * The URL for the file system to the image. |
| * @param loader - |
| * the loader used to get this data |
| * @return ImageData[] |
| */ |
| ImageData[] getImageData(URL fileSystemPath, ImageLoader loader) { |
| try { |
| InputStream stream = fileSystemPath.openStream(); |
| ImageData[] result = loader.load(stream); |
| stream.close(); |
| return result; |
| } catch (FileNotFoundException exception) { |
| ProgressManagerUtil.logException(exception); |
| return null; |
| } catch (IOException exception) { |
| ProgressManagerUtil.logException(exception); |
| return null; |
| } |
| } |
| |
| /** |
| * Get the current image for the receiver. If there is no progress yet |
| * return null. |
| * |
| * @param element |
| * @return |
| */ |
| Image getDisplayImage(JobTreeElement element) { |
| if (element.isJobInfo()) { |
| JobInfo info = (JobInfo) element; |
| int done = info.getPercentDone(); |
| if (done > 0) { |
| int index = Math.min(4, (done / 20)); |
| return JFaceResources.getImage(keys[index]); |
| } else { |
| if (info.isBlocked()) |
| return JFaceResources.getImage(BLOCKED_JOB_KEY); |
| if (info.getErrorStatus() != null) |
| return JFaceResources.getImage(ERROR_JOB_KEY); |
| int state = info.getJob().getState(); |
| if (state == Job.SLEEPING) |
| return JFaceResources.getImage(SLEEPING_JOB_KEY); |
| if (state == Job.WAITING) |
| return JFaceResources.getImage(WAITING_JOB_KEY); |
| |
| //By default return the 0 progress image |
| return JFaceResources.getImage(keys[0]); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Block the current thread until UIJob is served. The message is used to |
| * announce to the user a pending UI Job. |
| * |
| * Note: This is experimental API and subject to change at any time. |
| * |
| * @param job |
| * @param message |
| * @return IStatus |
| * @since 3.0 |
| */ |
| public IStatus requestInUI(UIJob job, String message) { |
| return feedbackManager.requestInUI(job, message); |
| } |
| |
| /** |
| * Return the ProgressFeedbackManager for the receiver. |
| * |
| * @return ProgressFeedbackManager |
| */ |
| ProgressFeedbackManager getFeedbackManager() { |
| return feedbackManager; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.progress.IProgressManager#busyCursorWhile(org.eclipse.jface.operation.IRunnableWithProgress) |
| */ |
| public void busyCursorWhile(final IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { |
| |
| final ProgressMonitorJobsDialog dialog = new ProgressMonitorJobsDialog(null); |
| dialog.setOpenOnRun(false); |
| final boolean[] busy = { true }; |
| |
| scheduleProgressMonitorJob(dialog,busy); |
| |
| final InvocationTargetException[] invokes = new InvocationTargetException[1]; |
| final InterruptedException[] interrupt = new InterruptedException[1]; |
| |
| invokes[0] = null; |
| interrupt[0] = null; |
| |
| BusyIndicator.showWhile(Display.getCurrent(), new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| try { |
| dialog.setOpenOnRun(false); |
| dialog.run(true /* fork */ |
| , true /* cancelable */ |
| , runnable); |
| |
| //Run the event loop until the progress job wakes up |
| Display display = Display.getCurrent(); |
| while (busy[0]) { |
| if (!display.readAndDispatch()) |
| display.sleep(); |
| } |
| |
| } catch (InvocationTargetException e) { |
| invokes[0] = e; |
| } catch (InterruptedException e) { |
| interrupt[0] = e; |
| } |
| } |
| }); |
| |
| if (invokes[0] != null) |
| throw invokes[0]; |
| |
| if (interrupt[0] != null) |
| throw interrupt[0]; |
| |
| } |
| |
| /** |
| * Schedule the job that starts the progress monitor. |
| * @param dialog |
| * @param busy |
| */ |
| private void scheduleProgressMonitorJob(final ProgressMonitorJobsDialog dialog, final boolean[] busy) { |
| |
| final boolean [] defer = new boolean[1]; |
| defer[0] = false; |
| final UIJob updateJob = new UIJob(ProgressMessages.getString("ProgressManager.openJobName")) {//$NON-NLS-1$ |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| |
| //If there is a modal shell open then wait |
| Shell[] shells = getDisplay().getShells(); |
| for(int i = 0; i < shells.length; i ++){ |
| |
| //Do not stop for shells that will not |
| //block the user. |
| if(shells[i].isVisible()){ |
| int style = shells[i].getStyle(); |
| if((style & SWT.APPLICATION_MODAL |
| | style & SWT.SYSTEM_MODAL |
| | style & SWT.PRIMARY_MODAL) > 0){ |
| defer[0] = true; |
| return Status.CANCEL_STATUS; |
| } |
| } |
| } |
| |
| busy[0] = false; |
| |
| dialog.open(); |
| if (monitor.isCanceled()) |
| return Status.CANCEL_STATUS; |
| else |
| return Status.OK_STATUS; |
| } |
| }; |
| |
| updateJob.addJobChangeListener(new JobChangeAdapter(){ |
| /* (non-Javadoc) |
| * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.runtime.jobs.IJobChangeEvent) |
| */ |
| public void done(IJobChangeEvent event) { |
| |
| //If the platform is not runnin exit |
| if(!PlatformUI.isWorkbenchRunning()) |
| return; |
| //If we are deferring try again. |
| if(defer[0]){ |
| defer[0] = false; |
| updateJob.schedule(LONG_OPERATION_MILLISECONDS); |
| } |
| } |
| }); |
| |
| updateJob.schedule(LONG_OPERATION_MILLISECONDS); |
| } |
| |
| /** |
| * Shutdown the receiver. |
| */ |
| |
| public void shutdown(){ |
| this.listeners.clear(); |
| Platform.getJobManager().setProgressProvider(null); |
| Platform.getJobManager().removeJobChangeListener(this.changeListener); |
| } |
| } |