Home » Eclipse Projects » scout » Update the value of a field during its own execChangedValue() event.(org.eclipse.scout.rt.client.ui.form.fields.AbstractValueField.setValue(AbstractValueField.java:258) Loop detection in ***Field with value ***)

System-Jobs are Jobs that are not visible to the user (They are not displayed in the Job View).
(In our project, we have removed the "Job View" completely).

A typical Client-Sync-Job freezes the user interface, but after a delay.
With the SwtBusyHandler, it is possible to influence this behavior.
For example, it is possible to freeze the whole workbench or just a part of it.

One issue still need to be fixed:
When the form is opened (as view in my case), if the load operation (in ModifyHandler.execLoad()) takes a long time, the form do not have the focus when it appears.

This is a problem for our user.
- A form without focus cannot be closed with the "escape" KeyStroke we have in our forms
- Our users want to start working with the form, without having to TAB until the first field is reached.

The time the workbench is blocked, the focus request is ignored because the workbench filters the resulting OS-event from the SWT event queue. Actually, this is exactly the behaviour wanted to prevent the user from interacting with your application.

To solve your problem, you have to delay requesting the focus until the workbench is not blocked anymore. The easiest way to do that is by contributing your own implementation of SwtScoutForm#handleRequestFocusFromScout. There, one possible way could be to try to set the focus repeatedly as long as not being accepted by the UI. Obviously, this is not good practice and it would be way better to only set the focus once the workbench is not blocked anymore. If having a look at IBusyHandler, you may notice that there is a state-lock you can wait for to get awaken once the long-running operation completes. Unfortunately, this will not work very reliable because being the same trigger for also exiting the workbench blocking mode as well.

As a consequence, you have to introduce your own BusyJob and BusyHandler with your BusyHandler firing a notification once the blocking mode is exited which is shortly after the long-running operation completed. With that mechanism installed, you finally can wait for that event in SwtScoutForm#handleRequestFocusFromScout and only set the focus if being in non-blocked state.

In your previous post you presented a solution of how to block the workbench immediately when running a ClientSyncJob. Actually, this might lead to unexpected side effects. Imagine, you have a FormField that validates on every key. Every time you type in some characters, the workbench is blocked and the focus restored afterwards. However, the field is focused anew and you lose the current caret position. To face that problem, BusyJob is divided into 2 temporal timed phases: In the first phase, typically a busy cursor is present but the workbench not blocked yet. Only if the operation takes some more time, the workbench gets blocked. That is why I suggest you not to bypass the first phase but to reduce the duration to detect long-running operations instead.

Another point to consider is that when requesting the initial focus in AbstractFormHandler #execLoad, the Scout model is not attached to the UI yet, meaning that the focus cannot be applied yet. Once the model is attached to the UI, the event-history is looked for such a focus request which is applied if present. The point is that this history only keeps events for some maximum period of time (by default this is 5 seconds). To preserve events longer in history, you have to set a bigger expiration duration in AbstractForm#createEventHistory or more easily, simply request the focus at the very end of your execLoad method instead.

In the following, please find the changes required:

If you like to have that behavior in Scout, please file a bug on Bugzilla.