KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > AWTKeyStroke


1 /*
2  * @(#)AWTKeyStroke.java 1.23 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.awt;
8
9 import java.awt.event.KeyEvent JavaDoc;
10 import java.awt.event.InputEvent JavaDoc;
11 import java.util.Collections JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15 import java.io.Serializable JavaDoc;
16 import java.security.AccessController JavaDoc;
17 import java.security.PrivilegedAction JavaDoc;
18 import java.lang.reflect.Constructor JavaDoc;
19 import java.lang.reflect.InvocationTargetException JavaDoc;
20 import java.lang.reflect.Modifier JavaDoc;
21 import java.lang.reflect.Field JavaDoc;
22
23 /**
24  * An <code>AWTKeyStroke</code> represents a key action on the
25  * keyboard, or equivalent input device. <code>AWTKeyStroke</code>s
26  * can correspond to only a press or release of a
27  * particular key, just as <code>KEY_PRESSED</code> and
28  * <code>KEY_RELEASED</code> <code>KeyEvent</code>s do;
29  * alternately, they can correspond to typing a specific Java character, just
30  * as <code>KEY_TYPED</code> <code>KeyEvent</code>s do.
31  * In all cases, <code>AWTKeyStroke</code>s can specify modifiers
32  * (alt, shift, control, meta, or a combination thereof) which must be present
33  * during the action for an exact match.
34  * <p>
35  * <code>AWTKeyStrokes</code> are immutable, and are intended
36  * to be unique. Client code should never create an
37  * <code>AWTKeyStroke</code> on its own, but should instead use
38  * a variant of <code>getAWTKeyStroke</code>. Client use of these factory
39  * methods allows the <code>AWTKeyStroke</code> implementation
40  * to cache and share instances efficiently.
41  *
42  * @see #getAWTKeyStroke
43  *
44  * @version 1.23, 05/05/04
45  * @author Arnaud Weber
46  * @author David Mendenhall
47  * @since 1.4
48  */

49 public class AWTKeyStroke implements Serializable JavaDoc {
50     static final long serialVersionUID = -6430539691155161871L;
51
52     private static Map JavaDoc cache;
53     private static AWTKeyStroke JavaDoc cacheKey;
54     private static Constructor JavaDoc ctor = getCtor(AWTKeyStroke JavaDoc.class);
55     private static Map JavaDoc modifierKeywords;
56     /**
57      * Associates VK_XXX (as a String) with code (as Integer). This is
58      * done to avoid the overhead of the reflective call to find the
59      * constant.
60      */

61     private static VKCollection vks;
62
63     private char keyChar = KeyEvent.CHAR_UNDEFINED;
64     private int keyCode = KeyEvent.VK_UNDEFINED;
65     private int modifiers;
66     private boolean onKeyRelease;
67
68     static {
69         /* ensure that the necessary native libraries are loaded */
70         Toolkit.loadLibraries();
71     }
72
73     /**
74      * Constructs an <code>AWTKeyStroke</code> with default values.
75      * The default values used are:
76      * <table border="1" summary="AWTKeyStroke default values">
77      * <tr><th>Property</th><th>Default Value</th></tr>
78      * <tr>
79      * <td>Key Char</td>
80      * <td><code>KeyEvent.CHAR_UNDEFINED</code></td>
81      * </tr>
82      * <tr>
83      * <td>Key Code</td>
84      * <td><code>KeyEvent.VK_UNDEFINED</code></td>
85      * </tr>
86      * <tr>
87      * <td>Modifiers</td>
88      * <td>none</td>
89      * </tr>
90      * <tr>
91      * <td>On key release?</td>
92      * <td><code>false</code></td>
93      * </tr>
94      * </table>
95      *
96      * <code>AWTKeyStroke</code>s should not be constructed
97      * by client code. Use a variant of <code>getAWTKeyStroke</code>
98      * instead.
99      *
100      * @see #getAWTKeyStroke
101      */

102     protected AWTKeyStroke() {
103     }
104
105     /**
106      * Constructs an <code>AWTKeyStroke</code> with the specified
107      * values. <code>AWTKeyStroke</code>s should not be constructed
108      * by client code. Use a variant of <code>getAWTKeyStroke</code>
109      * instead.
110      *
111      * @param keyChar the character value for a keyboard key
112      * @param keyCode the key code for this <code>AWTKeyStroke</code>
113      * @param modifiers a bitwise-ored combination of any modifiers
114      * @param onKeyRelease <code>true</code> if this
115      * <code>AWTKeyStroke</code> corresponds
116      * to a key release; <code>false</code> otherwise
117      * @see #getAWTKeyStroke
118      */

119     protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
120                boolean onKeyRelease) {
121         this.keyChar = keyChar;
122     this.keyCode = keyCode;
123     this.modifiers = modifiers;
124     this.onKeyRelease = onKeyRelease;
125     }
126
127     /**
128      * Registers a new class which the factory methods in
129      * <code>AWTKeyStroke</code> will use when generating new
130      * instances of <code>AWTKeyStroke</code>s. After invoking this
131      * method, the factory methods will return instances of the specified
132      * Class. The specified Class must be either <code>AWTKeyStroke</code>
133      * or derived from <code>AWTKeyStroke</code>, and it must have a
134      * no-arg constructor. The constructor can be of any accessibility,
135      * including <code>private</code>. This operation
136      * flushes the current <code>AWTKeyStroke</code> cache.
137      *
138      * @param subclass the new Class of which the factory methods should create
139      * instances
140      * @throws IllegalArgumentException if subclass is <code>null</code>,
141      * or if subclass does not have a no-arg constructor
142      * @throws ClassCastException if subclass is not
143      * <code>AWTKeyStroke</code>, or a class derived from
144      * <code>AWTKeyStroke</code>
145      */

