diff options
Diffstat (limited to 'server/src/com/vaadin/event/ShortcutAction.java')
-rw-r--r-- | server/src/com/vaadin/event/ShortcutAction.java | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/server/src/com/vaadin/event/ShortcutAction.java b/server/src/com/vaadin/event/ShortcutAction.java new file mode 100644 index 0000000000..c42dd731c8 --- /dev/null +++ b/server/src/com/vaadin/event/ShortcutAction.java @@ -0,0 +1,373 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.event; + +import java.io.Serializable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.vaadin.terminal.Resource; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.Panel; +import com.vaadin.ui.Window; + +/** + * Shortcuts are a special type of {@link Action}s used to create keyboard + * shortcuts. + * <p> + * The ShortcutAction is triggered when the user presses a given key in + * combination with the (optional) given modifier keys. + * </p> + * <p> + * ShortcutActions can be global (by attaching to the {@link Window}), or + * attached to different parts of the UI so that a specific shortcut is only + * valid in part of the UI. For instance, one can attach shortcuts to a specific + * {@link Panel} - look for {@link ComponentContainer}s implementing + * {@link Handler Action.Handler} or {@link Notifier Action.Notifier}. + * </p> + * <p> + * ShortcutActions have a caption that may be used to display the shortcut + * visually. This allows the ShortcutAction to be used as a plain Action while + * still reacting to a keyboard shortcut. Note that this functionality is not + * very well supported yet, but it might still be a good idea to give a caption + * to the shortcut. + * </p> + * + * @author Vaadin Ltd. + * @version + * @since 4.0.1 + */ +@SuppressWarnings("serial") +public class ShortcutAction extends Action { + + private final int keyCode; + + private final int[] modifiers; + + /** + * Creates a shortcut that reacts to the given {@link KeyCode} and + * (optionally) {@link ModifierKey}s. <br/> + * The shortcut might be shown in the UI (e.g context menu), in which case + * the caption will be used. + * + * @param caption + * used when displaying the shortcut visually + * @param kc + * KeyCode that the shortcut reacts to + * @param m + * optional modifier keys + */ + public ShortcutAction(String caption, int kc, int[] m) { + super(caption); + keyCode = kc; + modifiers = m; + } + + /** + * Creates a shortcut that reacts to the given {@link KeyCode} and + * (optionally) {@link ModifierKey}s. <br/> + * The shortcut might be shown in the UI (e.g context menu), in which case + * the caption and icon will be used. + * + * @param caption + * used when displaying the shortcut visually + * @param icon + * used when displaying the shortcut visually + * @param kc + * KeyCode that the shortcut reacts to + * @param m + * optional modifier keys + */ + public ShortcutAction(String caption, Resource icon, int kc, int[] m) { + super(caption, icon); + keyCode = kc; + modifiers = m; + } + + /** + * Used in the caption shorthand notation to indicate the ALT modifier. + */ + public static final char SHORTHAND_CHAR_ALT = '&'; + /** + * Used in the caption shorthand notation to indicate the SHIFT modifier. + */ + public static final char SHORTHAND_CHAR_SHIFT = '_'; + /** + * Used in the caption shorthand notation to indicate the CTRL modifier. + */ + public static final char SHORTHAND_CHAR_CTRL = '^'; + + // regex-quote (escape) the characters + private static final String SHORTHAND_ALT = Pattern.quote(Character + .toString(SHORTHAND_CHAR_ALT)); + private static final String SHORTHAND_SHIFT = Pattern.quote(Character + .toString(SHORTHAND_CHAR_SHIFT)); + private static final String SHORTHAND_CTRL = Pattern.quote(Character + .toString(SHORTHAND_CHAR_CTRL)); + // Used for replacing escaped chars, e.g && with & + private static final Pattern SHORTHAND_ESCAPE = Pattern.compile("(" + + SHORTHAND_ALT + "?)" + SHORTHAND_ALT + "|(" + SHORTHAND_SHIFT + + "?)" + SHORTHAND_SHIFT + "|(" + SHORTHAND_CTRL + "?)" + + SHORTHAND_CTRL); + // Used for removing escaped chars, only leaving real shorthands + private static final Pattern SHORTHAND_REMOVE = Pattern.compile("([" + + SHORTHAND_ALT + "|" + SHORTHAND_SHIFT + "|" + SHORTHAND_CTRL + + "])\\1"); + // Mnemonic char, optionally followed by another, and optionally a third + private static final Pattern SHORTHANDS = Pattern.compile("(" + + SHORTHAND_ALT + "|" + SHORTHAND_SHIFT + "|" + SHORTHAND_CTRL + + ")(?!\\1)(?:(" + SHORTHAND_ALT + "|" + SHORTHAND_SHIFT + "|" + + SHORTHAND_CTRL + ")(?!\\1|\\2))?(?:(" + SHORTHAND_ALT + "|" + + SHORTHAND_SHIFT + "|" + SHORTHAND_CTRL + ")(?!\\1|\\2|\\3))?."); + + /** + * Constructs a ShortcutAction using a shorthand notation to encode the + * keycode and modifiers in the caption. + * <p> + * Insert one or more modifier characters before the character to use as + * keycode. E.g <code>"&Save"</code> will make a shortcut responding to + * ALT-S, <code>"E^xit"</code> will respond to CTRL-X.<br/> + * Multiple modifiers can be used, e.g <code>"&^Delete"</code> will respond + * to CTRL-ALT-D (the order of the modifier characters is not important). + * </p> + * <p> + * The modifier characters will be removed from the caption. The modifier + * character is be escaped by itself: two consecutive characters are turned + * into the original character w/o the special meaning. E.g + * <code>"Save&&&close"</code> will respond to ALT-C, and the caption will + * say "Save&close". + * </p> + * + * @param shorthandCaption + * the caption in modifier shorthand + */ + public ShortcutAction(String shorthandCaption) { + this(shorthandCaption, null); + } + + /** + * Constructs a ShortcutAction using a shorthand notation to encode the + * keycode a in the caption. + * <p> + * This works the same way as {@link #ShortcutAction(String)}, with the + * exception that the modifiers given override those indicated in the + * caption. I.e use any of the modifier characters in the caption to + * indicate the keycode, but the modifier will be the given set.<br/> + * E.g + * <code>new ShortcutAction("Do &stuff", new int[]{ShortcutAction.ModifierKey.CTRL}));</code> + * will respond to CTRL-S. + * </p> + * + * @param shorthandCaption + * @param modifierKeys + */ + public ShortcutAction(String shorthandCaption, int[] modifierKeys) { + // && -> & etc + super(SHORTHAND_ESCAPE.matcher(shorthandCaption).replaceAll("$1$2$3")); + // replace escaped chars with something that won't accidentally match + shorthandCaption = SHORTHAND_REMOVE.matcher(shorthandCaption) + .replaceAll("\u001A"); + Matcher matcher = SHORTHANDS.matcher(shorthandCaption); + if (matcher.find()) { + String match = matcher.group(); + + // KeyCode from last char in match, uppercase + keyCode = Character.toUpperCase(matcher.group().charAt( + match.length() - 1)); + + // Given modifiers override this indicated in the caption + if (modifierKeys != null) { + modifiers = modifierKeys; + } else { + // Read modifiers from caption + int[] mod = new int[match.length() - 1]; + for (int i = 0; i < mod.length; i++) { + int kc = match.charAt(i); + switch (kc) { + case SHORTHAND_CHAR_ALT: + mod[i] = ModifierKey.ALT; + break; + case SHORTHAND_CHAR_CTRL: + mod[i] = ModifierKey.CTRL; + break; + case SHORTHAND_CHAR_SHIFT: + mod[i] = ModifierKey.SHIFT; + break; + } + } + modifiers = mod; + } + + } else { + keyCode = -1; + modifiers = modifierKeys; + } + } + + /** + * Get the {@link KeyCode} that this shortcut reacts to (in combination with + * the {@link ModifierKey}s). + * + * @return keycode for this shortcut + */ + public int getKeyCode() { + return keyCode; + } + + /** + * Get the {@link ModifierKey}s required for the shortcut to react. + * + * @return modifier keys for this shortcut + */ + public int[] getModifiers() { + return modifiers; + } + + /** + * Key codes that can be used for shortcuts + * + */ + public interface KeyCode extends Serializable { + public static final int ENTER = 13; + + public static final int ESCAPE = 27; + + public static final int PAGE_UP = 33; + + public static final int PAGE_DOWN = 34; + + public static final int TAB = 9; + + public static final int ARROW_LEFT = 37; + + public static final int ARROW_UP = 38; + + public static final int ARROW_RIGHT = 39; + + public static final int ARROW_DOWN = 40; + + public static final int BACKSPACE = 8; + + public static final int DELETE = 46; + + public static final int INSERT = 45; + + public static final int END = 35; + + public static final int HOME = 36; + + public static final int F1 = 112; + + public static final int F2 = 113; + + public static final int F3 = 114; + + public static final int F4 = 115; + + public static final int F5 = 116; + + public static final int F6 = 117; + + public static final int F7 = 118; + + public static final int F8 = 119; + + public static final int F9 = 120; + + public static final int F10 = 121; + + public static final int F11 = 122; + + public static final int F12 = 123; + + public static final int A = 65; + + public static final int B = 66; + + public static final int C = 67; + + public static final int D = 68; + + public static final int E = 69; + + public static final int F = 70; + + public static final int G = 71; + + public static final int H = 72; + + public static final int I = 73; + + public static final int J = 74; + + public static final int K = 75; + + public static final int L = 76; + + public static final int M = 77; + + public static final int N = 78; + + public static final int O = 79; + + public static final int P = 80; + + public static final int Q = 81; + + public static final int R = 82; + + public static final int S = 83; + + public static final int T = 84; + + public static final int U = 85; + + public static final int V = 86; + + public static final int W = 87; + + public static final int X = 88; + + public static final int Y = 89; + + public static final int Z = 90; + + public static final int NUM0 = 48; + + public static final int NUM1 = 49; + + public static final int NUM2 = 50; + + public static final int NUM3 = 51; + + public static final int NUM4 = 52; + + public static final int NUM5 = 53; + + public static final int NUM6 = 54; + + public static final int NUM7 = 55; + + public static final int NUM8 = 56; + + public static final int NUM9 = 57; + + public static final int SPACEBAR = 32; + } + + /** + * Modifier key constants + * + */ + public interface ModifierKey extends Serializable { + public static final int SHIFT = 16; + + public static final int CTRL = 17; + + public static final int ALT = 18; + + public static final int META = 91; + } +} |