Eclipse 3.0 - Responsiveness Plan Item

Showing progress in Eclipse 3.0

This document outlines the initial thoughts on progress support in Eclipse 3.0. It's basically a summary of the discussions we have had around this subject.

By: Jean-Michel Lemieux, 2003-09-24

Participants: Mike Wilson, Nick Edgar, John Arthorne, Tod Creasey

Motivation

In Eclipse 2.1 long running operations blocked the user interface via a progress dialog, busy cursor, or a progress indicator shown in another context (e.g. workbench, wizard). There are several APIs used by plugin developers for this purpose. There are actually too many choices for plugin developers to make in deciding how to show progress. This has resulted in the following symptoms:

Current APIs

/************************
 * Modal Progress APIs
 ************************/


/* Shows a busy cursor and runs the runnable in the current thread. */
org.eclipse.swt.custom.BusyIndicator::showWhile(Display display, Runnable runnable);



/* Allows an operation to run either in the current thread or in another thread. If the
   current thread is the UI thread the event queue is read and dispatched. */
org.eclipse.jface.operations.ModalContext::run(run(IRunnableWithProgress operation, boolean fork, IProgressMonitor monitor, Display display);



/* Is implemented by several contexts: workbench window, progress dialog, busy indicator
   wizards. Allows to run an operation in the current thread or in another thread while
   showing progress in the given context. The user can decide if the operation can be
   cancelled. */
org.eclipse.jface.operations.IRunnableContext::run(boolean fork, boolean cancelable, IRunnableWithProgress runnable);


/************************
 * Non-Modal Progress APIs
 ************************/


/* Runs an operation in a separate thread showing progress via a registered progress service. The
   Job can be cancelled via the progress monitor. */
org.eclipse.runtime.jobs.Job::run(IProgressMonitor monitor);

Elements of a solution

Here is a list of progress issues that we would like to address in 3.0.

  1. Support for showing modal and non-modal progress in a cohesive way. Make it easy for plugin developers to say "run this operation" without having to decide about the particular mechanism should be used to display progress. This would allow the platform to implement a standard progress strategy.
  2. Support for allowing the user to cancel a model operation that is blocked by a non-modal operation. This can happen when a modal operation cannot run until a non-modal operation completes.
  3. Support for showing non-modal progress in a view/editor. This means that when an non-modal operation affects a view/editor the user should get feedback that the views is doing work.
  4. Support for showing non-model progress when populating a viewer (e.g. tree viewer, table viewer).

Cohesive modal and non-modal progress

Instead of the user having to decide where and how to show progress, the platform should provide a single method for displaying modal progress. This single progress API could enforce that work is never performed in the UI thread, fine grain cancellation is supported, and progress is shown consistently.

Summary: We would require a single API for running a modal operation. Can have the same parameters as IRunnableContext and existing implementations of IRunnableContext could delegate to a new progress service. In addition, wizards could continue to be a IRunnableContext but should support showing the fine grain cancellation hint. A single API would allow the platform UI team to experiment with different ways of showing progress and have it apply to all operations. For example, you could imagine that a good solution for a common progress story to include a combined busy cursor with a delayed progress indicator.

Fine grain cancellation

It's now possible to any operation that modifies the workspace to block for an unknown amount of time while a non-modal operation has a lock on the workspace or resources required by the modal operation. The user should minimally:

  1. See that the modal operation is blocked by another operation.
  2. Be able to cancel the modal operation.
  3. Wait for the non-modal operation to finish and let the modal operation continue afterwards.
  4. (optionally) be able to cancel the non-modal operation that's blocking the modal one.

The notification of a modal operation being blocked by a non-modal must be smart and non-intrusive. It is quite possible that blocking is resolved quickly and the user should not have to know that there was a small delay in starting the operation. For example, it wouldn't be good to pop-up a dialog every time a modal operation is blocked.

To support this an extension to IProgressMonitor will have to be created to allow the resources plugin to notify the progress service that an operation is being blocked.

Progress for non-modal operations affecting a view/editor

With more plugins using non-modal operations to update views and editors it is useful for the user to understand when a view/editors content is being changed by a non-modal operation. We should add an API for associated a non-modal operation (e.g. a org.eclipse.runtime.Job) with a IWorkbenchPartSite. This would allow the platform UI team to experiment with methods of showing non-modal progress in a view or editor.

For scheduling a non-modal operation the developer would have to decide if the job affects a view. And if it does than call something similar to:

view.getSite().schedule(aJob);
editorPart.getSite().schedule(aJob);

And if a non-modal operation doesn't affect a particular view, it would be scheduled and progress shown via the standard non-modal progress support:

aJob.schedule();

Progress for non-modal populating of a viewer

When a non-modal operation is populating a viewer (e.g. fetching children for a tree node, or fetching members for a table) it may be useful to show the user a hint that the viewer is not showing the complete results. For a tree viewer it may be useful to show the progress hint for each sub-folder (e.g. the 'pending' placeholder in the CVS repositories view) and for a table viewer simply clearing the view than showing the non-modal progress for a view/editor.

When is it ok to do work in the UI thread?

If the work can be run in under 100ms and there are no workspace changes made. If either of these requirements are not met, than work should be performed in another thread. For this reason, I recommend that the new progress API remove the fork option and automatically run the operation in another thread while processing the SWT events queue. This implies that the operations that satisfy the conditions for running in the UI thread can continue to use the org.eclipse.swt.custom.BusyIndicator.showWhile() method for displaying progress.