146     protected static void registerSubclass(Class JavaDoc<?> subclass) {
147         if (subclass == null) {
148         throw new IllegalArgumentException JavaDoc("subclass cannot be null");
149     }
150     if (AWTKeyStroke.ctor.getDeclaringClass().equals(subclass)) {
151         // Already registered
152
return;
153     }
154     if (!AWTKeyStroke JavaDoc.class.isAssignableFrom(subclass)) {
155         throw new ClassCastException JavaDoc("subclass is not derived from AWTKeyStroke");
156     }
157
158         Constructor JavaDoc ctor = getCtor(subclass);
159
160     String JavaDoc couldNotInstantiate = "subclass could not be instantiated";
161
162         if (ctor == null) {
163         throw new IllegalArgumentException JavaDoc(couldNotInstantiate);
164     }
165     try {
166         AWTKeyStroke JavaDoc stroke = (AWTKeyStroke JavaDoc)ctor.newInstance(null);
167         if (stroke == null) {
168             throw new IllegalArgumentException JavaDoc(couldNotInstantiate);
169         }
170     } catch (NoSuchMethodError JavaDoc e) {
171         throw new IllegalArgumentException JavaDoc(couldNotInstantiate);
172     } catch (ExceptionInInitializerError JavaDoc e) {
173         throw new IllegalArgumentException JavaDoc(couldNotInstantiate);
174     } catch (InstantiationException JavaDoc e) {
175         throw new IllegalArgumentException JavaDoc(couldNotInstantiate);
176     } catch (IllegalAccessException JavaDoc e) {
177         throw new IllegalArgumentException JavaDoc(couldNotInstantiate);
178     } catch (InvocationTargetException JavaDoc e) {
179         throw new IllegalArgumentException JavaDoc(couldNotInstantiate);
180     }
181
182     synchronized (AWTKeyStroke JavaDoc.class) {
183         AWTKeyStroke.ctor = ctor;
184         cache = null;
185         cacheKey = null;
186     }
187     }
188
189     /* returns noarg Constructor for class with accessible flag. No security
190        threat as accessible flag is set only for this Constructor object,
191        not for Class constructor.
192      */

