]> source.dussan.org Git - vaadin-framework.git/commitdiff
Merged shortcut action fix from 6.8 (#8484) 18/18/1
authorJohn Alhroos <john.ahlroos@itmill.com>
Tue, 18 Sep 2012 10:11:02 +0000 (10:11 +0000)
committerArtur Signell <artur@vaadin.com>
Fri, 28 Sep 2012 18:34:00 +0000 (21:34 +0300)
Change-Id: I1bc200afa9f4a4f3c5e469eb0b2f93278cca97a7

client/src/com/vaadin/client/ui/ShortcutAction.java [new file with mode: 0644]
client/src/com/vaadin/client/ui/ShortcutActionHandler.java
client/src/com/vaadin/client/ui/ShortcutActionTarget.java [new file with mode: 0644]
client/src/com/vaadin/client/ui/button/ButtonConnector.java
server/src/com/vaadin/event/ActionManager.java
server/src/com/vaadin/event/ShortcutAction.java
server/src/com/vaadin/ui/Button.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 (file)
index 0000000..3209c02
--- /dev/null
@@ -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
index 8dc0d9def79bffd6b6ab29e177be865a93bf1df0..929de7a15ddd66a46cf4f32538f1336f4c60916f 100644 (file)
@@ -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 (file)
index 0000000..6173346
--- /dev/null
@@ -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);
+}
index b15813c99e3f7e19871cc88c12e228a87f6ca187..546bdecb6130e90720a55a2db1311e9d5d5cee96 100644 (file)
@@ -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;
+    }
+
 }
index 85a1bf0f1250936a91e98c56ae0547dbfab67404..ad643863a700a29ef31d47f7c7e1d506cc466b53 100644 (file)
@@ -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<String, Object> 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);
             }
index b1d14b15fe2035179ac0f745ab04eb22b08422c4..9d13d41b9f8af90c36b49cceca1df9d9357cd954 100644 (file)
@@ -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. <br/>
@@ -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
      * 
index 02b768925975e4361d3985b3e0675cbe3b8aedff..d248efd570ad305f82c815ebe6822a26350fbbc5 100644 (file)
@@ -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
         }
     }