From e88f71dd6d1d7634e3a90a7e53859ff6dc028e21 Mon Sep 17 00:00:00 2001 From: Anna Koskinen Date: Thu, 16 Oct 2014 13:37:48 +0300 Subject: Moved accessibility shortcut handling to server-side. [#14843] Also allowed multiple shortcuts for closing Window. Change-Id: I35280ad1553af10ae54bc001e5707357f206b0ee --- server/src/com/vaadin/event/ShortcutAction.java | 38 ++++++++++ server/src/com/vaadin/ui/Window.java | 99 ++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 11 deletions(-) (limited to 'server/src/com') diff --git a/server/src/com/vaadin/event/ShortcutAction.java b/server/src/com/vaadin/event/ShortcutAction.java index 09accae1c7..32b909e9f2 100644 --- a/server/src/com/vaadin/event/ShortcutAction.java +++ b/server/src/com/vaadin/event/ShortcutAction.java @@ -17,6 +17,8 @@ package com.vaadin.event; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -236,6 +238,42 @@ public class ShortcutAction extends Action { return modifiers; } + /** + * Checks whether the shortcut can be triggered with the given combination + * of keys. + * + * @param keyCode + * potential match for the {@link KeyCode} that this shortcut + * reacts to + * @param modifierKeys + * (optional) potential matches for the {@link ModifierKey}s + * required for this shortcut to react + * @return true if keyCode and modifierKeys are a match, + * false otherwise + */ + public boolean isTriggeredBy(int keyCode, int... modifierKeys) { + boolean result = false; + if (keyCode == this.keyCode) { + if (modifierKeys == null) { + result = (modifiers == null); + } else if (modifiers != null) { + List modifierList = new ArrayList(); + for (int modifier : modifiers) { + modifierList.add(modifier); + } + for (int modifierKey : modifierKeys) { + if (modifierList.contains(modifierKey)) { + modifierList.remove(modifierKey); + } else { + return false; + } + } + result = modifierList.isEmpty(); + } + } + return result; + } + /** * Key codes that can be used for shortcuts * diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java index 35583c6052..653b620746 100644 --- a/server/src/com/vaadin/ui/Window.java +++ b/server/src/com/vaadin/ui/Window.java @@ -18,6 +18,9 @@ package com.vaadin.ui; import java.io.Serializable; import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; import java.util.Map; import com.vaadin.event.FieldEvents.BlurEvent; @@ -120,6 +123,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, super(caption, content); registerRpc(rpc); setSizeUndefined(); + setCloseShortcut(ShortcutAction.KeyCode.ESCAPE); } /* ********************************************************************* */ @@ -806,14 +810,48 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, /* * Actions */ - protected CloseShortcut closeShortcut; + private LinkedHashSet closeShortcuts = new LinkedHashSet(); + + protected Collection getCloseShortcuts() { + return Collections.unmodifiableCollection(closeShortcuts); + } + + /** + * Adds a keyboard shortcut for closing the window when user presses the + * given {@link KeyCode} and (optional) {@link ModifierKey}s.
+ * Note that this shortcut only reacts while the window has focus, closing + * itself - if you want to close a window from a UI, use + * {@link UI#addAction(com.vaadin.event.Action)} of the UI instead. + *

+ * If there is a prior CloseShortcut with the same keycode and modifiers, + * that gets removed before the new one is added. Prior CloseShortcuts with + * differing keycodes or modifiers are not affected. + * + * @param keyCode + * the keycode for invoking the shortcut + * @param modifiers + * the (optional) modifiers for invoking the shortcut, null for + * none + */ + public void addCloseShortcut(int keyCode, int... modifiers) { + // make sure there are no duplicates + removeCloseShortcut(keyCode, modifiers); + CloseShortcut closeShortcut = new CloseShortcut(this, keyCode, + modifiers); + closeShortcuts.add(closeShortcut); + addAction(closeShortcut); + } /** - * Makes is possible to close the window by pressing the given - * {@link KeyCode} and (optional) {@link ModifierKey}s.
+ * Sets the keyboard shortcut for closing the window when user presses the + * given {@link KeyCode} and (optional) {@link ModifierKey}s.
* Note that this shortcut only reacts while the window has focus, closing * itself - if you want to close a window from a UI, use * {@link UI#addAction(com.vaadin.event.Action)} of the UI instead. + *

+ * If there are any prior CloseShortcuts when this method is called those + * get removed before the new one is added. NOTE: this also removes the + * default shortcut that is added for accessibility purposes. * * @param keyCode * the keycode for invoking the shortcut @@ -822,22 +860,61 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * none */ public void setCloseShortcut(int keyCode, int... modifiers) { - if (closeShortcut != null) { - removeAction(closeShortcut); + removeCloseShortcuts(); + addCloseShortcut(keyCode, modifiers); + } + + /** + * Removes a keyboard shortcut previously set with + * {@link #setCloseShortcut(int, int...)} or + * {@link #addCloseShortcut(int, int...)}. + * + * @param keyCode + * the keycode for invoking the shortcut + * @param modifiers + * the (optional) modifiers for invoking the shortcut, null for + * none + */ + public void removeCloseShortcut(int keyCode, int... modifiers) { + for (CloseShortcut closeShortcut : closeShortcuts) { + if (closeShortcut.isTriggeredBy(keyCode, modifiers)) { + removeAction(closeShortcut); + closeShortcuts.remove(closeShortcut); + break; + } } - closeShortcut = new CloseShortcut(this, keyCode, modifiers); - addAction(closeShortcut); } /** - * Removes the keyboard shortcut previously set with - * {@link #setCloseShortcut(int, int...)}. + * @deprecated use {@link #resetCloseShortcuts()} instead, or + * {@link #removeCloseShortcuts()} if you also want to get rid + * of the default shortcut */ + @Deprecated public void removeCloseShortcut() { - if (closeShortcut != null) { + resetCloseShortcuts(); + } + + /** + * Removes all the keyboard shortcuts previously set with + * {@link #setCloseShortcut(int, int...)} or + * {@link #addCloseShortcut(int, int...)} and re-adds the default shortcut + * {@link KeyCode.ESCAPE}. + */ + public void resetCloseShortcuts() { + setCloseShortcut(ShortcutAction.KeyCode.ESCAPE); + } + + /** + * Removes all the keyboard shortcuts previously set with + * {@link #setCloseShortcut(int, int...)} or + * {@link #addCloseShortcut(int, int...)}. + */ + public void removeCloseShortcuts() { + for (CloseShortcut closeShortcut : closeShortcuts) { removeAction(closeShortcut); - closeShortcut = null; } + closeShortcuts.clear(); } /** -- cgit v1.2.3