193     private static Constructor JavaDoc getCtor(final Class JavaDoc clazz)
194     {
195         Object JavaDoc ctor = AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
196             public Object JavaDoc run() {
197                 try {
198                     Constructor JavaDoc ctor = clazz.getDeclaredConstructor(null);
199                     if (ctor != null) {
200                         ctor.setAccessible(true);
201                     }
202                     return ctor;
203                 } catch (SecurityException JavaDoc e) {
204                 } catch (NoSuchMethodException JavaDoc e) {
205                 }
206                 return null;
207             }
208         });
209         return (Constructor JavaDoc)ctor;
210     }
211
212     private static synchronized AWTKeyStroke JavaDoc getCachedStroke
213         (char keyChar, int keyCode, int modifiers, boolean onKeyRelease)
214     {
215     if (cache == null) {
216         cache = new HashMap JavaDoc();
217     }
218  
219     if (cacheKey == null) {
220         try {
221         cacheKey = (AWTKeyStroke JavaDoc)ctor.newInstance(null);
222         } catch (InstantiationException JavaDoc e) {
223                 assert(false);
224             } catch (IllegalAccessException JavaDoc e) {
225                 assert(false);
226             } catch (InvocationTargetException JavaDoc e) {
227                 assert(false);
228         }
229     }
230     cacheKey.keyChar = keyChar;
231     cacheKey.keyCode = keyCode;
232     cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers));
233     cacheKey.onKeyRelease = onKeyRelease;
234  
235     AWTKeyStroke JavaDoc stroke = (AWTKeyStroke JavaDoc)cache.get(cacheKey);
236     if (stroke == null) {
237         stroke = cacheKey;
238         cache.put(stroke, stroke);
239         cacheKey = null;
240     }
241     
242     return stroke;
243     }
244
245     /**
246      * Returns a shared instance of an <code>AWTKeyStroke</code>
247      * that represents a <code>KEY_TYPED</code> event for the
248      * specified character.
249      *
250      * @param keyChar the character value for a keyboard key
251      * @return an <code>AWTKeyStroke</code> object for that key
252      */

253     public static AWTKeyStroke JavaDoc getAWTKeyStroke(char keyChar) {
254         return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
255     }
256
257     /**
258      * Returns a shared instance of an <code>AWTKeyStroke</code>,
259      * given a Character object and a set of modifiers. Note
260      * that the first parameter is of type Character rather than
261      * char. This is to avoid inadvertent clashes with
262      * calls to <code>getAWTKeyStroke(int keyCode, int modifiers)</code>.
263      *
264      * The modifiers consist of any combination of:<ul>
265      * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
266      * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
267      * <li>java.awt.event.InputEvent.META_DOWN_MASK
268      * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
269      * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
270      * </ul>
271      * The old modifiers <ul>
272      * <li>java.awt.event.InputEvent.SHIFT_MASK
273      * <li>java.awt.event.InputEvent.CTRL_MASK
274      * <li>java.awt.event.InputEvent.META_MASK
275      * <li>java.awt.event.InputEvent.ALT_MASK
276      * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
277      * </ul>
278      * also can be used, but they are mapped to _DOWN_ modifiers.
279      *
280      * Since these numbers are all different powers of two, any combination of
281      * them is an integer in which each bit represents a different modifier
282      * key. Use 0 to specify no modifiers.
283      *
284      * @param keyChar the Character object for a keyboard character
285      * @param modifiers a bitwise-ored combination of any modifiers
286      * @return an <code>AWTKeyStroke</code> object for that key
287      * @throws IllegalArgumentException if <code>keyChar</code> is
288      * <code>null</code>
289      *
290      * @see java.awt.event.InputEvent
291      */

