Save This Page
Home » openjdk-7 » java » awt » [javadoc | source]
    1   /*
    2    * Copyright 2000-2006 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any 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        * The modifiers consist of any combination of:<ul>
  333        * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
  334        * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
  335        * <li>java.awt.event.InputEvent.META_DOWN_MASK
  336        * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
  337        * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
  338        * </ul>
  339        * The old modifiers <ul>
  340        * <li>java.awt.event.InputEvent.SHIFT_MASK
  341        * <li>java.awt.event.InputEvent.CTRL_MASK
  342        * <li>java.awt.event.InputEvent.META_MASK
  343        * <li>java.awt.event.InputEvent.ALT_MASK
  344        * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
  345        * </ul>
  346        * also can be used, but they are mapped to _DOWN_ modifiers.
  347        *
  348        * Since these numbers are all different powers of two, any combination of
  349        * them is an integer in which each bit represents a different modifier
  350        * key. Use 0 to specify no modifiers.
  351        *
  352        * @param keyCode an int specifying the numeric code for a keyboard key
  353        * @param modifiers a bitwise-ored combination of any modifiers
  354        * @param onKeyRelease <code>true</code> if the <code>AWTKeyStroke</code>
  355        *        should represent a key release; <code>false</code> otherwise
  356        * @return an AWTKeyStroke object for that key
  357        *
  358        * @see java.awt.event.KeyEvent
  359        * @see java.awt.event.InputEvent
  360        */
  361       public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
  362                                                  boolean onKeyRelease) {
  363           return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
  364                                  onKeyRelease);
  365       }
  366   
  367       /**
  368        * Returns a shared instance of an <code>AWTKeyStroke</code>,
  369        * given a numeric key code and a set of modifiers. The returned
  370        * <code>AWTKeyStroke</code> will correspond to a key press.
  371        * <p>
  372        * The "virtual key" constants defined in
  373        * <code>java.awt.event.KeyEvent</code> can be
  374        * used to specify the key code. For example:<ul>
  375        * <li><code>java.awt.event.KeyEvent.VK_ENTER</code>
  376        * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
  377        * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
  378        * </ul>
  379        * The modifiers consist of any combination of:<ul>
  380        * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
  381        * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
  382        * <li>java.awt.event.InputEvent.META_DOWN_MASK
  383        * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
  384        * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
  385        * </ul>
  386        * The old modifiers <ul>
  387        * <li>java.awt.event.InputEvent.SHIFT_MASK
  388        * <li>java.awt.event.InputEvent.CTRL_MASK
  389        * <li>java.awt.event.InputEvent.META_MASK
  390        * <li>java.awt.event.InputEvent.ALT_MASK
  391        * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
  392        * </ul>
  393        * also can be used, but they are mapped to _DOWN_ modifiers.
  394        *
  395        * Since these numbers are all different powers of two, any combination of
  396        * them is an integer in which each bit represents a different modifier
  397        * key. Use 0 to specify no modifiers.
  398        *
  399        * @param keyCode an int specifying the numeric code for a keyboard key
  400        * @param modifiers a bitwise-ored combination of any modifiers
  401        * @return an <code>AWTKeyStroke</code> object for that key
  402        *
  403        * @see java.awt.event.KeyEvent
  404        * @see java.awt.event.InputEvent
  405        */
  406       public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) {
  407           return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
  408                                  false);
  409       }
  410   
  411       /**
  412        * Returns an <code>AWTKeyStroke</code> which represents the
  413        * stroke which generated a given <code>KeyEvent</code>.
  414        * <p>
  415        * This method obtains the keyChar from a <code>KeyTyped</code>
  416        * event, and the keyCode from a <code>KeyPressed</code> or
  417        * <code>KeyReleased</code> event. The <code>KeyEvent</code> modifiers are
  418        * obtained for all three types of <code>KeyEvent</code>.
  419        *
  420        * @param anEvent the <code>KeyEvent</code> from which to
  421        *      obtain the <code>AWTKeyStroke</code>
  422        * @throws NullPointerException if <code>anEvent</code> is null
  423        * @return the <code>AWTKeyStroke</code> that precipitated the event
  424        */
  425       public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) {
  426           int id = anEvent.getID();
  427           switch(id) {
  428             case KeyEvent.KEY_PRESSED:
  429             case KeyEvent.KEY_RELEASED:
  430               return getCachedStroke(KeyEvent.CHAR_UNDEFINED,
  431                                      anEvent.getKeyCode(),
  432                                      anEvent.getModifiers(),
  433                                      (id == KeyEvent.KEY_RELEASED));
  434             case KeyEvent.KEY_TYPED:
  435               return getCachedStroke(anEvent.getKeyChar(),
  436                                      KeyEvent.VK_UNDEFINED,
  437                                      anEvent.getModifiers(),
  438                                      false);
  439             default:
  440               // Invalid ID for this KeyEvent
  441               return null;
  442           }
  443       }
  444   
  445       /**
  446        * Parses a string and returns an <code>AWTKeyStroke</code>.
  447        * The string must have the following syntax:
  448        * <pre>
  449        *    &lt;modifiers&gt;* (&lt;typedID&gt; | &lt;pressedReleasedID&gt;)
  450        *
  451        *    modifiers := shift | control | ctrl | meta | alt | altGraph
  452        *    typedID := typed &lt;typedKey&gt;
  453        *    typedKey := string of length 1 giving Unicode character.
  454        *    pressedReleasedID := (pressed | released) key
  455        *    key := KeyEvent key code name, i.e. the name following "VK_".
  456        * </pre>
  457        * If typed, pressed or released is not specified, pressed is assumed. Here
  458        * are some examples:
  459        * <pre>
  460        *     "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
  461        *     "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
  462        *     "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
  463        *     "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
  464        *     "typed a" => getAWTKeyStroke('a');
  465        * </pre>
  466        *
  467        * @param s a String formatted as described above
  468        * @return an <code>AWTKeyStroke</code> object for that String
  469        * @throws IllegalArgumentException if <code>s</code> is <code>null</code>,
  470        *        or is formatted incorrectly
  471        */
  472       public static AWTKeyStroke getAWTKeyStroke(String s) {
  473           if (s == null) {
  474               throw new IllegalArgumentException("String cannot be null");
  475           }
  476   
  477           final String errmsg = "String formatted incorrectly";
  478   
  479           StringTokenizer st = new StringTokenizer(s, " ");
  480   
  481           int mask = 0;
  482           boolean released = false;
  483           boolean typed = false;
  484           boolean pressed = false;
  485   
  486           synchronized (AWTKeyStroke.class) {
  487               if (modifierKeywords == null) {
  488                   Map uninitializedMap = new HashMap(8, 1.0f);
  489                   uninitializedMap.put("shift",
  490                                        Integer.valueOf(InputEvent.SHIFT_DOWN_MASK
  491                                                        |InputEvent.SHIFT_MASK));
  492                   uninitializedMap.put("control",
  493                                        Integer.valueOf(InputEvent.CTRL_DOWN_MASK
  494                                                        |InputEvent.CTRL_MASK));
  495                   uninitializedMap.put("ctrl",
  496                                        Integer.valueOf(InputEvent.CTRL_DOWN_MASK
  497                                                        |InputEvent.CTRL_MASK));
  498                   uninitializedMap.put("meta",
  499                                        Integer.valueOf(InputEvent.META_DOWN_MASK
  500                                                        |InputEvent.META_MASK));
  501                   uninitializedMap.put("alt",
  502                                        Integer.valueOf(InputEvent.ALT_DOWN_MASK
  503                                                        |InputEvent.ALT_MASK));
  504                   uninitializedMap.put("altGraph",
  505                                        Integer.valueOf(InputEvent.ALT_GRAPH_DOWN_MASK
  506                                                        |InputEvent.ALT_GRAPH_MASK));
  507                   uninitializedMap.put("button1",
  508                                        Integer.valueOf(InputEvent.BUTTON1_DOWN_MASK));
  509                   uninitializedMap.put("button2",
  510                                        Integer.valueOf(InputEvent.BUTTON2_DOWN_MASK));
  511                   uninitializedMap.put("button3",
  512                                        Integer.valueOf(InputEvent.BUTTON3_DOWN_MASK));
  513                   modifierKeywords =
  514                       Collections.synchronizedMap(uninitializedMap);
  515               }
  516           }
  517   
  518           int count = st.countTokens();
  519   
  520           for (int i = 1; i <= count; i++) {
  521               String token = st.nextToken();
  522   
  523               if (typed) {
  524                   if (token.length() != 1 || i != count) {
  525                       throw new IllegalArgumentException(errmsg);
  526                   }
  527                   return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED,
  528                                          mask, false);
  529               }
  530   
  531               if (pressed || released || i == count) {
  532                   if (i != count) {
  533                       throw new IllegalArgumentException(errmsg);
  534                   }
  535   
  536                   String keyCodeName = "VK_" + token;
  537                   int keyCode = getVKValue(keyCodeName);
  538   
  539                   return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
  540                                          mask, released);
  541               }
  542   
  543               if (token.equals("released")) {
  544                   released = true;
  545                   continue;
  546               }
  547               if (token.equals("pressed")) {
  548                   pressed = true;
  549                   continue;
  550               }
  551               if (token.equals("typed")) {
  552                   typed = true;
  553                   continue;
  554               }
  555   
  556               Integer tokenMask = (Integer)modifierKeywords.get(token);
  557               if (tokenMask != null) {
  558                   mask |= tokenMask.intValue();
  559               } else {
  560                   throw new IllegalArgumentException(errmsg);
  561               }
  562           }
  563   
  564           throw new IllegalArgumentException(errmsg);
  565       }
  566   
  567       private static VKCollection getVKCollection() {
  568           if (vks == null) {
  569               vks = new VKCollection();
  570           }
  571           return vks;
  572       }
  573       /**
  574        * Returns the integer constant for the KeyEvent.VK field named
  575        * <code>key</code>. This will throw an
  576        * <code>IllegalArgumentException</code> if <code>key</code> is
  577        * not a valid constant.
  578        */
  579       private static int getVKValue(String key) {
  580           VKCollection vkCollect = getVKCollection();
  581   
  582           Integer value = vkCollect.findCode(key);
  583   
  584           if (value == null) {
  585               int keyCode = 0;
  586               final String errmsg = "String formatted incorrectly";
  587   
  588               try {
  589                   keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class);
  590               } catch (NoSuchFieldException nsfe) {
  591                   throw new IllegalArgumentException(errmsg);
  592               } catch (IllegalAccessException iae) {
  593                   throw new IllegalArgumentException(errmsg);
  594               }
  595               value = Integer.valueOf(keyCode);
  596               vkCollect.put(key, value);
  597           }
  598           return value.intValue();
  599       }
  600   
  601       /**
  602        * Returns the character for this <code>AWTKeyStroke</code>.
  603        *
  604        * @return a char value
  605        * @see #getAWTKeyStroke(char)
  606        * @see KeyEvent#getKeyChar
  607        */
  608       public final char getKeyChar() {
  609           return keyChar;
  610       }
  611   
  612       /**
  613        * Returns the numeric key code for this <code>AWTKeyStroke</code>.
  614        *
  615        * @return an int containing the key code value
  616        * @see #getAWTKeyStroke(int,int)
  617        * @see KeyEvent#getKeyCode
  618        */
  619       public final int getKeyCode() {
  620           return keyCode;
  621       }
  622   
  623       /**
  624        * Returns the modifier keys for this <code>AWTKeyStroke</code>.
  625        *
  626        * @return an int containing the modifiers
  627        * @see #getAWTKeyStroke(int,int)
  628        */
  629       public final int getModifiers() {
  630           return modifiers;
  631       }
  632   
  633       /**
  634        * Returns whether this <code>AWTKeyStroke</code> represents a key release.
  635        *
  636        * @return <code>true</code> if this <code>AWTKeyStroke</code>
  637        *          represents a key release; <code>false</code> otherwise
  638        * @see #getAWTKeyStroke(int,int,boolean)
  639        */
  640       public final boolean isOnKeyRelease() {
  641           return onKeyRelease;
  642       }
  643   
  644       /**
  645        * Returns the type of <code>KeyEvent</code> which corresponds to
  646        * this <code>AWTKeyStroke</code>.
  647        *
  648        * @return <code>KeyEvent.KEY_PRESSED</code>,
  649        *         <code>KeyEvent.KEY_TYPED</code>,
  650        *         or <code>KeyEvent.KEY_RELEASED</code>
  651        * @see java.awt.event.KeyEvent
  652        */
  653       public final int getKeyEventType() {
  654           if (keyCode == KeyEvent.VK_UNDEFINED) {
  655               return KeyEvent.KEY_TYPED;
  656           } else {
  657               return (onKeyRelease)
  658                   ? KeyEvent.KEY_RELEASED
  659                   : KeyEvent.KEY_PRESSED;
  660           }
  661       }
  662   
  663       /**
  664        * Returns a numeric value for this object that is likely to be unique,
  665        * making it a good choice as the index value in a hash table.
  666        *
  667        * @return an int that represents this object
  668        */
  669       public int hashCode() {
  670           return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) +
  671               (onKeyRelease ? 1 : 2);
  672       }
  673   
  674       /**
  675        * Returns true if this object is identical to the specified object.
  676        *
  677        * @param anObject the Object to compare this object to
  678        * @return true if the objects are identical
  679        */
  680       public final boolean equals(Object anObject) {
  681           if (anObject instanceof AWTKeyStroke) {
  682               AWTKeyStroke ks = (AWTKeyStroke)anObject;
  683               return (ks.keyChar == keyChar && ks.keyCode == keyCode &&
  684                       ks.onKeyRelease == onKeyRelease &&
  685                       ks.modifiers == modifiers);
  686           }
  687           return false;
  688       }
  689   
  690       /**
  691        * Returns a string that displays and identifies this object's properties.
  692        * The <code>String</code> returned by this method can be passed
  693        * as a parameter to <code>getAWTKeyStroke(String)</code> to produce
  694        * a key stroke equal to this key stroke.
  695        *
  696        * @return a String representation of this object
  697        * @see #getAWTKeyStroke(String)
  698        */
  699       public String toString() {
  700           if (keyCode == KeyEvent.VK_UNDEFINED) {
  701               return getModifiersText(modifiers) + "typed " + keyChar;
  702           } else {
  703               return getModifiersText(modifiers) +
  704                   (onKeyRelease ? "released" : "pressed") + " " +
  705                   getVKText(keyCode);
  706           }
  707       }
  708   
  709       static String getModifiersText(int modifiers) {
  710           StringBuilder buf = new StringBuilder();
  711   
  712           if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) {
  713               buf.append("shift ");
  714           }
  715           if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) {
  716               buf.append("ctrl ");
  717           }
  718           if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) {
  719               buf.append("meta ");
  720           }
  721           if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
  722               buf.append("alt ");
  723           }
  724           if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) {
  725               buf.append("altGraph ");
  726           }
  727           if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) {
  728               buf.append("button1 ");
  729           }
  730           if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) {
  731               buf.append("button2 ");
  732           }
  733           if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) {
  734               buf.append("button3 ");
  735           }
  736   
  737           return buf.toString();
  738       }
  739   
  740       static String getVKText(int keyCode) {
  741           VKCollection vkCollect = getVKCollection();
  742           Integer key = Integer.valueOf(keyCode);
  743           String name = vkCollect.findName(key);
  744           if (name != null) {
  745               return name.substring(3);
  746           }
  747           int expected_modifiers =
  748               (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
  749   
  750           Field[] fields = KeyEvent.class.getDeclaredFields();
  751           for (int i = 0; i < fields.length; i++) {
  752               try {
  753                   if (fields[i].getModifiers() == expected_modifiers
  754                       && fields[i].getType() == Integer.TYPE
  755                       && fields[i].getName().startsWith("VK_")
  756                       && fields[i].getInt(KeyEvent.class) == keyCode)
  757                   {
  758                       name = fields[i].getName();
  759                       vkCollect.put(name, key);
  760                       return name.substring(3);
  761                   }
  762               } catch (IllegalAccessException e) {
  763                   assert(false);
  764               }
  765           }
  766           return "UNKNOWN";
  767       }
  768   
  769       /**
  770        * Returns a cached instance of <code>AWTKeyStroke</code> (or a subclass of
  771        * <code>AWTKeyStroke</code>) which is equal to this instance.
  772        *
  773        * @return a cached instance which is equal to this instance
  774        */
  775       protected Object readResolve() throws java.io.ObjectStreamException {
  776           synchronized (AWTKeyStroke.class) {
  777               Class newClass = getClass();
  778               if (!newClass.equals(ctor.getDeclaringClass())) {
  779                   registerSubclass(newClass);
  780               }
  781               return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
  782           }
  783       }
  784   
  785       private static int mapOldModifiers(int modifiers) {
  786           if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
  787               modifiers |= InputEvent.SHIFT_DOWN_MASK;
  788           }
  789           if ((modifiers & InputEvent.ALT_MASK) != 0) {
  790               modifiers |= InputEvent.ALT_DOWN_MASK;
  791           }
  792           if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
  793               modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
  794           }
  795           if ((modifiers & InputEvent.CTRL_MASK) != 0) {
  796               modifiers |= InputEvent.CTRL_DOWN_MASK;
  797           }
  798           if ((modifiers & InputEvent.META_MASK) != 0) {
  799               modifiers |= InputEvent.META_DOWN_MASK;
  800           }
  801   
  802           modifiers &= InputEvent.SHIFT_DOWN_MASK
  803               | InputEvent.ALT_DOWN_MASK
  804               | InputEvent.ALT_GRAPH_DOWN_MASK
  805               | InputEvent.CTRL_DOWN_MASK
  806               | InputEvent.META_DOWN_MASK
  807               | InputEvent.BUTTON1_DOWN_MASK
  808               | InputEvent.BUTTON2_DOWN_MASK
  809               | InputEvent.BUTTON3_DOWN_MASK;
  810   
  811           return modifiers;
  812       }
  813   
  814       private static int mapNewModifiers(int modifiers) {
  815           if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
  816               modifiers |= InputEvent.SHIFT_MASK;
  817           }
  818           if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
  819               modifiers |= InputEvent.ALT_MASK;
  820           }
  821           if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
  822               modifiers |= InputEvent.ALT_GRAPH_MASK;
  823           }
  824           if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
  825               modifiers |= InputEvent.CTRL_MASK;
  826           }
  827           if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
  828               modifiers |= InputEvent.META_MASK;
  829           }
  830   
  831           return modifiers;
  832       }
  833   
  834   }
  835   
  836   class VKCollection {
  837       Map code2name;
  838       Map name2code;
  839   
  840       public VKCollection() {
  841           code2name = new HashMap();
  842           name2code = new HashMap();
  843       }
  844   
  845       public synchronized void put(String name, Integer code) {
  846           assert((name != null) && (code != null));
  847           assert(findName(code) == null);
  848           assert(findCode(name) == null);
  849           code2name.put(code, name);
  850           name2code.put(name, code);
  851       }
  852   
  853       public synchronized Integer findCode(String name) {
  854           assert(name != null);
  855           return (Integer)name2code.get(name);
  856       }
  857   
  858       public synchronized String findName(Integer code) {
  859           assert(code != null);
  860           return (String)code2name.get(code);
  861       }
  862   }

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