Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package java.awt;
   26   
   27   import java.awt.event.KeyEvent;
   28   import java.awt.event.InputEvent;
   29   import java.util.Collections;
   30   import java.util.HashMap;
   31   import java.util.Map;
   32   import java.util.StringTokenizer;
   33   import java.io.Serializable;
   34   import java.security.AccessController;
   35   import java.security.PrivilegedAction;
   36   import java.lang.reflect.Constructor;
   37   import java.lang.reflect.InvocationTargetException;
   38   import java.lang.reflect.Modifier;
   39   import java.lang.reflect.Field;
   40   
   41   /**
   42    * An <code>AWTKeyStroke</code> represents a key action on the
   43    * keyboard, or equivalent input device. <code>AWTKeyStroke</code>s
   44    * can correspond to only a press or release of a
   45    * particular key, just as <code>KEY_PRESSED</code> and
   46    * <code>KEY_RELEASED</code> <code>KeyEvent</code>s do;
   47    * alternately, they can correspond to typing a specific Java character, just
   48    * as <code>KEY_TYPED</code> <code>KeyEvent</code>s do.
   49    * In all cases, <code>AWTKeyStroke</code>s can specify modifiers
   50    * (alt, shift, control, meta, altGraph, or a combination thereof) which must be present
   51    * during the action for an exact match.
   52    * <p>
   53    * <code>AWTKeyStrokes</code> are immutable, and are intended
   54    * to be unique. Client code should never create an
   55    * <code>AWTKeyStroke</code> on its own, but should instead use
   56    * a variant of <code>getAWTKeyStroke</code>. Client use of these factory
   57    * methods allows the <code>AWTKeyStroke</code> implementation
   58    * to cache and share instances efficiently.
   59    *
   60    * @see #getAWTKeyStroke
   61    *
   62    * @author Arnaud Weber
   63    * @author David Mendenhall
   64    * @since 1.4
   65    */
   66   public class AWTKeyStroke implements Serializable {
   67       static final long serialVersionUID = -6430539691155161871L;
   68   
   69       private static Map cache;
   70       private static AWTKeyStroke cacheKey;
   71       private static Constructor ctor = getCtor(AWTKeyStroke.class);
   72       private static Map modifierKeywords;
   73       /**
   74        * Associates VK_XXX (as a String) with code (as Integer). This is
   75        * done to avoid the overhead of the reflective call to find the
   76        * constant.
   77        */
   78       private static VKCollection vks;
   79   
   80       private char keyChar = KeyEvent.CHAR_UNDEFINED;
   81       private int keyCode = KeyEvent.VK_UNDEFINED;
   82       private int modifiers;
   83       private boolean onKeyRelease;
   84   
   85       static {
   86           /* ensure that the necessary native libraries are loaded */
   87           Toolkit.loadLibraries();
   88       }
   89   
   90       /**
   91        * Constructs an <code>AWTKeyStroke</code> with default values.
   92        * The default values used are:
   93        * <table border="1" summary="AWTKeyStroke default values">
   94        * <tr><th>Property</th><th>Default Value</th></tr>
   95        * <tr>
   96        *    <td>Key Char</td>
   97        *    <td><code>KeyEvent.CHAR_UNDEFINED</code></td>
   98        * </tr>
   99        * <tr>
  100        *    <td>Key Code</td>
  101        *    <td><code>KeyEvent.VK_UNDEFINED</code></td>
  102        * </tr>
  103        * <tr>
  104        *    <td>Modifiers</td>
  105        *    <td>none</td>
  106        * </tr>
  107        * <tr>
  108        *    <td>On key release?</td>
  109        *    <td><code>false</code></td>
  110        * </tr>
  111        * </table>
  112        *
  113        * <code>AWTKeyStroke</code>s should not be constructed
  114        * by client code. Use a variant of <code>getAWTKeyStroke</code>
  115        * instead.
  116        *
  117        * @see #getAWTKeyStroke
  118        */
  119       protected AWTKeyStroke() {
  120       }
  121   
  122       /**
  123        * Constructs an <code>AWTKeyStroke</code> with the specified
  124        * values. <code>AWTKeyStroke</code>s should not be constructed
  125        * by client code. Use a variant of <code>getAWTKeyStroke</code>
  126        * instead.
  127        *
  128        * @param keyChar the character value for a keyboard key
  129        * @param keyCode the key code for this <code>AWTKeyStroke</code>
  130        * @param modifiers a bitwise-ored combination of any modifiers
  131        * @param onKeyRelease <code>true</code> if this
  132        *        <code>AWTKeyStroke</code> corresponds
  133        *        to a key release; <code>false</code> otherwise
  134        * @see #getAWTKeyStroke
  135        */
  136       protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
  137                              boolean onKeyRelease) {
  138           this.keyChar = keyChar;
  139           this.keyCode = keyCode;
  140           this.modifiers = modifiers;
  141           this.onKeyRelease = onKeyRelease;
  142       }
  143   
  144       /**
  145        * Registers a new class which the factory methods in
  146        * <code>AWTKeyStroke</code> will use when generating new
  147        * instances of <code>AWTKeyStroke</code>s. After invoking this
  148        * method, the factory methods will return instances of the specified
  149        * Class. The specified Class must be either <code>AWTKeyStroke</code>
  150        * or derived from <code>AWTKeyStroke</code>, and it must have a
  151        * no-arg constructor. The constructor can be of any accessibility,
  152        * including <code>private</code>. This operation
  153        * flushes the current <code>AWTKeyStroke</code> cache.
  154        *
  155        * @param subclass the new Class of which the factory methods should create
  156        *        instances
  157        * @throws IllegalArgumentException if subclass is <code>null</code>,
  158        *         or if subclass does not have a no-arg constructor
  159        * @throws ClassCastException if subclass is not
  160        *         <code>AWTKeyStroke</code>, or a class derived from
  161        *         <code>AWTKeyStroke</code>
  162        */
  163       protected static void registerSubclass(Class<?> subclass) {
  164           if (subclass == null) {
  165               throw new IllegalArgumentException("subclass cannot be null");
  166           }
  167           if (AWTKeyStroke.ctor.getDeclaringClass().equals(subclass)) {
  168               // Already registered
  169               return;
  170           }
  171           if (!AWTKeyStroke.class.isAssignableFrom(subclass)) {
  172               throw new ClassCastException("subclass is not derived from AWTKeyStroke");
  173           }
  174   
  175           Constructor ctor = getCtor(subclass);
  176   
  177           String couldNotInstantiate = "subclass could not be instantiated";
  178   
  179           if (ctor == null) {
  180               throw new IllegalArgumentException(couldNotInstantiate);
  181           }
  182           try {
  183               AWTKeyStroke stroke = (AWTKeyStroke)ctor.newInstance((Object[]) null);
  184               if (stroke == null) {
  185                   throw new IllegalArgumentException(couldNotInstantiate);
  186               }
  187           } catch (NoSuchMethodError e) {
  188               throw new IllegalArgumentException(couldNotInstantiate);
  189           } catch (ExceptionInInitializerError e) {
  190               throw new IllegalArgumentException(couldNotInstantiate);
  191           } catch (InstantiationException e) {
  192               throw new IllegalArgumentException(couldNotInstantiate);
  193           } catch (IllegalAccessException e) {
  194               throw new IllegalArgumentException(couldNotInstantiate);
  195           } catch (InvocationTargetException e) {
  196               throw new IllegalArgumentException(couldNotInstantiate);
  197           }
  198   
  199           synchronized (AWTKeyStroke.class) {
  200               AWTKeyStroke.ctor = ctor;
  201               cache = null;
  202               cacheKey = null;
  203           }
  204       }
  205   
  206       /* returns noarg Constructor for class with accessible flag. No security
  207          threat as accessible flag is set only for this Constructor object,
  208          not for Class constructor.
  209        */
  210       private static Constructor getCtor(final Class clazz)
  211       {
  212           Object ctor = AccessController.doPrivileged(new PrivilegedAction() {
  213               public Object run() {
  214                   try {
  215                       Constructor ctor = clazz.getDeclaredConstructor((Class[]) null);
  216                       if (ctor != null) {
  217                           ctor.setAccessible(true);
  218                       }
  219                       return ctor;
  220                   } catch (SecurityException e) {
  221                   } catch (NoSuchMethodException e) {
  222                   }
  223                   return null;
  224               }
  225           });
  226           return (Constructor)ctor;
  227       }
  228   
  229       private static synchronized AWTKeyStroke getCachedStroke
  230           (char keyChar, int keyCode, int modifiers, boolean onKeyRelease)
  231       {
  232           if (cache == null) {
  233               cache = new HashMap();
  234           }
  235   
  236           if (cacheKey == null) {
  237               try {
  238                   cacheKey = (AWTKeyStroke)ctor.newInstance((Object[]) null);
  239               } catch (InstantiationException e) {
  240                   assert(false);
  241               } catch (IllegalAccessException e) {
  242                   assert(false);
  243               } catch (InvocationTargetException e) {
  244                   assert(false);
  245               }
  246           }
  247           cacheKey.keyChar = keyChar;
  248           cacheKey.keyCode = keyCode;
  249           cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers));
  250           cacheKey.onKeyRelease = onKeyRelease;
  251   
  252           AWTKeyStroke stroke = (AWTKeyStroke)cache.get(cacheKey);
  253           if (stroke == null) {
  254               stroke = cacheKey;
  255               cache.put(stroke, stroke);
  256               cacheKey = null;
  257           }
  258   
  259           return stroke;
  260       }
  261   
  262       /**
  263        * Returns a shared instance of an <code>AWTKeyStroke</code>
  264        * that represents a <code>KEY_TYPED</code> event for the
  265        * specified character.
  266        *
  267        * @param keyChar the character value for a keyboard key
  268        * @return an <code>AWTKeyStroke</code> object for that key
  269        */
  270       public static AWTKeyStroke getAWTKeyStroke(char keyChar) {
  271           return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
  272       }
  273   
  274       /**
  275        * Returns a shared instance of an {@code AWTKeyStroke}
  276        * that represents a {@code KEY_TYPED} event for the
  277        * specified Character object and a set of modifiers. Note
  278        * that the first parameter is of type Character rather than
  279        * char. This is to avoid inadvertent clashes with
  280        * calls to <code>getAWTKeyStroke(int keyCode, int modifiers)</code>.
  281        *
  282        * The modifiers consist of any combination of following:<ul>
  283        * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
  284        * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
  285        * <li>java.awt.event.InputEvent.META_DOWN_MASK
  286        * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
  287        * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
  288        * </ul>
  289        * The old modifiers listed below also can be used, but they are
  290        * mapped to _DOWN_ modifiers. <ul>
  291        * <li>java.awt.event.InputEvent.SHIFT_MASK
  292        * <li>java.awt.event.InputEvent.CTRL_MASK
  293        * <li>java.awt.event.InputEvent.META_MASK
  294        * <li>java.awt.event.InputEvent.ALT_MASK
  295        * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
  296        * </ul>
  297        * also can be used, but they are mapped to _DOWN_ modifiers.
  298        *
  299        * Since these numbers are all different powers of two, any combination of
  300        * them is an integer in which each bit represents a different modifier
  301        * key. Use 0 to specify no modifiers.
  302        *
  303        * @param keyChar the Character object for a keyboard character
  304        * @param modifiers a bitwise-ored combination of any modifiers
  305        * @return an <code>AWTKeyStroke</code> object for that key
  306        * @throws IllegalArgumentException if <code>keyChar</code> is
  307        *       <code>null</code>
  308        *
  309        * @see java.awt.event.InputEvent
  310        */
  311       public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers)
  312       {
  313           if (keyChar == null) {
  314               throw new IllegalArgumentException("keyChar cannot be null");
  315           }
  316           return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
  317                                  modifiers, false);
  318       }
  319   
  320       /**
  321        * Returns a shared instance of an <code>AWTKeyStroke</code>,
  322        * given a numeric key code and a set of modifiers, specifying
  323        * whether the key is activated when it is pressed or released.
  324        * <p>
  325        * The "virtual key" constants defined in
  326        * <code>java.awt.event.KeyEvent</code> can be
  327        * used to specify the key code. For example:<ul>
  328        * <li><code>java.awt.event.KeyEvent.VK_ENTER</code>
  329        * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
  330        * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
  331        * </ul>
  332        * Alternatively, the key code may be obtained by calling
  333        * <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>.
  334        *
  335        * The modifiers consist of any combination of:<ul>
  336        * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
  337        * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
  338        * <li>java.awt.event.InputEvent.META_DOWN_MASK
  339        * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
  340        * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
  341        * </ul>
  342        * The old modifiers <ul>
  343        * <li>java.awt.event.InputEvent.SHIFT_MASK
  344        * <li>java.awt.event.InputEvent.CTRL_MASK
  345        * <li>java.awt.event.InputEvent.META_MASK
  346        * <li>java.awt.event.InputEvent.ALT_MASK
  347        * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
  348        * </ul>
  349        * also can be used, but they are mapped to _DOWN_ modifiers.
  350        *
  351        * Since these numbers are all different powers of two, any combination of
  352        * them is an integer in which each bit represents a different modifier
  353        * key. Use 0 to specify no modifiers.
  354        *
  355        * @param keyCode an int specifying the numeric code for a keyboard key
  356        * @param modifiers a bitwise-ored combination of any modifiers
  357        * @param onKeyRelease <code>true</code> if the <code>AWTKeyStroke</code>
  358        *        should represent a key release; <code>false</code> otherwise
  359        * @return an AWTKeyStroke object for that key
  360        *
  361        * @see java.awt.event.KeyEvent
  362        * @see java.awt.event.InputEvent
  363        */
  364       public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
  365                                                  boolean onKeyRelease) {
  366           return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
  367                                  onKeyRelease);
  368       }
  369   
  370       /**
  371        * Returns a shared instance of an <code>AWTKeyStroke</code>,
  372        * given a numeric key code and a set of modifiers. The returned
  373        * <code>AWTKeyStroke</code> will correspond to a key press.
  374        * <p>
  375        * The "virtual key" constants defined in
  376        * <code>java.awt.event.KeyEvent</code> can be
  377        * used to specify the key code. For example:<ul>
  378        * <li><code>java.awt.event.KeyEvent.VK_ENTER</code>
  379        * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
  380        * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
  381        * </ul>
  382        * The modifiers consist of any combination of:<ul>
  383        * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
  384        * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
  385        * <li>java.awt.event.InputEvent.META_DOWN_MASK
  386        * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
  387        * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
  388        * </ul>
  389        * The old modifiers <ul>
  390        * <li>java.awt.event.InputEvent.SHIFT_MASK
  391        * <li>java.awt.event.InputEvent.CTRL_MASK
  392        * <li>java.awt.event.InputEvent.META_MASK
  393        * <li>java.awt.event.InputEvent.ALT_MASK
  394        * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
  395        * </ul>
  396        * also can be used, but they are mapped to _DOWN_ modifiers.
  397        *
  398        * Since these numbers are all different powers of two, any combination of
  399        * them is an integer in which each bit represents a different modifier
  400        * key. Use 0 to specify no modifiers.
  401        *
  402        * @param keyCode an int specifying the numeric code for a keyboard key
  403        * @param modifiers a bitwise-ored combination of any modifiers
  404        * @return an <code>AWTKeyStroke</code> object for that key
  405        *
  406        * @see java.awt.event.KeyEvent
  407        * @see java.awt.event.InputEvent
  408        */
  409       public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) {
  410           return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
  411                                  false);
  412       }
  413   
  414       /**
  415        * Returns an <code>AWTKeyStroke</code> which represents the
  416        * stroke which generated a given <code>KeyEvent</code>.
  417        * <p>
  418        * This method obtains the keyChar from a <code>KeyTyped</code>
  419        * event, and the keyCode from a <code>KeyPressed</code> or
  420        * <code>KeyReleased</code> event. The <code>KeyEvent</code> modifiers are
  421        * obtained for all three types of <code>KeyEvent</code>.
  422        *
  423        * @param anEvent the <code>KeyEvent</code> from which to
  424        *      obtain the <code>AWTKeyStroke</code>
  425        * @throws NullPointerException if <code>anEvent</code> is null
  426        * @return the <code>AWTKeyStroke</code> that precipitated the event
  427        */
  428       public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) {
  429           int id = anEvent.getID();
  430           switch(id) {
  431             case KeyEvent.KEY_PRESSED:
  432             case KeyEvent.KEY_RELEASED:
  433               return getCachedStroke(KeyEvent.CHAR_UNDEFINED,
  434                                      anEvent.getKeyCode(),
  435                                      anEvent.getModifiers(),
  436                                      (id == KeyEvent.KEY_RELEASED));
  437             case KeyEvent.KEY_TYPED:
  438               return getCachedStroke(anEvent.getKeyChar(),
  439                                      KeyEvent.VK_UNDEFINED,
  440                                      anEvent.getModifiers(),
  441                                      false);
  442             default:
  443               // Invalid ID for this KeyEvent
  444               return null;
  445           }
  446       }
  447   
  448       /**
  449        * Parses a string and returns an <code>AWTKeyStroke</code>.
  450        * The string must have the following syntax:
  451        * <pre>
  452        *    &lt;modifiers&gt;* (&lt;typedID&gt; | &lt;pressedReleasedID&gt;)
  453        *
  454        *    modifiers := shift | control | ctrl | meta | alt | altGraph
  455        *    typedID := typed &lt;typedKey&gt;
  456        *    typedKey := string of length 1 giving Unicode character.
  457        *    pressedReleasedID := (pressed | released) key
  458        *    key := KeyEvent key code name, i.e. the name following "VK_".
  459        * </pre>
  460        * If typed, pressed or released is not specified, pressed is assumed. Here
  461        * are some examples:
  462        * <pre>
  463        *     "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
  464        *     "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
  465        *     "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
  466        *     "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
  467        *     "typed a" => getAWTKeyStroke('a');
  468        * </pre>
  469        *
  470        * @param s a String formatted as described above
  471        * @return an <code>AWTKeyStroke</code> object for that String
  472        * @throws IllegalArgumentException if <code>s</code> is <code>null</code>,
  473        *        or is formatted incorrectly
  474        */
  475       public static AWTKeyStroke getAWTKeyStroke(String s) {
  476           if (s == null) {
  477               throw new IllegalArgumentException("String cannot be null");
  478           }
  479   
  480           final String errmsg = "String formatted incorrectly";
  481   
  482           StringTokenizer st = new StringTokenizer(s, " ");
  483   
  484           int mask = 0;
  485           boolean released = false;
  486           boolean typed = false;
  487           boolean pressed = false;
  488   
  489           synchronized (AWTKeyStroke.class) {
  490               if (modifierKeywords == null) {
  491                   Map uninitializedMap = new HashMap(8, 1.0f);
  492                   uninitializedMap.put("shift",
  493                                        Integer.valueOf(InputEvent.SHIFT_DOWN_MASK
  494                                                        |InputEvent.SHIFT_MASK));
  495                   uninitializedMap.put("control",
  496                                        Integer.valueOf(InputEvent.CTRL_DOWN_MASK
  497                                                        |InputEvent.CTRL_MASK));
  498                   uninitializedMap.put("ctrl",
  499                                        Integer.valueOf(InputEvent.CTRL_DOWN_MASK
  500                                                        |InputEvent.CTRL_MASK));
  501                   uninitializedMap.put("meta",
  502                                        Integer.valueOf(InputEvent.META_DOWN_MASK
  503                                                        |InputEvent.META_MASK));
  504                   uninitializedMap.put("alt",
  505                                        Integer.valueOf(InputEvent.ALT_DOWN_MASK
  506                                                        |InputEvent.ALT_MASK));
  507                   uninitializedMap.put("altGraph",
  508                                        Integer.valueOf(InputEvent.ALT_GRAPH_DOWN_MASK
  509                                                        |InputEvent.ALT_GRAPH_MASK));
  510                   uninitializedMap.put("button1",
  511                                        Integer.valueOf(InputEvent.BUTTON1_DOWN_MASK));
  512                   uninitializedMap.put("button2",
  513                                        Integer.valueOf(InputEvent.BUTTON2_DOWN_MASK));
  514                   uninitializedMap.put("button3",
  515                                        Integer.valueOf(InputEvent.BUTTON3_DOWN_MASK));
  516                   modifierKeywords =
  517                       Collections.synchronizedMap(uninitializedMap);
  518               }
  519           }
  520   
  521           int count = st.countTokens();
  522   
  523           for (int i = 1; i <= count; i++) {
  524               String token = st.nextToken();
  525   
  526               if (typed) {
  527                   if (token.length() != 1 || i != count) {
  528                       throw new IllegalArgumentException(errmsg);
  529                   }
  530                   return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED,
  531                                          mask, false);
  532               }
  533   
  534               if (pressed || released || i == count) {
  535                   if (i != count) {
  536                       throw new IllegalArgumentException(errmsg);
  537                   }
  538   
  539                   String keyCodeName = "VK_" + token;
  540                   int keyCode = getVKValue(keyCodeName);
  541   
  542                   return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
  543                                          mask, released);
  544               }
  545   
  546               if (token.equals("released")) {
  547                   released = true;
  548                   continue;
  549               }
  550               if (token.equals("pressed")) {
  551                   pressed = true;
  552                   continue;
  553               }
  554               if (token.equals("typed")) {
  555                   typed = true;
  556                   continue;
  557               }
  558   
  559               Integer tokenMask = (Integer)modifierKeywords.get(token);
  560               if (tokenMask != null) {
  561                   mask |= tokenMask.intValue();
  562               } else {
  563                   throw new IllegalArgumentException(errmsg);
  564               }
  565           }
  566   
  567           throw new IllegalArgumentException(errmsg);
  568       }
  569   
  570       private static VKCollection getVKCollection() {
  571           if (vks == null) {
  572               vks = new VKCollection();
  573           }
  574           return vks;
  575       }
  576       /**
  577        * Returns the integer constant for the KeyEvent.VK field named
  578        * <code>key</code>. This will throw an
  579        * <code>IllegalArgumentException</code> if <code>key</code> is
  580        * not a valid constant.
  581        */
  582       private static int getVKValue(String key) {
  583           VKCollection vkCollect = getVKCollection();
  584   
  585           Integer value = vkCollect.findCode(key);
  586   
  587           if (value == null) {
  588               int keyCode = 0;
  589               final String errmsg = "String formatted incorrectly";
  590   
  591               try {
  592                   keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class);
  593               } catch (NoSuchFieldException nsfe) {
  594                   throw new IllegalArgumentException(errmsg);
  595               } catch (IllegalAccessException iae) {
  596                   throw new IllegalArgumentException(errmsg);
  597               }
  598               value = Integer.valueOf(keyCode);
  599               vkCollect.put(key, value);
  600           }
  601           return value.intValue();
  602       }
  603   
  604       /**
  605        * Returns the character for this <code>AWTKeyStroke</code>.
  606        *
  607        * @return a char value
  608        * @see #getAWTKeyStroke(char)
  609        * @see KeyEvent#getKeyChar
  610        */
  611       public final char getKeyChar() {
  612           return keyChar;
  613       }
  614   
  615       /**
  616        * Returns the numeric key code for this <code>AWTKeyStroke</code>.
  617        *
  618        * @return an int containing the key code value
  619        * @see #getAWTKeyStroke(int,int)
  620        * @see KeyEvent#getKeyCode
  621        */
  622       public final int getKeyCode() {
  623           return keyCode;
  624       }
  625   
  626       /**
  627        * Returns the modifier keys for this <code>AWTKeyStroke</code>.
  628        *
  629        * @return an int containing the modifiers
  630        * @see #getAWTKeyStroke(int,int)
  631        */
  632       public final int getModifiers() {
  633           return modifiers;
  634       }
  635   
  636       /**
  637        * Returns whether this <code>AWTKeyStroke</code> represents a key release.
  638        *
  639        * @return <code>true</code> if this <code>AWTKeyStroke</code>
  640        *          represents a key release; <code>false</code> otherwise
  641        * @see #getAWTKeyStroke(int,int,boolean)
  642        */
  643       public final boolean isOnKeyRelease() {
  644           return onKeyRelease;
  645       }
  646   
  647       /**
  648        * Returns the type of <code>KeyEvent</code> which corresponds to
  649        * this <code>AWTKeyStroke</code>.
  650        *
  651        * @return <code>KeyEvent.KEY_PRESSED</code>,
  652        *         <code>KeyEvent.KEY_TYPED</code>,
  653        *         or <code>KeyEvent.KEY_RELEASED</code>
  654        * @see java.awt.event.KeyEvent
  655        */
  656       public final int getKeyEventType() {
  657           if (keyCode == KeyEvent.VK_UNDEFINED) {
  658               return KeyEvent.KEY_TYPED;
  659           } else {
  660               return (onKeyRelease)
  661                   ? KeyEvent.KEY_RELEASED
  662                   : KeyEvent.KEY_PRESSED;
  663           }
  664       }
  665   
  666       /**
  667        * Returns a numeric value for this object that is likely to be unique,
  668        * making it a good choice as the index value in a hash table.
  669        *
  670        * @return an int that represents this object
  671        */
  672       public int hashCode() {
  673           return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) +
  674               (onKeyRelease ? 1 : 2);
  675       }
  676   
  677       /**
  678        * Returns true if this object is identical to the specified object.
  679        *
  680        * @param anObject the Object to compare this object to
  681        * @return true if the objects are identical
  682        */
  683       public final boolean equals(Object anObject) {
  684           if (anObject instanceof AWTKeyStroke) {
  685               AWTKeyStroke ks = (AWTKeyStroke)anObject;
  686               return (ks.keyChar == keyChar && ks.keyCode == keyCode &&
  687                       ks.onKeyRelease == onKeyRelease &&
  688                       ks.modifiers == modifiers);
  689           }
  690           return false;
  691       }
  692   
  693       /**
  694        * Returns a string that displays and identifies this object's properties.
  695        * The <code>String</code> returned by this method can be passed
  696        * as a parameter to <code>getAWTKeyStroke(String)</code> to produce
  697        * a key stroke equal to this key stroke.
  698        *
  699        * @return a String representation of this object
  700        * @see #getAWTKeyStroke(String)
  701        */
  702       public String toString() {
  703           if (keyCode == KeyEvent.VK_UNDEFINED) {
  704               return getModifiersText(modifiers) + "typed " + keyChar;
  705           } else {
  706               return getModifiersText(modifiers) +
  707                   (onKeyRelease ? "released" : "pressed") + " " +
  708                   getVKText(keyCode);
  709           }
  710       }
  711   
  712       static String getModifiersText(int modifiers) {
  713           StringBuilder buf = new StringBuilder();
  714   
  715           if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) {
  716               buf.append("shift ");
  717           }
  718           if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) {
  719               buf.append("ctrl ");
  720           }
  721           if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) {
  722               buf.append("meta ");
  723           }
  724           if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
  725               buf.append("alt ");
  726           }
  727           if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) {
  728               buf.append("altGraph ");
  729           }
  730           if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) {
  731               buf.append("button1 ");
  732           }
  733           if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) {
  734               buf.append("button2 ");
  735           }
  736           if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) {
  737               buf.append("button3 ");
  738           }
  739   
  740           return buf.toString();
  741       }
  742   
  743       static String getVKText(int keyCode) {
  744           VKCollection vkCollect = getVKCollection();
  745           Integer key = Integer.valueOf(keyCode);
  746           String name = vkCollect.findName(key);
  747           if (name != null) {
  748               return name.substring(3);
  749           }
  750           int expected_modifiers =
  751               (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
  752   
  753           Field[] fields = KeyEvent.class.getDeclaredFields();
  754           for (int i = 0; i < fields.length; i++) {
  755               try {
  756                   if (fields[i].getModifiers() == expected_modifiers
  757                       && fields[i].getType() == Integer.TYPE
  758                       && fields[i].getName().startsWith("VK_")
  759                       && fields[i].getInt(KeyEvent.class) == keyCode)
  760                   {
  761                       name = fields[i].getName();
  762                       vkCollect.put(name, key);
  763                       return name.substring(3);
  764                   }
  765               } catch (IllegalAccessException e) {
  766                   assert(false);
  767               }
  768           }
  769           return "UNKNOWN";
  770       }
  771   
  772       /**
  773        * Returns a cached instance of <code>AWTKeyStroke</code> (or a subclass of
  774        * <code>AWTKeyStroke</code>) which is equal to this instance.
  775        *
  776        * @return a cached instance which is equal to this instance
  777        */
  778       protected Object readResolve() throws java.io.ObjectStreamException {
  779           synchronized (AWTKeyStroke.class) {
  780               Class newClass = getClass();
  781               if (!newClass.equals(ctor.getDeclaringClass())) {
  782                   registerSubclass(newClass);
  783               }
  784               return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
  785           }
  786       }
  787   
  788       private static int mapOldModifiers(int modifiers) {
  789           if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
  790               modifiers |= InputEvent.SHIFT_DOWN_MASK;
  791           }
  792           if ((modifiers & InputEvent.ALT_MASK) != 0) {
  793               modifiers |= InputEvent.ALT_DOWN_MASK;
  794           }
  795           if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
  796               modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
  797           }
  798           if ((modifiers & InputEvent.CTRL_MASK) != 0) {
  799               modifiers |= InputEvent.CTRL_DOWN_MASK;
  800           }
  801           if ((modifiers & InputEvent.META_MASK) != 0) {
  802               modifiers |= InputEvent.META_DOWN_MASK;
  803           }
  804   
  805           modifiers &= InputEvent.SHIFT_DOWN_MASK
  806               | InputEvent.ALT_DOWN_MASK
  807               | InputEvent.ALT_GRAPH_DOWN_MASK
  808               | InputEvent.CTRL_DOWN_MASK
  809               | InputEvent.META_DOWN_MASK
  810               | InputEvent.BUTTON1_DOWN_MASK
  811               | InputEvent.BUTTON2_DOWN_MASK
  812               | InputEvent.BUTTON3_DOWN_MASK;
  813   
  814           return modifiers;
  815       }
  816   
  817       private static int mapNewModifiers(int modifiers) {
  818           if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
  819               modifiers |= InputEvent.SHIFT_MASK;
  820           }
  821           if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
  822               modifiers |= InputEvent.ALT_MASK;
  823           }
  824           if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
  825               modifiers |= InputEvent.ALT_GRAPH_MASK;
  826           }
  827           if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
  828               modifiers |= InputEvent.CTRL_MASK;
  829           }
  830           if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
  831               modifiers |= InputEvent.META_MASK;
  832           }
  833   
  834           return modifiers;
  835       }
  836   
  837   }
  838   
  839   class VKCollection {
  840       Map code2name;
  841       Map name2code;
  842   
  843       public VKCollection() {
  844           code2name = new HashMap();
  845           name2code = new HashMap();
  846       }
  847   
  848       public synchronized void put(String name, Integer code) {
  849           assert((name != null) && (code != null));
  850           assert(findName(code) == null);
  851           assert(findCode(name) == null);
  852           code2name.put(code, name);
  853           name2code.put(name, code);
  854       }
  855   
  856       public synchronized Integer findCode(String name) {
  857           assert(name != null);
  858           return (Integer)name2code.get(name);
  859       }
  860   
  861       public synchronized String findName(Integer code) {
  862           assert(code != null);
  863           return (String)code2name.get(code);
  864       }
  865   }

Home » openjdk-7 » java » awt » [javadoc | source]