292     public static AWTKeyStroke JavaDoc getAWTKeyStroke(Character JavaDoc keyChar,
293                            int modifiers) {
294         if (keyChar == null) {
295         throw new IllegalArgumentException JavaDoc("keyChar cannot be null");
296     }
297         return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
298                    modifiers, false);
299     }
300
301     /**
302      * Returns a shared instance of an <code>AWTKeyStroke</code>,
303      * given a numeric key code and a set of modifiers, specifying
304      * whether the key is activated when it is pressed or released.
305      * <p>
306      * The "virtual key" constants defined in
307      * <code>java.awt.event.KeyEvent</code> can be
308      * used to specify the key code. For example:<ul>
309      * <li><code>java.awt.event.KeyEvent.VK_ENTER</code>
310      * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
311      * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
312      * </ul>
313      * The modifiers consist of any combination of:<ul>
314      * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
315      * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
316      * <li>java.awt.event.InputEvent.META_DOWN_MASK
317      * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
318      * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
319      * </ul>
320      * The old modifiers <ul>
321      * <li>java.awt.event.InputEvent.SHIFT_MASK
322      * <li>java.awt.event.InputEvent.CTRL_MASK
323      * <li>java.awt.event.InputEvent.META_MASK
324      * <li>java.awt.event.InputEvent.ALT_MASK
325      * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
326      * </ul>
327      * also can be used, but they are mapped to _DOWN_ modifiers.
328      *
329      * Since these numbers are all different powers of two, any combination of
330      * them is an integer in which each bit represents a different modifier
331      * key. Use 0 to specify no modifiers.
332      *
333      * @param keyCode an int specifying the numeric code for a keyboard key
334      * @param modifiers a bitwise-ored combination of any modifiers
335      * @param onKeyRelease <code>true</code> if the <code>AWTKeyStroke</code>
336      * should represent a key release; <code>false</code> otherwise
337      * @return an AWTKeyStroke object for that key
338      *
339      * @see java.awt.event.KeyEvent
340      * @see java.awt.event.InputEvent
341      */

342     public static AWTKeyStroke JavaDoc getAWTKeyStroke(int keyCode, int modifiers,
343                            boolean onKeyRelease) {
344         return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
345                    onKeyRelease);
346     }
347
348     /**
349      * Returns a shared instance of an <code>AWTKeyStroke</code>,
350      * given a numeric key code and a set of modifiers. The returned
351      * <code>AWTKeyStroke</code> will correspond to a key press.
352      * <p>
353      * The "virtual key" constants defined in
354      * <code>java.awt.event.KeyEvent</code> can be
355      * used to specify the key code. For example:<ul>
356      * <li><code>java.awt.event.KeyEvent.VK_ENTER</code>
357      * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
358      * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
359      * </ul>
360      * The modifiers consist of any combination of:<ul>
361      * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
362      * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
363      * <li>java.awt.event.InputEvent.META_DOWN_MASK
364      * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
365      * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
366      * </ul>
367      * The old modifiers <ul>
368      * <li>java.awt.event.InputEvent.SHIFT_MASK
369      * <li>java.awt.event.InputEvent.CTRL_MASK
370      * <li>java.awt.event.InputEvent.META_MASK
371      * <li>java.awt.event.InputEvent.ALT_MASK
372      * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
373      * </ul>
374      * also can be used, but they are mapped to _DOWN_ modifiers.
375      *
376      * Since these numbers are all different powers of two, any combination of
377      * them is an integer in which each bit represents a different modifier
378      * key. Use 0 to specify no modifiers.
379      *
380      * @param keyCode an int specifying the numeric code for a keyboard key
381      * @param modifiers a bitwise-ored combination of any modifiers
382      * @return an <code>AWTKeyStroke</code> object for that key
383      *
384      * @see java.awt.event.KeyEvent
385      * @see java.awt.event.InputEvent
386      */

