Nifty Progress Reporting in RCP Applications

Nifty Progress Reporting in RCP Applications

I don’t (always) like the ways Eclipse provides me to do long running operations. So I created another way with a nicer UI.

With the Jobs framework the Eclipse IDE provides some means for long running operations. The Jobs framework is able to run tasks in a parallel fashion and queue the rest, while providing user feedback with progress monitors. Other RCP applications have different needs when doing long running operations.

Specifically the Job frameworks UI feedback is not always what an RCP application wants. Sometimes I find that I’d rather prevent the user from clicking in the UI than queue more jobs. This happens for example if the user action triggers a network access that might take a while. There is no point in accepting the same user action again. So I want to provide a nice feedback mechanism to the user that their click is being processed.

Eclipse provides a progress monitor dialog. It’s a modal dialog that shows a process to the user and prevents her from clicking in the workbench. Personally, I don’t think it’s very appealing. Also, it’s not what I want… while I want some view being blocked often other views should stay operable.

swtscreensnapz035

I don’t know anything that means my use case from Eclipse so I created a few classes myself that take care of a presentable way to block workbench parts. Basically it’s a transparent shell that lays itself over a given control and displays a SWT ProgressIndicator widget. It responds to the controls re-size, move and disposal events… and looks quite neat! Way better than the progress modal dialog, and it leaves it up to the programmer which part of the UI should be blocked.

From the programmers point of view, I took the approach we find in Eclipse all the time: The programmer has to implement some “I..Runner” interface that is custom to my API.
It contains a run method that takes an IProgressMonitor and is called outside the UI thread.
My aim was to make the different steps during and after the long running operation as clear as possible to the programmer and reduce their need for inner classes. Unlike the Eclipse API I don’t think that it’s the users responsibility to sync back into the UI thread. This use case is common and creates unnecessary bloat in the source code. Therefore I provide 2 methods that are called within the UI thread after the operation is done, one for doing the actual feedback for the user and one for exception handling (if necessary).
[code lang=’java’]
public interface IResponsiveRunner {

/**
* called from without the UI Thread
*/
public abstract void runOutsideUIThread( final IProgressMonitor monitor ) throws Exception;

/**
* called after {@link #runOutsideUIThread(IProgressMonitor)} from within the UI Thread
*/
public abstract void uiFeedbackAfterRun();

/**
* Called within the UI thread. This method is called if an error occurs during execute before
* {@link #uiFeedbackAfterRun()} is called.
* @param caught
*/
public abstract void handleException( final Exception caught );
}
[/code]
This is what a programmer has to implement. Starting the nifty progress report is very similar to using a progress monitor dialog, instantiate and run:

[code lang=’java’]
new NiftyProgress( myResponsiveRunner, new TransparentUIBlocker( control ) ).run();
[/code]
The TransparentUIBlocker is the class that does the actual blocking. It’s passed in under a generic IUIBlocker interface that might have other implementations.

So, as a programmer, you provide an implementation of the IResponsiveRunner and point to a control that should be blocked, and you’re done. Nifty feedback to the user.

I attached a zip with plug-in projects with the classes and a small application that makes use of them. Use it, it’s EPL.

Oh, and if someone can tell me how to get notified if a view is hidden behind another one in a view stack, please do.

10 Comments
  • Posted at 11:01, 2009-03-18

    Hi,

    It’s great, thanks. Your TransparentUIBlocker is a kind of glasspane of Swing.

    There is a problem when a not Eclipse window is in front of view under long running operations. The TransparentUIBlocker shell can be always visible and not the RCP application shell.

    Mickael

  • Yuri Schimke
    Posted at 11:28, 2009-03-18

    For finding out about part visibility events

    https://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IPartListener2.html

    To find out if a particular view is currently visible (Without events)

    getSite().getPage().isPartVisible(this);

  • Posted at 12:10, 2009-03-18

    Nice, I really like the idea, and it looks quite good and intuitive.

    The implementation details in the Runner interface are rather neat as well, allowing throwing Exceptions of any kind and splitting the exception handling concerns. Plus separating UI and non-UI code is a thoughtful touch as well. That is usually the usage pattern: Some long running process (network access, complex calculation) followed by a short UI-update.
    It’d would probably be helpful to have an adapter implementation to use plain old IRunnableWithProgress instances.

    Also: code in zip attachments? That’s so 20th century 😉 A perfect project to put up on github or bitbucket!

  • Posted at 13:39, 2009-03-18

    Hmm, I think the statement that jobs mainly target for file based RCP clients is wrong. We use jobs heavily on the server side and in RCP applications for non-file based stuff.

    The is standard API for rendering a part’s busy state while a job is running IWorkbenchSiteProgressService. I think a smarter way of doing it would be to extend the implementation to allow RCP applications switching the busy feedback. One implementation could be the semi-transparent overlay you provide (which looks cool btw).

    -Gunnar

  • Chris
    Posted at 16:19, 2009-03-18

    Keulkeul’s issue also seems to happen in linux (specifically Ubuntu 8.10). I minimize the rcp app and the pane is still visible.

    Otherwise, this looks pretty neat.

    -Chris

  • Remy Chi Jian Suen
    Posted at 16:11, 2009-03-18

    Hi Matthias, I would suggest filing an enhancement request against Platform/UI for the possibility of integrating this into the Platform itself if you haven’t done so already.

  • Govind
    Posted at 16:34, 2009-12-01

    Hi

    This is very good example..
    I wanred to why when i give IProgressMonitor.UNKNOWN it doesnt show any progress.

    Thanks and Regards
    Govind R

  • Govind
    Posted at 19:04, 2009-12-01

    ya i to have Keulkeul’s issue .. i have on windows xp and 7

    Possible way to overcome..

  • Paul
    Posted at 15:09, 2011-05-25

    Firstly i would like to thanks for the code, it helped me a lot in my project.

    As a token of my gratitude i can solve Keulkeul’s problem.

    It’s maybe to late for him but let it be for others like me to know 😉

    You have to make a simple change in the TransparentUIBlocker class.

    Yust change this:
    shell = new Shell( parent.getDisplay(), SWT.ON_TOP
    | SWT.MODELESS
    | SWT.NO_FOCUS );
    Into:
    shell = new Shell( parent.getShell(), SWT.MODELESS | SWT.NO_FOCUS );

    And all is going to be yust fine, cheers!

    P.S. I only tested it on windows 7