Shortcut keys can be defined as actions using the
ShortcutAction
class. To handle key presses, you need
to define an action handler by implementing the Handler
interface. The interface has two methods that you need to implement:
getActions()
and
handleAction()
.
The getActions()
interface method must return an
array of Action
objects for the component specified
with the second parameter for the method, the sender
of
an action. For a keyboard shortcut, you use a
ShortcutAction
. The implementation of the method should
look somewhat as follows:
public Action[] getActions(Object target, Object sender) { Action[] actions = new Action[1]; // Set the action for the requested component if (sender == ok) { // Bind the unmodified Enter key to the Ok button. actions[0] = new ShortcutAction("Default key", ShortcutAction.KeyCode.ENTER, null); } else if (sender == cancel) { // Bind "C" key modified with Alt to the Cancel button. actions[0] = new ShortcutAction("Alt+C", ShortcutAction.KeyCode.C, new int[] { ShortcutAction.ModifierKey.ALT}); } else return null; return actions; }
The method takes a symbolic caption for the action; this is largely irrelevant
for shortcut actions. The second parameter is the keycode, as defined in
ShortcutAction.KeyCode
interface. Currently, the
following keycodes are allowed:
Function keys
Control keys
Number pad keys
Arrow keys
Other movement keys
The third parameter is an array of modifier keys, as defined in the
ShortcutAction.ModifierKey
interface. The
following modifier keys are allowed: ALT
,
CTRL
, and SHIFT
. The modifier
keys can be combined; for example, the following defines shortcut key
combination
Ctrl-Shift-S:
ShortcutAction("Ctrl+Shift+S", ShortcutAction.KeyCode.S, new int[] { ShortcutAction.ModifierKey.CTRL, ShortcutAction.ModifierKey.SHIFT});
The following example demonstrates the definition of a default button for a user interface, as well as a normal shortcut key, Alt-C for clicking the button.
import com.itmill.toolkit.event.Action; import com.itmill.toolkit.event.ShortcutAction; import com.itmill.toolkit.event.Action.Handler; import com.itmill.toolkit.ui.*; public class DefaultButtonExample extends CustomComponent implements Handler { // Define and create user interface components Panel panel = new Panel("Login"); VerticalLayout formlayout = new VerticalLayout(); TextField username = new TextField("Username"); TextField password = new TextField("Password"); HorizontalLayout buttons = new HorizontalLayout(); // Create buttons and define their listener methods. Here we use parameterless // methods so that we can use same methods for both click events and keyboard // actions. Button ok = new Button("OK", this, "okHandler"); Button cancel = new Button("Cancel", this, "cancelHandler"); public DefaultButtonExample() { // Set up the user interface setCompositionRoot(panel); panel.addComponent(formlayout); formlayout.addComponent(username); formlayout.addComponent(password); formlayout.setStyle("form"); formlayout.addComponent(buttons); buttons.addComponent(ok); buttons.addComponent(cancel); // Set focus to username username.focus(); // Set this object as the action handler for actions related to the Ok // and Cancel buttons. ok.addActionHandler(this); cancel.addActionHandler(this); } /** * Retrieve actions for a specific component. This method will be called for each * object that has a handler; in this example the Ok and Cancel buttons. **/ public Action[] getActions(Object target, Object sender) { Action[] actions = new Action[1]; // Set the action for the requested component if (sender == ok) { // Bind the unmodified Enter key to the Ok button. actions[0] = new ShortcutAction("Default key", ShortcutAction.KeyCode.ENTER, null); } else if (sender == cancel) { // Bind "C" key modified with Alt to the Cancel button. actions[0] = new ShortcutAction("Alt+C", ShortcutAction.KeyCode.C, new int[] { ShortcutAction.ModifierKey.ALT}); } else return null; return actions; } /** * Handle actions received from keyboard. This simply directs the actions to * the same listener methods that are called with ButtonClick events. **/ public void handleAction(Action action, Object sender, Object target) { if (target == ok) this.okHandler(); if (target == cancel) this.cancelHandler(); } public void okHandler() { // Do something: report the click formlayout.addComponent(new Label("OK clicked")); } public void cancelHandler() { // Do something: report the click formlayout.addComponent(new Label("Cancel clicked")); } }
Notice that the keyboard actions are handled from the entire page. This can
cause problems if you have components that require a certain key. For example,
multi-line TextField
requires the
Enter key. There is currently no way to filter the shortcut
actions out while the focus is inside some specific component, so you need to
avoid such conflicts.