387     public static AWTKeyStroke JavaDoc getAWTKeyStroke(int keyCode, int modifiers) {
388         return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
389                    false);
390     }
391
392     /**
393      * Returns an <code>AWTKeyStroke</code> which represents the
394      * stroke which generated a given <code>KeyEvent</code>.
395      * <p>
396      * This method obtains the keyChar from a <code>KeyTyped</code>
397      * event, and the keyCode from a <code>KeyPressed</code> or
398      * <code>KeyReleased</code> event. The <code>KeyEvent</code> modifiers are
399      * obtained for all three types of <code>KeyEvent</code>.
400      *
401      * @param anEvent the <code>KeyEvent</code> from which to
402      * obtain the <code>AWTKeyStroke</code>
403      * @throws NullPointerException if <code>anEvent</code> is null
404      * @return the <code>AWTKeyStroke</code> that precipitated the event
405      */

406     public static AWTKeyStroke JavaDoc getAWTKeyStrokeForEvent(KeyEvent JavaDoc anEvent) {
407         int id = anEvent.getID();
408         switch(id) {
409           case KeyEvent.KEY_PRESSED:
410           case KeyEvent.KEY_RELEASED:
411         return getCachedStroke(KeyEvent.CHAR_UNDEFINED,
412                    anEvent.getKeyCode(),
413                    anEvent.getModifiers(),
414                    (id == KeyEvent.KEY_RELEASED));
415           case KeyEvent.KEY_TYPED:
416         return getCachedStroke(anEvent.getKeyChar(),
417                    KeyEvent.VK_UNDEFINED,
418                    anEvent.getModifiers(),
419                    false);
420           default:
421             // Invalid ID for this KeyEvent
422
return null;
423         }
424     }
425
426     /**
427      * Parses a string and returns an <code>AWTKeyStroke</code>.
428      * The string must have the following syntax:
429      * <pre>
430      * &lt;modifiers&gt;* (&lt;typedID&gt; | &lt;pressedReleasedID&gt;)
431      *
432      * modifiers := shift | control | ctrl | meta | alt | altGraph
433      * typedID := typed &lt;typedKey&gt;
434      * typedKey := string of length 1 giving Unicode character.
435      * pressedReleasedID := (pressed | released) key
436      * key := KeyEvent key code name, i.e. the name following "VK_".
437      * </pre>
438      * If typed, pressed or released is not specified, pressed is assumed. Here
439      * are some examples:
440      * <pre>
441      * "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
442      * "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
443      * "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
444      * "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
445      * "typed a" => getAWTKeyStroke('a');
446      * </pre>
447      *
448      * @param s a String formatted as described above
449      * @return an <code>AWTKeyStroke</code> object for that String
450      * @throws IllegalArgumentException if <code>s</code> is <code>null</code>,
451      * or is formatted incorrectly
452      */

