From a003c8724c1f719e3a9f3ab876396a180b19cae1 Mon Sep 17 00:00:00 2001 From: John Alhroos Date: Tue, 18 Sep 2012 10:11:02 +0000 Subject: [PATCH] Merged shortcut action fix from 6.8 (#8484) Change-Id: I1bc200afa9f4a4f3c5e469eb0b2f93278cca97a7 --- .../com/vaadin/client/ui/ShortcutAction.java | 108 ++++++++++++++++++ .../client/ui/ShortcutActionHandler.java | 76 ++++++------ .../client/ui/ShortcutActionTarget.java | 24 ++++ .../client/ui/button/ButtonConnector.java | 20 +++- .../src/com/vaadin/event/ActionManager.java | 30 ++++- .../src/com/vaadin/event/ShortcutAction.java | 45 ++++++++ server/src/com/vaadin/ui/Button.java | 9 +- 7 files changed, 266 insertions(+), 46 deletions(-) create mode 100644 client/src/com/vaadin/client/ui/ShortcutAction.java create mode 100644 client/src/com/vaadin/client/ui/ShortcutActionTarget.java diff --git a/client/src/com/vaadin/client/ui/ShortcutAction.java b/client/src/com/vaadin/client/ui/ShortcutAction.java new file mode 100644 index 0000000000..3209c02203 --- /dev/null +++ b/client/src/com/vaadin/client/ui/ShortcutAction.java @@ -0,0 +1,108 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.client.ui; + +import com.vaadin.client.ApplicationConnection; +import com.vaadin.server.KeyMapper; + +public class ShortcutAction { + + private final ShortcutKeyCombination sc; + private final String caption; + private final String key; + private String targetCID; + private String targetAction; + + /** + * Constructor + * + * @param key + * The @link {@link KeyMapper} key of the action. + * @param sc + * The key combination that triggers the action + * @param caption + * The caption of the action + */ + public ShortcutAction(String key, ShortcutKeyCombination sc, String caption) { + this(key, sc, caption, null, null); + } + + /** + * Constructor + * + * @param key + * The @link {@link KeyMapper} key of the action. + * @param sc + * The key combination that triggers the action + * @param caption + * The caption of the action + * @param targetPID + * The pid of the component the action is targeting. We use the + * pid, instead of the actual Paintable here, so we can delay the + * fetching of the Paintable in cases where the Paintable does + * not yet exist when the action is painted. + * @param targetAction + * The target string of the action. The target string is given to + * the targeted Paintable if the paintable implements the + * {@link ShortcutActionTarget} interface. + */ + public ShortcutAction(String key, ShortcutKeyCombination sc, + String caption, String targetCID, String targetAction) { + this.sc = sc; + this.key = key; + this.caption = caption; + this.targetCID = targetCID; + this.targetAction = targetAction; + } + + /** + * Get the key combination that triggers the action + */ + public ShortcutKeyCombination getShortcutCombination() { + return sc; + } + + /** + * Get the caption of the action + */ + public String getCaption() { + return caption; + } + + /** + * Get the {@link KeyMapper} key for the action + */ + public String getKey() { + return key; + } + + /** + * Get the pid of the target of the action. Use + * {@link ApplicationConnection#getPaintable(String)} to get the actual + * Paintable + */ + public String getTargetCID() { + return targetCID; + } + + /** + * Get the target string of the action + */ + public String getTargetAction() { + return targetAction; + } + +} \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/ShortcutActionHandler.java b/client/src/com/vaadin/client/ui/ShortcutActionHandler.java index 8dc0d9def7..929de7a15d 100644 --- a/client/src/com/vaadin/client/ui/ShortcutActionHandler.java +++ b/client/src/com/vaadin/client/ui/ShortcutActionHandler.java @@ -30,9 +30,11 @@ import com.google.gwt.user.client.ui.KeyboardListenerCollection; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.BrowserInfo; import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ConnectorMap; import com.vaadin.client.UIDL; import com.vaadin.client.Util; import com.vaadin.client.ui.richtextarea.VRichTextArea; +import com.vaadin.shared.Connector; /** * A helper class to implement keyboard shorcut handling. Keeps a list of owners @@ -43,6 +45,15 @@ import com.vaadin.client.ui.richtextarea.VRichTextArea; */ public class ShortcutActionHandler { + public static final String ACTION_TARGET_ATTRIBUTE = "sat"; + public static final String ACTION_TARGET_ACTION_ATTRIBUTE = "sata"; + public static final String ACTION_CAPTION_ATTRIBUTE = "caption"; + public static final String ACTION_KEY_ATTRIBUTE = "key"; + public static final String ACTION_SHORTCUT_KEY_ATTRIBUTE = "kc"; + public static final String ACTION_MODIFIER_KEYS_ATTRIBUTE = "mk"; + public static final String ACTION_TARGET_VARIABLE = "actiontarget"; + public static final String ACTION_TARGET_ACTION_VARIABLE = "action"; + /** * An interface implemented by those users of this helper class that want to * support special components like {@link VRichTextArea} that don't properly @@ -108,15 +119,23 @@ public class ShortcutActionHandler { final UIDL action = (UIDL) it.next(); int[] modifiers = null; - if (action.hasAttribute("mk")) { - modifiers = action.getIntArrayAttribute("mk"); + if (action.hasAttribute(ACTION_MODIFIER_KEYS_ATTRIBUTE)) { + modifiers = action + .getIntArrayAttribute(ACTION_MODIFIER_KEYS_ATTRIBUTE); } final ShortcutKeyCombination kc = new ShortcutKeyCombination( - action.getIntAttribute("kc"), modifiers); - final String key = action.getStringAttribute("key"); - final String caption = action.getStringAttribute("caption"); - actions.add(new ShortcutAction(key, kc, caption)); + action.getIntAttribute(ACTION_SHORTCUT_KEY_ATTRIBUTE), + modifiers); + final String key = action.getStringAttribute(ACTION_KEY_ATTRIBUTE); + final String caption = action + .getStringAttribute(ACTION_CAPTION_ATTRIBUTE); + final String targetPID = action + .getStringAttribute(ACTION_TARGET_ATTRIBUTE); + final String targetAction = action + .getStringAttribute(ACTION_TARGET_ACTION_ATTRIBUTE); + actions.add(new ShortcutAction(key, kc, caption, targetPID, + targetAction)); } } @@ -171,11 +190,22 @@ public class ShortcutActionHandler { Scheduler.get().scheduleDeferred(new Command() { @Override public void execute() { - if (finalTarget != null) { - client.updateVariable(paintableId, "actiontarget", - finalTarget, false); + Connector shortcutTarget = ConnectorMap.get(client) + .getConnector(a.getTargetCID()); + + boolean handledClientSide = false; + if (shortcutTarget instanceof ShortcutActionTarget) { + handledClientSide = ((ShortcutActionTarget) shortcutTarget) + .handleAction(a); + } + if (!handledClientSide) { + if (finalTarget != null) { + client.updateVariable(paintableId, + ACTION_TARGET_VARIABLE, finalTarget, false); + } + client.updateVariable(paintableId, + ACTION_TARGET_ACTION_VARIABLE, a.getKey(), true); } - client.updateVariable(paintableId, "action", a.getKey(), true); } }); } @@ -282,29 +312,3 @@ class ShortcutKeyCombination { return false; } } - -class ShortcutAction { - - private final ShortcutKeyCombination sc; - private final String caption; - private final String key; - - public ShortcutAction(String key, ShortcutKeyCombination sc, String caption) { - this.sc = sc; - this.key = key; - this.caption = caption; - } - - public ShortcutKeyCombination getShortcutCombination() { - return sc; - } - - public String getCaption() { - return caption; - } - - public String getKey() { - return key; - } - -} diff --git a/client/src/com/vaadin/client/ui/ShortcutActionTarget.java b/client/src/com/vaadin/client/ui/ShortcutActionTarget.java new file mode 100644 index 0000000000..617334600e --- /dev/null +++ b/client/src/com/vaadin/client/ui/ShortcutActionTarget.java @@ -0,0 +1,24 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.client.ui; + +/** + * Widgets who wish to be notificed when a shortcut action has been triggered + * with the widget as a target should implement this interface. The + * {@link #handleAction(ShortcutAction)} method will be called just before the + * action is communicated to the server + * + */ +public interface ShortcutActionTarget { + + /** + * Called by the {@link ShortcutActionHandler} just before the shortcut + * action is sent to the server side + * + * @param action + * The action which will be performed on the server side + * @return Returns true if the shortcut was handled + */ + boolean handleAction(ShortcutAction action); +} diff --git a/client/src/com/vaadin/client/ui/button/ButtonConnector.java b/client/src/com/vaadin/client/ui/button/ButtonConnector.java index b15813c99e..546bdecb61 100644 --- a/client/src/com/vaadin/client/ui/button/ButtonConnector.java +++ b/client/src/com/vaadin/client/ui/button/ButtonConnector.java @@ -33,6 +33,8 @@ import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler; import com.vaadin.client.ui.AbstractComponentConnector; import com.vaadin.client.ui.Icon; +import com.vaadin.client.ui.ShortcutAction; +import com.vaadin.client.ui.ShortcutActionTarget; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; import com.vaadin.shared.ui.Connect; @@ -43,7 +45,7 @@ import com.vaadin.ui.Button; @Connect(value = Button.class, loadStyle = LoadStyle.EAGER) public class ButtonConnector extends AbstractComponentConnector implements - BlurHandler, FocusHandler, ClickHandler { + BlurHandler, FocusHandler, ClickHandler, ShortcutActionTarget { private ButtonServerRpc rpc = RpcProxy.create(ButtonServerRpc.class, this); private FocusAndBlurServerRpc focusBlurProxy = RpcProxy.create( @@ -165,4 +167,20 @@ public class ButtonConnector extends AbstractComponentConnector implements rpc.click(details); } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.terminal.gwt.client.ui.ShortcutActionTarget#handleAction(com + * .vaadin.terminal.gwt.client.ui.ShortcutAction) + */ + public boolean handleAction(ShortcutAction action) { + if ("click".equals(action.getTargetAction())) { + getWidget().onClick(); + return true; + } + return false; + } + } diff --git a/server/src/com/vaadin/event/ActionManager.java b/server/src/com/vaadin/event/ActionManager.java index 85a1bf0f12..ad643863a7 100644 --- a/server/src/com/vaadin/event/ActionManager.java +++ b/server/src/com/vaadin/event/ActionManager.java @@ -18,6 +18,7 @@ package com.vaadin.event; import java.util.HashSet; import java.util.Map; +import com.vaadin.client.ui.ShortcutActionHandler; import com.vaadin.event.Action.Container; import com.vaadin.event.Action.Handler; import com.vaadin.server.KeyMapper; @@ -187,14 +188,29 @@ public class ActionManager implements Action.Container, Action.Handler, } if (a instanceof ShortcutAction) { final ShortcutAction sa = (ShortcutAction) a; - paintTarget.addAttribute("kc", sa.getKeyCode()); + paintTarget + .addAttribute( + ShortcutActionHandler.ACTION_SHORTCUT_KEY_ATTRIBUTE, + sa.getKeyCode()); final int[] modifiers = sa.getModifiers(); if (modifiers != null) { final String[] smodifiers = new String[modifiers.length]; for (int i = 0; i < modifiers.length; i++) { smodifiers[i] = String.valueOf(modifiers[i]); } - paintTarget.addAttribute("mk", smodifiers); + paintTarget + .addAttribute( + ShortcutActionHandler.ACTION_MODIFIER_KEYS_ATTRIBUTE, + smodifiers); + } + if (sa.getTarget() != null) { + paintTarget.addAttribute( + ShortcutActionHandler.ACTION_TARGET_ATTRIBUTE, + sa.getTarget()); + paintTarget + .addAttribute( + ShortcutActionHandler.ACTION_TARGET_ACTION_ATTRIBUTE, + sa.getTargetAction()); } } paintTarget.endTag("action"); @@ -212,10 +228,14 @@ public class ActionManager implements Action.Container, Action.Handler, } public void handleActions(Map variables, Container sender) { - if (variables.containsKey("action") && actionMapper != null) { - final String key = (String) variables.get("action"); + if (variables + .containsKey(ShortcutActionHandler.ACTION_TARGET_ACTION_VARIABLE) + && actionMapper != null) { + final String key = (String) variables + .get(ShortcutActionHandler.ACTION_TARGET_ACTION_VARIABLE); final Action action = actionMapper.get(key); - final Object target = variables.get("actiontarget"); + final Object target = variables + .get(ShortcutActionHandler.ACTION_TARGET_VARIABLE); if (action != null) { handleAction(action, sender, target); } diff --git a/server/src/com/vaadin/event/ShortcutAction.java b/server/src/com/vaadin/event/ShortcutAction.java index b1d14b15fe..9d13d41b9f 100644 --- a/server/src/com/vaadin/event/ShortcutAction.java +++ b/server/src/com/vaadin/event/ShortcutAction.java @@ -21,6 +21,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import com.vaadin.server.Resource; +import com.vaadin.ui.Component; import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.Panel; import com.vaadin.ui.Window; @@ -57,6 +58,10 @@ public class ShortcutAction extends Action { private final int[] modifiers; + private Component target; + + private String targetAction; + /** * Creates a shortcut that reacts to the given {@link KeyCode} and * (optionally) {@link ModifierKey}s.
@@ -236,6 +241,46 @@ public class ShortcutAction extends Action { return modifiers; } + /** + * Set the target for the shortcut action. If the target widget on the + * client side implements {@link ShortcutActionTarget} it will be notified + * of the action before the action is communicated to the server side + * + * @param target + * The component which will be thet target of the action + */ + public void setTarget(Component target) { + this.target = target; + } + + /** + * Get the target of the shortcut action + */ + public Component getTarget() { + return target; + } + + /** + * Get the action string that is given to the {@link ShortcutActionTarget} + * on the client side + * + * @return + */ + public String getTargetAction() { + return targetAction; + } + + /** + * Set the action string that is give to the {@link ShortcutActionTarget} on + * the client side + * + * @param targetAction + * The target action string + */ + public void setTargetAction(String targetAction) { + this.targetAction = targetAction; + } + /** * Key codes that can be used for shortcuts * diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java index 02b7689259..d248efd570 100644 --- a/server/src/com/vaadin/ui/Button.java +++ b/server/src/com/vaadin/ui/Button.java @@ -463,7 +463,6 @@ public class Button extends AbstractComponent implements * */ public static class ClickShortcut extends ShortcutListener { - protected Button button; /** * Creates a keyboard shortcut for clicking the given button using the @@ -476,7 +475,8 @@ public class Button extends AbstractComponent implements */ public ClickShortcut(Button button, String shorthandCaption) { super(shorthandCaption); - this.button = button; + setTarget(button); + setTargetAction("click"); } /** @@ -492,7 +492,8 @@ public class Button extends AbstractComponent implements */ public ClickShortcut(Button button, int keyCode, int... modifiers) { super(null, keyCode, modifiers); - this.button = button; + setTarget(button); + setTargetAction("click"); } /** @@ -510,7 +511,7 @@ public class Button extends AbstractComponent implements @Override public void handleAction(Object sender, Object target) { - button.click(); + // Action handled on the client side } } -- 2.39.5