blob: dca44f6d986606f9e487f0d89512d7309b25e9ae [file] [log] [blame]
<title>Showing Progress in Eclipse</title>
<table border="0" cellspacing="5" cellpadding="2" width="100%">
<tr>
<td align="left" valign="top" bgcolor="#0080c0"> <b><font color="#ffffff" face="Arial,Helvetica">
Eclipse 3.0 - Responsiveness Plan Item</font></b> </td>
</tr>
</table>
<h1>Showing progress in Eclipse 3.0</h1>
<p>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.</p>
<p>By: Jean-Michel Lemieux, 2003-09-24</p>
<p> Participants: Mike Wilson, Nick Edgar, John Arthorne, Tod Creasey</p>
<h2>Motivation</h2>
<p>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:</p>
<ul>
<li>Too much work is performed in the UI thread. This can cause the application
window to stop painting. Most of these problems are caused by progress APIs
that don't actually fork to perform the work (e.g. BusyIndicator, BusyIndicatorRunnableContext).</li>
<li>Progress is not shown consistently in the workbench. Should you use a progress
dialog, busy indicator, or use the workbench progress indicator?</li>
<li>Plugin developers would decide that an operation shouldn't take too long
and use a busy indicator. But the actual time an operation requires can very
and a busy indicator is not cancelable. To compound this, there are no APIs
in Eclipse to show a busy indicator while performing the actual work in another
thread.</li>
<li>Since there are so many progress APIs it's hard to provide a framework for
progress that would help the plugin developer and provide a more consistent
progress story in Eclipse.</li>
<li>The new Jobs API in org.eclipse.runtime is providing another way of looking
at progress. In 3.0 there will be model and non-model operations. Both require
progress and model operations can potentially be blocked by a or many non-model
operations. </li>
</ul>
<h2>Current APIs</h2>
<pre>
/************************
* 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);
</pre>
<h2>Elements of a solution</h2>
<p>Here is a list of progress issues that we would like to address in 3.0. </p>
<ol>
<li>Support for showing modal and non-modal progress in a cohesive way. Make
it easy for plugin developers to say &quot;run this operation&quot; 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.</li>
<li>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. </li>
<li>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.</li>
<li>Support for showing non-model progress when populating a viewer (e.g. tree
viewer, table viewer).</li>
</ol>
<h3>Cohesive modal and non-modal progress</h3>
<p>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.</p>
<p>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.</p>
<h3>Fine grain cancellation</h3>
<p>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:</p>
<ol>
<li>See that the modal operation is blocked by another operation. </li>
<li>Be able to cancel the modal operation.</li>
<li>Wait for the non-modal operation to finish and let the modal operation continue
afterwards.</li>
<li>(optionally) be able to cancel the non-modal operation that's blocking the
modal one.</li>
</ol>
<p>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.</p>
<p>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.</p>
<h3>Progress for non-modal operations affecting a view/editor</h3>
<p>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.</p>
<p>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:</p>
<pre>
view.getSite().schedule(aJob);
editorPart.getSite().schedule(aJob);</pre>
<p>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:</p>
<pre>aJob.schedule();</pre>
<h3>Progress for non-modal populating of a viewer</h3>
<p>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.</p>
<h3>When is it ok to do work in the UI thread?</h3>
<p>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.</p>
</BODY>
</html>