453     public static AWTKeyStroke JavaDoc getAWTKeyStroke(String JavaDoc s) {
454     if (s == null) {
455         throw new IllegalArgumentException JavaDoc("String cannot be null");
456     }
457
458         final String JavaDoc errmsg = "String formatted incorrectly";
459
460         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(s, " ");
461
462     int mask = 0;
463     boolean released = false;
464     boolean typed = false;
465     boolean pressed = false;
466
467         if (modifierKeywords == null) {
468         synchronized (AWTKeyStroke JavaDoc.class) {
469             if (modifierKeywords == null) {
470             Map JavaDoc uninitializedMap = new HashMap JavaDoc(8, 1.0f);
471             uninitializedMap.put("shift",
472                      new Integer JavaDoc(InputEvent.SHIFT_DOWN_MASK
473                              |InputEvent.SHIFT_MASK));
474             uninitializedMap.put("control",
475                      new Integer JavaDoc(InputEvent.CTRL_DOWN_MASK
476                              |InputEvent.CTRL_MASK));
477             uninitializedMap.put("ctrl",
478                      new Integer JavaDoc(InputEvent.CTRL_DOWN_MASK
479                              |InputEvent.CTRL_MASK));
480             uninitializedMap.put("meta",
481                      new Integer JavaDoc(InputEvent.META_DOWN_MASK
482                              |InputEvent.META_MASK));
483             uninitializedMap.put("alt",
484                      new Integer JavaDoc(InputEvent.ALT_DOWN_MASK
485                              |InputEvent.ALT_MASK));
486             uninitializedMap.put("altGraph",
487                      new Integer JavaDoc(InputEvent.ALT_GRAPH_DOWN_MASK
488                              |InputEvent.ALT_GRAPH_MASK));
489             uninitializedMap.put("button1",
490                      new Integer JavaDoc(InputEvent.BUTTON1_DOWN_MASK));
491             uninitializedMap.put("button2",
492                      new Integer JavaDoc(InputEvent.BUTTON2_DOWN_MASK));
493             uninitializedMap.put("button3",
494                      new Integer JavaDoc(InputEvent.BUTTON3_DOWN_MASK));
495             modifierKeywords =
496                 Collections.synchronizedMap(uninitializedMap);
497         }
498         }
499     }
500
501     int count = st.countTokens();
502
503     for (int i = 1; i <= count; i++) {
504         String JavaDoc token = st.nextToken();
505
506         if (typed) {
507             if (token.length() != 1 || i != count) {
508             throw new IllegalArgumentException JavaDoc(errmsg);
509         }
510         return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED,
511                        mask, false);
512         }
513
514         if (pressed || released || i == count) {
515             if (i != count) {
516             throw new IllegalArgumentException JavaDoc(errmsg);
517         }
518
519         String JavaDoc keyCodeName = "VK_" + token;
520         int keyCode = getVKValue(keyCodeName);
521
522         return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
523                        mask, released);
524         }
525
526         if (token.equals("released")) {
527         released = true;
528         continue;
529         }
530         if (token.equals("pressed")) {
531             pressed = true;
532         continue;
533         }
534         if (token.equals("typed")) {
535         typed = true;
536         continue;
537         }
538
539         Integer JavaDoc tokenMask = (Integer JavaDoc)modifierKeywords.get(token);
540         if (tokenMask != null) {
541         mask |= tokenMask.intValue();
542         } else {
543             throw new IllegalArgumentException JavaDoc(errmsg);
544         }
545     }
546
547     throw new IllegalArgumentException JavaDoc(errmsg);
548     }
549
550     private static VKCollection getVKCollection() {
551         if (vks == null) {
552             vks = new VKCollection();
553         }
554         return vks;
555     }
556     /**
557      * Returns the integer constant for the KeyEvent.VK field named
558      * <code>key</code>. This will throw an
559      * <code>IllegalArgumentException</code> if <code>key</code> is
560      * not a valid constant.
561      */

562     private static int getVKValue(String JavaDoc key) {
563         VKCollection vkCollect = getVKCollection();
564
565         Integer JavaDoc value = vkCollect.findCode(key);
566
567         if (value == null) {
568             int keyCode = 0;
569             final String JavaDoc errmsg = "String formatted incorrectly";
570
571             try {
572                 keyCode = KeyEvent JavaDoc.class.getField(key).getInt(KeyEvent JavaDoc.class);
573             } catch (NoSuchFieldException JavaDoc nsfe) {
574                 throw new IllegalArgumentException JavaDoc(errmsg);
575             } catch (IllegalAccessException JavaDoc iae) {
576                 throw new IllegalArgumentException JavaDoc(errmsg);
577             }
578             value = new Integer JavaDoc(keyCode);
579             vkCollect.put(key, value);
580         }
581         return value.intValue();
582     }
583
584     /**
585      * Returns the character for this <code>AWTKeyStroke</code>.
586      *
587      * @return a char value
588      * @see #getAWTKeyStroke(char)
589      */

590     public final char getKeyChar() {
591         return keyChar;
592     }
593
594     /**
595      * Returns the numeric key code for this <code>AWTKeyStroke</code>.
596      *
597      * @return an int containing the key code value
598      * @see #getAWTKeyStroke(int,int)
599      */

