| Summary: | [Progress] Improve IProgressService#busyCursorWhile() API | ||
|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Benjamin Pasero <bpasero> |
| Component: | UI | Assignee: | Platform UI Triaged <platform-ui-triaged> |
| Status: | CLOSED WONTFIX | QA Contact: | |
| Severity: | normal | ||
| Priority: | P5 | CC: | blizzy-keyword-eclipse_bugs.ba215a |
| Version: | 3.3 | Keywords: | helpwanted |
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows XP | ||
| Whiteboard: | stalebug | ||
|
Description
Benjamin Pasero
If you don't use the progress dialog why don't you just use BusyIndicator#showWhile Well I am having this problem: There is a operation I am performing which in some cases exceeds a certain amount of time. In any case I would like to use the Busy-Indicator to show some feedback to the user that something is happening. However, the BusyIndicator-API only allows a runnable for the UI-Thread, otherwise its not working. I would like to use the Busy-Indicator while the runnable is running in a Background-Job. This allows to still being able to play with the UI while the operation is running. Either showing a Progress-Dialog or not is something different for me. If I want to show the Dialog, it should in addition allow me to set wether the operation is cancelable or not. Ben Btw there is a cursor which goes into the direction I am talking about: CURSOR_APPSTARTING. On Windows this cursor is showing the sandbox in a small version together with the Point-Arrow. That indicates that something is running in the background, while the UI is still responsive. Ben Actually maybe I was not very clear in this report. What I am basically looking for is API to: - Run something in a background-job to not block the UI-Thread - show lightweight feedback / progress (ideally just a Busy-Cursor). Ben I think you are clear Ben - all you want is the existing public void showInDialog(Shell shell, Job job) with no dialog after 250ms.
Have a look at the code in ProgressMonitorFocusJobDialog#show(Job jobToWatch, final Shell originatingShell). What we do there is lock the UI for 250ms when running the job and then open the dialog if the job is still running.
Couldn't you just do something like (Sorry about the crappy formatting):
BusyIndicator.showWhile(PlatformUI.getWorkbench().getDisplay(),
new Runnable() {
public void run() {
try {while(job.isRunning()){
Thread
.sleep(ProgressManagerUtil.SHORT_OPERATION_TIME);}
} catch (InterruptedException e) {
// Do not log as this is a common operation from the
// lock listener
}
}
});
(In reply to comment #5) > I think you are clear Ben - all you want is the existing public void > showInDialog(Shell shell, Job job) with no dialog after 250ms. Yes I think thats exactly what I want. Thanks for pointing me to that Method, I did not see it when I first looked. > > Have a look at the code in ProgressMonitorFocusJobDialog#show(Job jobToWatch, > final Shell originatingShell). What we do there is lock the UI for 250ms when > running the job and then open the dialog if the job is still running. > > Couldn't you just do something like (Sorry about the crappy formatting): > > BusyIndicator.showWhile(PlatformUI.getWorkbench().getDisplay(), > new Runnable() { > public void run() { > try {while(job.isRunning()){ > Thread > > .sleep(ProgressManagerUtil.SHORT_OPERATION_TIME);} > } catch (InterruptedException > e) { > // Do not log as this > is a common operation from the > // lock listener > } > } > }); > I will try that once I am back from work and give feedback then. Ben Actually it turns out that these solutions are still blocking the UI-Thread. Here is a Snippet which is what I was looking for. Its a modified-version of BusyIndicator#showWhile which shows the Waiting-Cursor (actually the one with small sandbox) as long as the operation is running in the background:
public static void runInBackgroundWithBusyIndicator(final Runnable runnable) {
final Display display = Display.getCurrent();
final Integer busyId = new Integer(nextBusyId++);
/* Guard against Illegal-Thread-Access */
if (display == null)
throw new IllegalStateException("Method was not called from the UI-Thread!");
/* Set the Cursor */
Cursor cursor = display.getSystemCursor(SWT.CURSOR_APPSTARTING);
Shell[] shells = display.getShells();
for (int i = 0; i < shells.length; i++) {
Integer id = (Integer) shells[i].getData(BUSYID_NAME);
if (id == null) {
shells[i].setCursor(cursor);
shells[i].setData(BUSYID_NAME, busyId);
}
}
/* Start the Runnable in the Background Job */
Job job = new Job("") {
@Override
protected IStatus run(IProgressMonitor monitor) {
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
runnable.run();
}
});
/* Reset the Cursor from the UIJob */
UIJob uiJob = new UIJob("") {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
Shell[] shells = display.getShells();
for (int i = 0; i < shells.length; i++) {
Integer id = (Integer) shells[i].getData(BUSYID_NAME);
if (id == busyId) {
shells[i].setCursor(null);
shells[i].setData(BUSYID_NAME, null);
}
}
return Status.OK_STATUS;
}
};
uiJob.setSystem(true);
uiJob.schedule();
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
Ben
So you still want to process UI events during your busy indicator? This is actually a lot harder to program for as it is possible for other code to get run that might mess up your operation. This is of course fine if you have control over the plug-ins in your application but can be hard to get right in a system like the SDK where people plug-in all of the time. Also the UIJob might be run right away here so your cursors would be set immediately potentially. I suspect I am missing some ideas here so please fill me in if so. (In reply to comment #8) > So you still want to process UI events during your busy indicator? This is > actually a lot harder to program for as it is possible for other code to get > run that might mess up your operation. I totally agree. There are a lot of cases where this is not a good idea. The operation we have is not a long-op, its only taking like 1 second. Thats not really enough for the user to mess up the operation, but still notable if the UI-Thread is blocked meanwhile. Its also too short to bring up a Modal Dialog. > > This is of course fine if you have control over the plug-ins in your > application but can be hard to get right in a system like the SDK where people > plug-in all of the time. Right. > > Also the UIJob might be run right away here so your cursors would be set > immediately potentially. Is that a problem? I think BusyIndicator#showWhile would to the same if the runnable was very short-running. > > I suspect I am missing some ideas here so please fill me in if so. > Aside from all the discussion here, I'd like to express my vote on the cancelable parameter for IProgressService.busyCursorWhile(). Perhaps IProgressServiceExt could be introduced that has this method. Please feel free to attach a patch This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug. If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie. |