Recently, I was asked how to programmatically open the calendar popup of a date field. Actually, Scout does not provide such functionality out of the box and it is not planned to introduce such functionality in the near future.
But there exists a quite good workaround to accomplish that goal by triggering the 'F2'-keystroke which in turn opens the popup. By now there is no Keystroke-Scout-API to do so but it's easy to do yourself. Since keystrokes are UI-specific, the idea is to provide a keystroke Scout-OSGi service from within your UI-Plugins which in turn can be accessed from within your Client-Plug-In.
In the following, I'll present you the steps required to implement that service in Swing-, SWT- and RAP-UI.
1. Define the Keystroke-Service-API in your Client-Plugin:
/**
* Service to programmatically trigger keystrokes.
*/
public interface IKeyStrokeService extends IService {
enum KeyStroke {
F2;
}
/**
* Triggers the given keystroke on the currently focused field.
*/
void triggerKeyStroke(KeyStroke keyStroke);
}
2. In your Form, you can invoke that Service:
/**
* Opens the date popup programmatically.
*/
private void openDatePopup() {
// Make the widget the focus owner to handle the keystroke.
getDateField().requestFocus();
// Wait for the focus to be requested. This is necessary because requesting the focus is executed asynchronously.
try {
Thread.sleep(100L);
}
catch (InterruptedException e) {
LOG.warn("Failed to wait for the widget to be focused.");
}
// Trigger the keystroke.
SERVICES.getService(IKeyStrokeService.class).triggerKeyStroke(KeyStroke.F2);
}
3a. Provide an implementation for the Swing-UI:
public class SwingKeyStrokeService extends AbstractService implements IKeyStrokeService {
private static final IScoutLogger LOG = ScoutLogManager.getLogger(SwingKeyStrokeService.class);
@Override
public void triggerKeyStroke(KeyStroke keyStroke) {
try {
new Robot().keyPress(toSwingKeyStroke(keyStroke));
}
catch (AWTException e) {
LOG.warn("Failed to trigger keystroke.", e);
}
}
private static int toSwingKeyStroke(KeyStroke keyStroke) {
switch (keyStroke) {
case F2:
return KeyEvent.VK_F2;
default:
throw new IllegalArgumentException(String.format("KeyStroke '%s' not supported.", keyStroke));
}
}
}
3b. Register your Service in the Swing-UI plugin.xml:
<extension point="org.eclipse.scout.service.services">
<service
class="org.yourapp.ui.swing.SwingKeyStrokeService"
factory="org.eclipse.scout.service.DefaultServiceFactory">
</service>
</extension>
4a. Provide an implementation for the SWT-UI:
public class SwtKeyStrokeService extends AbstractService implements IKeyStrokeService {
private static final IScoutLogger LOG = ScoutLogManager.getLogger(SwtKeyStrokeService.class);
@Override
public void triggerKeyStroke(KeyStroke keyStroke) {
Event event = new Event();
event.display = Display.getDefault();
event.type = SWT.KeyUp;
event.keyCode = toSwtKeyStroke(keyStroke);
Display.getDefault().post(event);
}
private static int toSwtKeyStroke(KeyStroke keyStroke) {
switch (keyStroke) {
case F2:
return SWT.F2;
default:
throw new IllegalArgumentException(String.format("KeyStroke '%s' not supported.", keyStroke));
}
}
}
4b. Register your Service in the SWT-UI plugin.xml:
<extension point="org.eclipse.scout.service.services">
<service
class="org.yourapp.ui.swt.SwtKeyStrokeService"
factory="org.eclipse.scout.service.DefaultServiceFactory">
</service>
</extension>
5a. Provide an implementation for the RAP-UI:
public class RwtKeyStrokeService extends AbstractService implements IKeyStrokeService {
private static final IScoutLogger LOG = ScoutLogManager.getLogger(RwtKeyStrokeService.class);
@Override
public void triggerKeyStroke(KeyStroke keyStroke) {
final IRwtEnvironment environment = (IRwtEnvironment) ClientSession.get().getData(IRwtEnvironment.ENVIRONMENT_KEY);
final Display display = environment.getDisplay();
final Event event = new Event();
event.display = display;
event.type = SWT.KeyUp;
event.keyCode = toSwtKeyStroke(keyStroke);
display.syncExec(new Runnable() {
@Override
public void run() {
display.getFocusControl().notifyListeners(SWT.KeyDown, event);
}
});
}
private static int toSwtKeyStroke(KeyStroke keyStroke) {
switch (keyStroke) {
case F2:
return SWT.F2;
default:
throw new IllegalArgumentException(String.format("KeyStroke '%s' not supported.", keyStroke));
}
}
}
5b. Register your Service in the RAP-UI plugin.xml:
<extension point="org.eclipse.scout.service.services">
<service
class="org.yourapp.ui.rap.RwtKeyStrokeService"
factory="org.eclipse.scout.service.DefaultServiceFactory">
</service>
</extension>