600     public final int getKeyCode() {
601         return keyCode;
602     }
603
604     /**
605      * Returns the modifier keys for this <code>AWTKeyStroke</code>.
606      *
607      * @return an int containing the modifiers
608      * @see #getAWTKeyStroke(int,int)
609      */

610     public final int getModifiers() {
611         return modifiers;
612     }
613
614     /**
615      * Returns whether this <code>AWTKeyStroke</code> represents a key release.
616      *
617      * @return <code>true</code> if this <code>AWTKeyStroke</code>
618      * represents a key release; <code>false</code> otherwise
619      * @see #getAWTKeyStroke(int,int,boolean)
620      */

621     public final boolean isOnKeyRelease() {
622         return onKeyRelease;
623     }
624
625     /**
626      * Returns the type of <code>KeyEvent</code> which corresponds to
627      * this <code>AWTKeyStroke</code>.
628      *
629      * @return <code>KeyEvent.KEY_PRESSED</code>,
630      * <code>KeyEvent.KEY_TYPED</code>,
631      * or <code>KeyEvent.KEY_RELEASED</code>
632      * @see java.awt.event.KeyEvent
633      */

634     public final int getKeyEventType() {
635     if (keyCode == KeyEvent.VK_UNDEFINED) {
636         return KeyEvent.KEY_TYPED;
637     } else {
638         return (onKeyRelease)
639         ? KeyEvent.KEY_RELEASED
640         : KeyEvent.KEY_PRESSED;
641     }
642     }
643
644     /**
645      * Returns a numeric value for this object that is likely to be unique,
646      * making it a good choice as the index value in a hash table.
647      *
648      * @return an int that represents this object
649      */

650     public int hashCode() {
651         return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) +
652             (onKeyRelease ? 1 : 2);
653     }
654
655     /**
656      * Returns true if this object is identical to the specified object.
657      *
658      * @param anObject the Object to compare this object to
659      * @return true if the objects are identical
660      */

661     public final boolean equals(Object JavaDoc anObject) {
662         if (anObject instanceof AWTKeyStroke JavaDoc) {
663             AWTKeyStroke JavaDoc ks = (AWTKeyStroke JavaDoc)anObject;
664         return (ks.keyChar == keyChar && ks.keyCode == keyCode &&
665             ks.onKeyRelease == onKeyRelease &&
666             ks.modifiers == modifiers);
667         }
668         return false;
669     }
670
671     /**
672      * Returns a string that displays and identifies this object's properties.
673      * The <code>String</code> returned by this method can be passed
674      * as a parameter to <code>getAWTKeyStroke(String)</code> to produce
675      * a key stroke equal to this key stroke.
676      *
677      * @return a String representation of this object
678      * @see #getAWTKeyStroke(String)
679      */

