| <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 "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.</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> |