| /******************************************************************************* |
| * Copyright (c) 2004, 2006 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 - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.progress; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IProgressMonitorWithBlocking; |
| import org.eclipse.core.runtime.IStatus; |
| 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.jface.dialogs.IDialogConstants; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.progress.IProgressConstants; |
| import org.eclipse.ui.progress.WorkbenchJob; |
| |
| /** |
| * The ProgressMonitorFocusJobDialog is a dialog that shows progress for a |
| * particular job in a modal dialog so as to give a user accustomed to a modal |
| * UI a more famiiar feel. |
| */ |
| class ProgressMonitorFocusJobDialog extends ProgressMonitorJobsDialog { |
| Job job; |
| |
| /** |
| * Create a new instance of the receiver with progress reported on the job. |
| * |
| * @param parentShell |
| * The shell this is parented from. |
| */ |
| public ProgressMonitorFocusJobDialog(Shell parentShell) { |
| super(parentShell == null ? ProgressManagerUtil.getNonModalShell() |
| : parentShell); |
| setCancelable(true); |
| enableDetailsButton = true; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#cancelPressed() |
| */ |
| protected void cancelPressed() { |
| job.cancel(); |
| super.cancelPressed(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#configureShell(org.eclipse.swt.widgets.Shell) |
| */ |
| protected void configureShell(Shell shell) { |
| super.configureShell(shell); |
| shell.setText(job.getName()); |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) |
| */ |
| protected void createButtonsForButtonBar(Composite parent) { |
| Button runInWorkspace = createButton( |
| parent, |
| IDialogConstants.CLOSE_ID, |
| ProgressMessages.ProgressMonitorFocusJobDialog_RunInBackgroundButton, |
| true); |
| runInWorkspace.addSelectionListener(new SelectionAdapter() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) |
| */ |
| public void widgetSelected(SelectionEvent e) { |
| Rectangle shellPosition = getShell().getBounds(); |
| job.setProperty(IProgressConstants.PROPERTY_IN_DIALOG, |
| Boolean.FALSE); |
| finishedRun(); |
| ProgressManagerUtil.animateDown(shellPosition); |
| } |
| }); |
| runInWorkspace.setCursor(arrowCursor); |
| |
| cancel = createButton(parent, IDialogConstants.CANCEL_ID, |
| IDialogConstants.CANCEL_LABEL, false); |
| cancel.setCursor(arrowCursor); |
| |
| createDetailsButton(parent); |
| } |
| |
| /** |
| * Returns a listener that will close the dialog when the job completes. |
| * |
| * @return IJobChangeListener |
| */ |
| private IJobChangeListener createCloseListener() { |
| return new JobChangeAdapter() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.jobs.IJobChangeListener#done(org.eclipse.core.runtime.jobs.IJobChangeEvent) |
| */ |
| public void done(IJobChangeEvent event) { |
| // first of all, make sure this listener is removed |
| event.getJob().removeJobChangeListener(this); |
| if (!PlatformUI.isWorkbenchRunning()) { |
| return; |
| } |
| // nothing to do if the dialog is already closed |
| if (getShell() == null) { |
| return; |
| } |
| WorkbenchJob closeJob = new WorkbenchJob( |
| ProgressMessages.ProgressMonitorFocusJobDialog_CLoseDialogJob) { |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| Shell currentShell = getShell(); |
| if (currentShell == null || currentShell.isDisposed()) { |
| return Status.CANCEL_STATUS; |
| } |
| finishedRun(); |
| return Status.OK_STATUS; |
| } |
| }; |
| closeJob.setSystem(true); |
| closeJob.schedule(); |
| } |
| }; |
| } |
| |
| /** |
| * Return the ProgressMonitorWithBlocking for the receiver. |
| * |
| * @return IProgressMonitorWithBlocking |
| */ |
| private IProgressMonitorWithBlocking getBlockingProgressMonitor() { |
| return new IProgressMonitorWithBlocking() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String, |
| * int) |
| */ |
| public void beginTask(String name, int totalWork) { |
| final String finalName = name; |
| final int finalWork = totalWork; |
| runAsync(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| getProgressMonitor().beginTask(finalName, finalWork); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked() |
| */ |
| public void clearBlocked() { |
| runAsync(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| ((IProgressMonitorWithBlocking) getProgressMonitor()) |
| .clearBlocked(); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#done() |
| */ |
| public void done() { |
| runAsync(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| getProgressMonitor().done(); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double) |
| */ |
| public void internalWorked(double work) { |
| final double finalWork = work; |
| runAsync(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| getProgressMonitor().internalWorked(finalWork); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled() |
| */ |
| public boolean isCanceled() { |
| return getProgressMonitor().isCanceled(); |
| } |
| |
| /** |
| * Run the runnable as an asyncExec if we are already open. |
| * |
| * @param runnable |
| */ |
| private void runAsync(final Runnable runnable) { |
| |
| if (alreadyClosed) { |
| return; |
| } |
| Shell currentShell = getShell(); |
| |
| Display display; |
| if (currentShell == null) { |
| display = Display.getDefault(); |
| } else { |
| if (currentShell.isDisposed())// Don't bother if it has |
| // been closed |
| return; |
| display = currentShell.getDisplay(); |
| } |
| |
| display.asyncExec(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| if (alreadyClosed) { |
| return;// Check again as the async may come too |
| // late |
| } |
| Shell shell = getShell(); |
| if (shell != null && shell.isDisposed()) |
| return; |
| |
| runnable.run(); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus) |
| */ |
| public void setBlocked(IStatus reason) { |
| final IStatus finalReason = reason; |
| runAsync(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| ((IProgressMonitorWithBlocking) getProgressMonitor()) |
| .setBlocked(finalReason); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean) |
| */ |
| public void setCanceled(boolean value) { |
| // Just a listener - doesn't matter. |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String) |
| */ |
| public void setTaskName(String name) { |
| final String finalName = name; |
| runAsync(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| getProgressMonitor().setTaskName(finalName); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String) |
| */ |
| public void subTask(String name) { |
| final String finalName = name; |
| runAsync(new Runnable() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Runnable#run() |
| */ |
| public void run() { |
| getProgressMonitor().subTask(finalName); |
| } |
| }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.IProgressMonitor#worked(int) |
| */ |
| public void worked(int work) { |
| internalWorked(work); |
| } |
| }; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jface.window.Window#open() |
| */ |
| public int open() { |
| int result = super.open(); |
| |
| // add a listener that will close the dialog when the job completes. |
| IJobChangeListener listener = createCloseListener(); |
| job.addJobChangeListener(listener); |
| if (job.getState() == Job.NONE) { |
| // if the job completed before we had a chance to add |
| // the listener, just remove the listener and return |
| job.removeJobChangeListener(listener); |
| finishedRun(); |
| cleanUpFinishedJob(); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Opens this dialog for the duration that the given job is running. |
| * |
| * @param jobToWatch |
| * @param originatingShell |
| * The shell this request was created from. Do not block on this |
| * shell. |
| */ |
| public void show(Job jobToWatch, final Shell originatingShell) { |
| job = jobToWatch; |
| // after the dialog is opened we can get access to its monitor |
| job.setProperty(IProgressConstants.PROPERTY_IN_DIALOG, Boolean.TRUE); |
| |
| ProgressManager.getInstance().progressFor(job).addProgressListener( |
| getBlockingProgressMonitor()); |
| |
| setOpenOnRun(false); |
| aboutToRun(); |
| // start with a quick busy indicator. Lock the UI as we |
| // want to preserve modality |
| BusyIndicator.showWhile(PlatformUI.getWorkbench().getDisplay(), |
| new Runnable() { |
| public void run() { |
| try { |
| Thread |
| .sleep(ProgressManagerUtil.SHORT_OPERATION_TIME); |
| } catch (InterruptedException e) { |
| // Do not log as this is a common operation from the |
| // lock listener |
| } |
| } |
| }); |
| |
| WorkbenchJob openJob = new WorkbenchJob( |
| ProgressMessages.ProgressMonitorFocusJobDialog_UserDialogJob) { |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| |
| // if the job is done at this point, we don't need the dialog |
| if (job.getState() == Job.NONE) { |
| finishedRun(); |
| cleanUpFinishedJob(); |
| return Status.CANCEL_STATUS; |
| } |
| |
| // now open the progress dialog if nothing else is |
| if (!ProgressManagerUtil.safeToOpen( |
| ProgressMonitorFocusJobDialog.this, originatingShell)) { |
| return Status.CANCEL_STATUS; |
| } |
| |
| // Do not bother if the parent is disposed |
| if (getParentShell() != null && getParentShell().isDisposed()) { |
| return Status.CANCEL_STATUS; |
| } |
| |
| open(); |
| |
| return Status.OK_STATUS; |
| } |
| }; |
| openJob.setSystem(true); |
| openJob.schedule(); |
| |
| } |
| |
| /** |
| * The job finished before we did anything so clean up the finished |
| * reference. |
| */ |
| private void cleanUpFinishedJob() { |
| ProgressManager.getInstance().checkForStaleness(job); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createDialogArea(org.eclipse.swt.widgets.Composite) |
| */ |
| protected Control createDialogArea(Composite parent) { |
| Control area = super.createDialogArea(parent); |
| // Give the job info as the initial details |
| getProgressMonitor().setTaskName( |
| ProgressManager.getInstance().getJobInfo(this.job) |
| .getDisplayString()); |
| return area; |
| } |
| } |