680     public String JavaDoc toString() {
681         if (keyCode == KeyEvent.VK_UNDEFINED) {
682             return getModifiersText(modifiers) + "typed " + keyChar;
683         } else {
684             return getModifiersText(modifiers) +
685                 (onKeyRelease ? "released" : "pressed") + " " +
686                 getVKText(keyCode);
687         }
688     }
689
690     static String JavaDoc getModifiersText(int modifiers) {
691         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
692
693         if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) {
694             buf.append("shift ");
695         }
696         if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) {
697             buf.append("ctrl ");
698         }
699         if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) {
700             buf.append("meta ");
701         }
702         if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
703             buf.append("alt ");
704         }
705         if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) {
706             buf.append("altGraph ");
707         }
708         if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) {
709             buf.append("button1 ");
710         }
711         if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) {
712             buf.append("button2 ");
713         }
714         if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) {
715             buf.append("button3 ");
716         }
717
718         return buf.toString();
719     }
720
721     static String JavaDoc getVKText(int keyCode) {
722         VKCollection vkCollect = getVKCollection();
723         Integer JavaDoc key = new Integer JavaDoc(keyCode);
724         String JavaDoc name = vkCollect.findName(key);
725         if (name != null) {
726             return name.substring(3);
727         }
728         int expected_modifiers =
729             (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
730
731         Field JavaDoc[] fields = KeyEvent JavaDoc.class.getDeclaredFields();
732         for (int i = 0; i < fields.length; i++) {
733             try {
734                 if (fields[i].getModifiers() == expected_modifiers
735                     && fields[i].getType() == Integer.TYPE
736                     && fields[i].getName().startsWith("VK_")
737                     && fields[i].getInt(KeyEvent JavaDoc.class) == keyCode)
738                 {
739                     name = fields[i].getName();
740                     vkCollect.put(name, key);
741                     return name.substring(3);
742                 }
743             } catch (IllegalAccessException JavaDoc e) {
744                 assert(false);
745             }
746         }
747         return "UNKNOWN";
748     }
749
750     /**
751      * Returns a cached instance of <code>AWTKeyStroke</code> (or a subclass of
752      * <code>AWTKeyStroke</code>) which is equal to this instance.
753      *
754      * @return a cached instance which is equal to this instance
755      */

756     protected Object JavaDoc readResolve() throws java.io.ObjectStreamException JavaDoc {
757         synchronized (AWTKeyStroke JavaDoc.class) {
758         Class JavaDoc newClass = getClass();
759         if (!newClass.equals(ctor.getDeclaringClass())) {
760             registerSubclass(newClass);
761         }
762         return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
763     }
764     }
765
766     private static int mapOldModifiers(int modifiers) {
767         if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
768         modifiers |= InputEvent.SHIFT_DOWN_MASK;
769     }
770     if ((modifiers & InputEvent.ALT_MASK) != 0) {
771         modifiers |= InputEvent.ALT_DOWN_MASK;
772     }
773     if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
774         modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
775     }
776     if ((modifiers & InputEvent.CTRL_MASK) != 0) {
777         modifiers |= InputEvent.CTRL_DOWN_MASK;
778     }
779     if ((modifiers & InputEvent.META_MASK) != 0) {
780         modifiers |= InputEvent.META_DOWN_MASK;
781     }
782
783     modifiers &= InputEvent.SHIFT_DOWN_MASK
784         | InputEvent.ALT_DOWN_MASK
785         | InputEvent.ALT_GRAPH_DOWN_MASK
786         | InputEvent.CTRL_DOWN_MASK
787         | InputEvent.META_DOWN_MASK
788         | InputEvent.BUTTON1_DOWN_MASK
789         | InputEvent.BUTTON2_DOWN_MASK
790         | InputEvent.BUTTON3_DOWN_MASK;
791     
792     return modifiers;
793     }
794
795     private static int mapNewModifiers(int modifiers) {
796         if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
797         modifiers |= InputEvent.SHIFT_MASK;
798     }
799     if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
800         modifiers |= InputEvent.ALT_MASK;
801     }
802     if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
803         modifiers |= InputEvent.ALT_GRAPH_MASK;
804     }
805     if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
806         modifiers |= InputEvent.CTRL_MASK;
807     }
808     if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
809         modifiers |= InputEvent.META_MASK;
810     }
811     
812     return modifiers;
813     }
814
815 }
816
817 class VKCollection {
818     Map JavaDoc code2name;
819     Map JavaDoc name2code;
820
821     public VKCollection() {
822         code2name = new HashMap JavaDoc();
823         name2code = new HashMap JavaDoc();
824     }
825
826     public synchronized void put(String JavaDoc name, Integer JavaDoc code) {
827         assert((name != null) && (code != null));
828         assert(findName(code) == null);
829         assert(findCode(name) == null);
830         code2name.put(code, name);
831         name2code.put(name, code);
832     }
833
834     public synchronized Integer JavaDoc findCode(String JavaDoc name) {
835         assert(name != null);
836         return (Integer JavaDoc)name2code.get(name);
837     }
838
839     public synchronized String JavaDoc findName(Integer JavaDoc code) {
840         assert(code != null);
841         return (String JavaDoc)code2name.get(code);
842     }
843 }
844
845
Popular Tags