- /*
- * @(#)AWTKeyStroke.java 1.23 04/05/05
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package java.awt;
-
- import java.awt.event.KeyEvent;
- import java.awt.event.InputEvent;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.StringTokenizer;
- import java.io.Serializable;
- import java.security.AccessController;
- import java.security.PrivilegedAction;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Modifier;
- import java.lang.reflect.Field;
-
- /**
- * An <code>AWTKeyStroke</code> represents a key action on the
- * keyboard, or equivalent input device. <code>AWTKeyStroke</code>s
- * can correspond to only a press or release of a
- * particular key, just as <code>KEY_PRESSED</code> and
- * <code>KEY_RELEASED</code> <code>KeyEvent</code>s do;
- * alternately, they can correspond to typing a specific Java character, just
- * as <code>KEY_TYPED</code> <code>KeyEvent</code>s do.
- * In all cases, <code>AWTKeyStroke</code>s can specify modifiers
- * (alt, shift, control, meta, or a combination thereof) which must be present
- * during the action for an exact match.
- * <p>
- * <code>AWTKeyStrokes</code> are immutable, and are intended
- * to be unique. Client code should never create an
- * <code>AWTKeyStroke</code> on its own, but should instead use
- * a variant of <code>getAWTKeyStroke</code>. Client use of these factory
- * methods allows the <code>AWTKeyStroke</code> implementation
- * to cache and share instances efficiently.
- *
- * @see #getAWTKeyStroke
- *
- * @version 1.23, 05/05/04
- * @author Arnaud Weber
- * @author David Mendenhall
- * @since 1.4
- */
- public class AWTKeyStroke implements Serializable {
- static final long serialVersionUID = -6430539691155161871L;
-
- private static Map cache;
- private static AWTKeyStroke cacheKey;
- private static Constructor ctor = getCtor(AWTKeyStroke.class);
- private static Map modifierKeywords;
- /**
- * Associates VK_XXX (as a String) with code (as Integer). This is
- * done to avoid the overhead of the reflective call to find the
- * constant.
- */
- private static VKCollection vks;
-
- private char keyChar = KeyEvent.CHAR_UNDEFINED;
- private int keyCode = KeyEvent.VK_UNDEFINED;
- private int modifiers;
- private boolean onKeyRelease;
-
- static {
- /* ensure that the necessary native libraries are loaded */
- Toolkit.loadLibraries();
- }
-
- /**
- * Constructs an <code>AWTKeyStroke</code> with default values.
- * The default values used are:
- * <table border="1" summary="AWTKeyStroke default values">
- * <tr><th>Property</th><th>Default Value</th></tr>
- * <tr>
- * <td>Key Char</td>
- * <td><code>KeyEvent.CHAR_UNDEFINED</code></td>
- * </tr>
- * <tr>
- * <td>Key Code</td>
- * <td><code>KeyEvent.VK_UNDEFINED</code></td>
- * </tr>
- * <tr>
- * <td>Modifiers</td>
- * <td>none</td>
- * </tr>
- * <tr>
- * <td>On key release?</td>
- * <td><code>false</code></td>
- * </tr>
- * </table>
- *
- * <code>AWTKeyStroke</code>s should not be constructed
- * by client code. Use a variant of <code>getAWTKeyStroke</code>
- * instead.
- *
- * @see #getAWTKeyStroke
- */
- protected AWTKeyStroke() {
- }
-
- /**
- * Constructs an <code>AWTKeyStroke</code> with the specified
- * values. <code>AWTKeyStroke</code>s should not be constructed
- * by client code. Use a variant of <code>getAWTKeyStroke</code>
- * instead.
- *
- * @param keyChar the character value for a keyboard key
- * @param keyCode the key code for this <code>AWTKeyStroke</code>
- * @param modifiers a bitwise-ored combination of any modifiers
- * @param onKeyRelease <code>true</code> if this
- * <code>AWTKeyStroke</code> corresponds
- * to a key release; <code>false</code> otherwise
- * @see #getAWTKeyStroke
- */
- protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
- boolean onKeyRelease) {
- this.keyChar = keyChar;
- this.keyCode = keyCode;
- this.modifiers = modifiers;
- this.onKeyRelease = onKeyRelease;
- }
-
- /**
- * Registers a new class which the factory methods in
- * <code>AWTKeyStroke</code> will use when generating new
- * instances of <code>AWTKeyStroke</code>s. After invoking this
- * method, the factory methods will return instances of the specified
- * Class. The specified Class must be either <code>AWTKeyStroke</code>
- * or derived from <code>AWTKeyStroke</code>, and it must have a
- * no-arg constructor. The constructor can be of any accessibility,
- * including <code>private</code>. This operation
- * flushes the current <code>AWTKeyStroke</code> cache.
- *
- * @param subclass the new Class of which the factory methods should create
- * instances
- * @throws IllegalArgumentException if subclass is <code>null</code>,
- * or if subclass does not have a no-arg constructor
- * @throws ClassCastException if subclass is not
- * <code>AWTKeyStroke</code>, or a class derived from
- * <code>AWTKeyStroke</code>
- */
- protected static void registerSubclass(Class<?> subclass) {
- if (subclass == null) {
- throw new IllegalArgumentException("subclass cannot be null");
- }
- if (AWTKeyStroke.ctor.getDeclaringClass().equals(subclass)) {
- // Already registered
- return;
- }
- if (!AWTKeyStroke.class.isAssignableFrom(subclass)) {
- throw new ClassCastException("subclass is not derived from AWTKeyStroke");
- }
-
- Constructor ctor = getCtor(subclass);
-
- String couldNotInstantiate = "subclass could not be instantiated";
-
- if (ctor == null) {
- throw new IllegalArgumentException(couldNotInstantiate);
- }
- try {
- AWTKeyStroke stroke = (AWTKeyStroke)ctor.newInstance(null);
- if (stroke == null) {
- throw new IllegalArgumentException(couldNotInstantiate);
- }
- } catch (NoSuchMethodError e) {
- throw new IllegalArgumentException(couldNotInstantiate);
- } catch (ExceptionInInitializerError e) {
- throw new IllegalArgumentException(couldNotInstantiate);
- } catch (InstantiationException e) {
- throw new IllegalArgumentException(couldNotInstantiate);
- } catch (IllegalAccessException e) {
- throw new IllegalArgumentException(couldNotInstantiate);
- } catch (InvocationTargetException e) {
- throw new IllegalArgumentException(couldNotInstantiate);
- }
-
- synchronized (AWTKeyStroke.class) {
- AWTKeyStroke.ctor = ctor;
- cache = null;
- cacheKey = null;
- }
- }
-
- /* returns noarg Constructor for class with accessible flag. No security
- threat as accessible flag is set only for this Constructor object,
- not for Class constructor.
- */
- private static Constructor getCtor(final Class clazz)
- {
- Object ctor = AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- try {
- Constructor ctor = clazz.getDeclaredConstructor(null);
- if (ctor != null) {
- ctor.setAccessible(true);
- }
- return ctor;
- } catch (SecurityException e) {
- } catch (NoSuchMethodException e) {
- }
- return null;
- }
- });
- return (Constructor)ctor;
- }
-
- private static synchronized AWTKeyStroke getCachedStroke
- (char keyChar, int keyCode, int modifiers, boolean onKeyRelease)
- {
- if (cache == null) {
- cache = new HashMap();
- }
-
- if (cacheKey == null) {
- try {
- cacheKey = (AWTKeyStroke)ctor.newInstance(null);
- } catch (InstantiationException e) {
- assert(false);
- } catch (IllegalAccessException e) {
- assert(false);
- } catch (InvocationTargetException e) {
- assert(false);
- }
- }
- cacheKey.keyChar = keyChar;
- cacheKey.keyCode = keyCode;
- cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers));
- cacheKey.onKeyRelease = onKeyRelease;
-
- AWTKeyStroke stroke = (AWTKeyStroke)cache.get(cacheKey);
- if (stroke == null) {
- stroke = cacheKey;
- cache.put(stroke, stroke);
- cacheKey = null;
- }
-
- return stroke;
- }
-
- /**
- * Returns a shared instance of an <code>AWTKeyStroke</code>
- * that represents a <code>KEY_TYPED</code> event for the
- * specified character.
- *
- * @param keyChar the character value for a keyboard key
- * @return an <code>AWTKeyStroke</code> object for that key
- */
- public static AWTKeyStroke getAWTKeyStroke(char keyChar) {
- return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
- }
-
- /**
- * Returns a shared instance of an <code>AWTKeyStroke</code>,
- * given a Character object and a set of modifiers. Note
- * that the first parameter is of type Character rather than
- * char. This is to avoid inadvertent clashes with
- * calls to <code>getAWTKeyStroke(int keyCode, int modifiers)</code>.
- *
- * The modifiers consist of any combination of:<ul>
- * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
- * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
- * <li>java.awt.event.InputEvent.META_DOWN_MASK
- * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
- * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
- * </ul>
- * The old modifiers <ul>
- * <li>java.awt.event.InputEvent.SHIFT_MASK
- * <li>java.awt.event.InputEvent.CTRL_MASK
- * <li>java.awt.event.InputEvent.META_MASK
- * <li>java.awt.event.InputEvent.ALT_MASK
- * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
- * </ul>
- * also can be used, but they are mapped to _DOWN_ modifiers.
- *
- * Since these numbers are all different powers of two, any combination of
- * them is an integer in which each bit represents a different modifier
- * key. Use 0 to specify no modifiers.
- *
- * @param keyChar the Character object for a keyboard character
- * @param modifiers a bitwise-ored combination of any modifiers
- * @return an <code>AWTKeyStroke</code> object for that key
- * @throws IllegalArgumentException if <code>keyChar</code> is
- * <code>null</code>
- *
- * @see java.awt.event.InputEvent
- */
- public static AWTKeyStroke getAWTKeyStroke(Character keyChar,
- int modifiers) {
- if (keyChar == null) {
- throw new IllegalArgumentException("keyChar cannot be null");
- }
- return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
- modifiers, false);
- }
-
- /**
- * Returns a shared instance of an <code>AWTKeyStroke</code>,
- * given a numeric key code and a set of modifiers, specifying
- * whether the key is activated when it is pressed or released.
- * <p>
- * The "virtual key" constants defined in
- * <code>java.awt.event.KeyEvent</code> can be
- * used to specify the key code. For example:<ul>
- * <li><code>java.awt.event.KeyEvent.VK_ENTER</code>
- * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
- * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
- * </ul>
- * The modifiers consist of any combination of:<ul>
- * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
- * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
- * <li>java.awt.event.InputEvent.META_DOWN_MASK
- * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
- * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
- * </ul>
- * The old modifiers <ul>
- * <li>java.awt.event.InputEvent.SHIFT_MASK
- * <li>java.awt.event.InputEvent.CTRL_MASK
- * <li>java.awt.event.InputEvent.META_MASK
- * <li>java.awt.event.InputEvent.ALT_MASK
- * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
- * </ul>
- * also can be used, but they are mapped to _DOWN_ modifiers.
- *
- * Since these numbers are all different powers of two, any combination of
- * them is an integer in which each bit represents a different modifier
- * key. Use 0 to specify no modifiers.
- *
- * @param keyCode an int specifying the numeric code for a keyboard key
- * @param modifiers a bitwise-ored combination of any modifiers
- * @param onKeyRelease <code>true</code> if the <code>AWTKeyStroke</code>
- * should represent a key release; <code>false</code> otherwise
- * @return an AWTKeyStroke object for that key
- *
- * @see java.awt.event.KeyEvent
- * @see java.awt.event.InputEvent
- */
- public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
- boolean onKeyRelease) {
- return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
- onKeyRelease);
- }
-
- /**
- * Returns a shared instance of an <code>AWTKeyStroke</code>,
- * given a numeric key code and a set of modifiers. The returned
- * <code>AWTKeyStroke</code> will correspond to a key press.
- * <p>
- * The "virtual key" constants defined in
- * <code>java.awt.event.KeyEvent</code> can be
- * used to specify the key code. For example:<ul>
- * <li><code>java.awt.event.KeyEvent.VK_ENTER</code>
- * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
- * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
- * </ul>
- * The modifiers consist of any combination of:<ul>
- * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
- * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
- * <li>java.awt.event.InputEvent.META_DOWN_MASK
- * <li>java.awt.event.InputEvent.ALT_DOWN_MASK
- * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
- * </ul>
- * The old modifiers <ul>
- * <li>java.awt.event.InputEvent.SHIFT_MASK
- * <li>java.awt.event.InputEvent.CTRL_MASK
- * <li>java.awt.event.InputEvent.META_MASK
- * <li>java.awt.event.InputEvent.ALT_MASK
- * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
- * </ul>
- * also can be used, but they are mapped to _DOWN_ modifiers.
- *
- * Since these numbers are all different powers of two, any combination of
- * them is an integer in which each bit represents a different modifier
- * key. Use 0 to specify no modifiers.
- *
- * @param keyCode an int specifying the numeric code for a keyboard key
- * @param modifiers a bitwise-ored combination of any modifiers
- * @return an <code>AWTKeyStroke</code> object for that key
- *
- * @see java.awt.event.KeyEvent
- * @see java.awt.event.InputEvent
- */
- public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) {
- return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
- false);
- }
-
- /**
- * Returns an <code>AWTKeyStroke</code> which represents the
- * stroke which generated a given <code>KeyEvent</code>.
- * <p>
- * This method obtains the keyChar from a <code>KeyTyped</code>
- * event, and the keyCode from a <code>KeyPressed</code> or
- * <code>KeyReleased</code> event. The <code>KeyEvent</code> modifiers are
- * obtained for all three types of <code>KeyEvent</code>.
- *
- * @param anEvent the <code>KeyEvent</code> from which to
- * obtain the <code>AWTKeyStroke</code>
- * @throws NullPointerException if <code>anEvent</code> is null
- * @return the <code>AWTKeyStroke</code> that precipitated the event
- */
- public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) {
- int id = anEvent.getID();
- switch(id) {
- case KeyEvent.KEY_PRESSED:
- case KeyEvent.KEY_RELEASED:
- return getCachedStroke(KeyEvent.CHAR_UNDEFINED,
- anEvent.getKeyCode(),
- anEvent.getModifiers(),
- (id == KeyEvent.KEY_RELEASED));
- case KeyEvent.KEY_TYPED:
- return getCachedStroke(anEvent.getKeyChar(),
- KeyEvent.VK_UNDEFINED,
- anEvent.getModifiers(),
- false);
- default:
- // Invalid ID for this KeyEvent
- return null;
- }
- }
-
- /**
- * Parses a string and returns an <code>AWTKeyStroke</code>.
- * The string must have the following syntax:
- * <pre>
- * <modifiers>* (<typedID> | <pressedReleasedID>)
- *
- * modifiers := shift | control | ctrl | meta | alt | altGraph
- * typedID := typed <typedKey>
- * typedKey := string of length 1 giving Unicode character.
- * pressedReleasedID := (pressed | released) key
- * key := KeyEvent key code name, i.e. the name following "VK_".
- * </pre>
- * If typed, pressed or released is not specified, pressed is assumed. Here
- * are some examples:
- * <pre>
- * "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
- * "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
- * "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
- * "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
- * "typed a" => getAWTKeyStroke('a');
- * </pre>
- *
- * @param s a String formatted as described above
- * @return an <code>AWTKeyStroke</code> object for that String
- * @throws IllegalArgumentException if <code>s</code> is <code>null</code>,
- * or is formatted incorrectly
- */
- public static AWTKeyStroke getAWTKeyStroke(String s) {
- if (s == null) {
- throw new IllegalArgumentException("String cannot be null");
- }
-
- final String errmsg = "String formatted incorrectly";
-
- StringTokenizer st = new StringTokenizer(s, " ");
-
- int mask = 0;
- boolean released = false;
- boolean typed = false;
- boolean pressed = false;
-
- if (modifierKeywords == null) {
- synchronized (AWTKeyStroke.class) {
- if (modifierKeywords == null) {
- Map uninitializedMap = new HashMap(8, 1.0f);
- uninitializedMap.put("shift",
- new Integer(InputEvent.SHIFT_DOWN_MASK
- |InputEvent.SHIFT_MASK));
- uninitializedMap.put("control",
- new Integer(InputEvent.CTRL_DOWN_MASK
- |InputEvent.CTRL_MASK));
- uninitializedMap.put("ctrl",
- new Integer(InputEvent.CTRL_DOWN_MASK
- |InputEvent.CTRL_MASK));
- uninitializedMap.put("meta",
- new Integer(InputEvent.META_DOWN_MASK
- |InputEvent.META_MASK));
- uninitializedMap.put("alt",
- new Integer(InputEvent.ALT_DOWN_MASK
- |InputEvent.ALT_MASK));
- uninitializedMap.put("altGraph",
- new Integer(InputEvent.ALT_GRAPH_DOWN_MASK
- |InputEvent.ALT_GRAPH_MASK));
- uninitializedMap.put("button1",
- new Integer(InputEvent.BUTTON1_DOWN_MASK));
- uninitializedMap.put("button2",
- new Integer(InputEvent.BUTTON2_DOWN_MASK));
- uninitializedMap.put("button3",
- new Integer(InputEvent.BUTTON3_DOWN_MASK));
- modifierKeywords =
- Collections.synchronizedMap(uninitializedMap);
- }
- }
- }
-
- int count = st.countTokens();
-
- for (int i = 1; i <= count; i++) {
- String token = st.nextToken();
-
- if (typed) {
- if (token.length() != 1 || i != count) {
- throw new IllegalArgumentException(errmsg);
- }
- return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED,
- mask, false);
- }
-
- if (pressed || released || i == count) {
- if (i != count) {
- throw new IllegalArgumentException(errmsg);
- }
-
- String keyCodeName = "VK_" + token;
- int keyCode = getVKValue(keyCodeName);
-
- return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
- mask, released);
- }
-
- if (token.equals("released")) {
- released = true;
- continue;
- }
- if (token.equals("pressed")) {
- pressed = true;
- continue;
- }
- if (token.equals("typed")) {
- typed = true;
- continue;
- }
-
- Integer tokenMask = (Integer)modifierKeywords.get(token);
- if (tokenMask != null) {
- mask |= tokenMask.intValue();
- } else {
- throw new IllegalArgumentException(errmsg);
- }
- }
-
- throw new IllegalArgumentException(errmsg);
- }
-
- private static VKCollection getVKCollection() {
- if (vks == null) {
- vks = new VKCollection();
- }
- return vks;
- }
- /**
- * Returns the integer constant for the KeyEvent.VK field named
- * <code>key</code>. This will throw an
- * <code>IllegalArgumentException</code> if <code>key</code> is
- * not a valid constant.
- */
- private static int getVKValue(String key) {
- VKCollection vkCollect = getVKCollection();
-
- Integer value = vkCollect.findCode(key);
-
- if (value == null) {
- int keyCode = 0;
- final String errmsg = "String formatted incorrectly";
-
- try {
- keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class);
- } catch (NoSuchFieldException nsfe) {
- throw new IllegalArgumentException(errmsg);
- } catch (IllegalAccessException iae) {
- throw new IllegalArgumentException(errmsg);
- }
- value = new Integer(keyCode);
- vkCollect.put(key, value);
- }
- return value.intValue();
- }
-
- /**
- * Returns the character for this <code>AWTKeyStroke</code>.
- *
- * @return a char value
- * @see #getAWTKeyStroke(char)
- */
- public final char getKeyChar() {
- return keyChar;
- }
-
- /**
- * Returns the numeric key code for this <code>AWTKeyStroke</code>.
- *
- * @return an int containing the key code value
- * @see #getAWTKeyStroke(int,int)
- */
- public final int getKeyCode() {
- return keyCode;
- }
-
- /**
- * Returns the modifier keys for this <code>AWTKeyStroke</code>.
- *
- * @return an int containing the modifiers
- * @see #getAWTKeyStroke(int,int)
- */
- public final int getModifiers() {
- return modifiers;
- }
-
- /**
- * Returns whether this <code>AWTKeyStroke</code> represents a key release.
- *
- * @return <code>true</code> if this <code>AWTKeyStroke</code>
- * represents a key release; <code>false</code> otherwise
- * @see #getAWTKeyStroke(int,int,boolean)
- */
- public final boolean isOnKeyRelease() {
- return onKeyRelease;
- }
-
- /**
- * Returns the type of <code>KeyEvent</code> which corresponds to
- * this <code>AWTKeyStroke</code>.
- *
- * @return <code>KeyEvent.KEY_PRESSED</code>,
- * <code>KeyEvent.KEY_TYPED</code>,
- * or <code>KeyEvent.KEY_RELEASED</code>
- * @see java.awt.event.KeyEvent
- */
- public final int getKeyEventType() {
- if (keyCode == KeyEvent.VK_UNDEFINED) {
- return KeyEvent.KEY_TYPED;
- } else {
- return (onKeyRelease)
- ? KeyEvent.KEY_RELEASED
- : KeyEvent.KEY_PRESSED;
- }
- }
-
- /**
- * Returns a numeric value for this object that is likely to be unique,
- * making it a good choice as the index value in a hash table.
- *
- * @return an int that represents this object
- */
- public int hashCode() {
- return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) +
- (onKeyRelease ? 1 : 2);
- }
-
- /**
- * Returns true if this object is identical to the specified object.
- *
- * @param anObject the Object to compare this object to
- * @return true if the objects are identical
- */
- public final boolean equals(Object anObject) {
- if (anObject instanceof AWTKeyStroke) {
- AWTKeyStroke ks = (AWTKeyStroke)anObject;
- return (ks.keyChar == keyChar && ks.keyCode == keyCode &&
- ks.onKeyRelease == onKeyRelease &&
- ks.modifiers == modifiers);
- }
- return false;
- }
-
- /**
- * Returns a string that displays and identifies this object's properties.
- * The <code>String</code> returned by this method can be passed
- * as a parameter to <code>getAWTKeyStroke(String)</code> to produce
- * a key stroke equal to this key stroke.
- *
- * @return a String representation of this object
- * @see #getAWTKeyStroke(String)
- */
- public String toString() {
- if (keyCode == KeyEvent.VK_UNDEFINED) {
- return getModifiersText(modifiers) + "typed " + keyChar;
- } else {
- return getModifiersText(modifiers) +
- (onKeyRelease ? "released" : "pressed") + " " +
- getVKText(keyCode);
- }
- }
-
- static String getModifiersText(int modifiers) {
- StringBuffer buf = new StringBuffer();
-
- if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) {
- buf.append("shift ");
- }
- if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) {
- buf.append("ctrl ");
- }
- if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) {
- buf.append("meta ");
- }
- if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
- buf.append("alt ");
- }
- if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) {
- buf.append("altGraph ");
- }
- if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) {
- buf.append("button1 ");
- }
- if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) {
- buf.append("button2 ");
- }
- if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) {
- buf.append("button3 ");
- }
-
- return buf.toString();
- }
-
- static String getVKText(int keyCode) {
- VKCollection vkCollect = getVKCollection();
- Integer key = new Integer(keyCode);
- String name = vkCollect.findName(key);
- if (name != null) {
- return name.substring(3);
- }
- int expected_modifiers =
- (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
-
- Field[] fields = KeyEvent.class.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- try {
- if (fields[i].getModifiers() == expected_modifiers
- && fields[i].getType() == Integer.TYPE
- && fields[i].getName().startsWith("VK_")
- && fields[i].getInt(KeyEvent.class) == keyCode)
- {
- name = fields[i].getName();
- vkCollect.put(name, key);
- return name.substring(3);
- }
- } catch (IllegalAccessException e) {
- assert(false);
- }
- }
- return "UNKNOWN";
- }
-
- /**
- * Returns a cached instance of <code>AWTKeyStroke</code> (or a subclass of
- * <code>AWTKeyStroke</code>) which is equal to this instance.
- *
- * @return a cached instance which is equal to this instance
- */
- protected Object readResolve() throws java.io.ObjectStreamException {
- synchronized (AWTKeyStroke.class) {
- Class newClass = getClass();
- if (!newClass.equals(ctor.getDeclaringClass())) {
- registerSubclass(newClass);
- }
- return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
- }
- }
-
- private static int mapOldModifiers(int modifiers) {
- if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
- modifiers |= InputEvent.SHIFT_DOWN_MASK;
- }
- if ((modifiers & InputEvent.ALT_MASK) != 0) {
- modifiers |= InputEvent.ALT_DOWN_MASK;
- }
- if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
- modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
- }
- if ((modifiers & InputEvent.CTRL_MASK) != 0) {
- modifiers |= InputEvent.CTRL_DOWN_MASK;
- }
- if ((modifiers & InputEvent.META_MASK) != 0) {
- modifiers |= InputEvent.META_DOWN_MASK;
- }
-
- modifiers &= InputEvent.SHIFT_DOWN_MASK
- | InputEvent.ALT_DOWN_MASK
- | InputEvent.ALT_GRAPH_DOWN_MASK
- | InputEvent.CTRL_DOWN_MASK
- | InputEvent.META_DOWN_MASK
- | InputEvent.BUTTON1_DOWN_MASK
- | InputEvent.BUTTON2_DOWN_MASK
- | InputEvent.BUTTON3_DOWN_MASK;
-
- return modifiers;
- }
-
- private static int mapNewModifiers(int modifiers) {
- if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
- modifiers |= InputEvent.SHIFT_MASK;
- }
- if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
- modifiers |= InputEvent.ALT_MASK;
- }
- if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
- modifiers |= InputEvent.ALT_GRAPH_MASK;
- }
- if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
- modifiers |= InputEvent.CTRL_MASK;
- }
- if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
- modifiers |= InputEvent.META_MASK;
- }
-
- return modifiers;
- }
-
- }
-
- class VKCollection {
- Map code2name;
- Map name2code;
-
- public VKCollection() {
- code2name = new HashMap();
- name2code = new HashMap();
- }
-
- public synchronized void put(String name, Integer code) {
- assert((name != null) && (code != null));
- assert(findName(code) == null);
- assert(findCode(name) == null);
- code2name.put(code, name);
- name2code.put(name, code);
- }
-
- public synchronized Integer findCode(String name) {
- assert(name != null);
- return (Integer)name2code.get(name);
- }
-
- public synchronized String findName(Integer code) {
- assert(code != null);
- return (String)code2name.get(code);
- }
- }
-