aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin/event/ShortcutAction.java
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/com/vaadin/event/ShortcutAction.java')
-rw-r--r--server/src/com/vaadin/event/ShortcutAction.java373
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;
+ }
+}