/*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
import sun.awt.AppContext;
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 AWTKeyStroke
represents a key action on the
* keyboard, or equivalent input device. AWTKeyStroke
s
* can correspond to only a press or release of a
* particular key, just as KEY_PRESSED
and
* KEY_RELEASED
KeyEvent
s do;
* alternately, they can correspond to typing a specific Java character, just
* as KEY_TYPED
KeyEvent
s do.
* In all cases, AWTKeyStroke
s can specify modifiers
* (alt, shift, control, meta, altGraph, or a combination thereof) which must be present
* during the action for an exact match.
*
* AWTKeyStrokes
are immutable, and are intended
* to be unique. Client code should never create an
* AWTKeyStroke
on its own, but should instead use
* a variant of getAWTKeyStroke
. Client use of these factory
* methods allows the AWTKeyStroke
implementation
* to cache and share instances efficiently.
*
* @see #getAWTKeyStroke
*
* @author Arnaud Weber
* @author David Mendenhall
* @since 1.4
*/
public class AWTKeyStroke implements Serializable {
static final long serialVersionUID = -6430539691155161871L;
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;
//A key for the collection of AWTKeyStrokes within AppContext.
private static Object APP_CONTEXT_CACHE_KEY = new Object();
//A key withing the cache
private static AWTKeyStroke APP_CONTEXT_KEYSTROKE_KEY = new AWTKeyStroke();
/*
* Reads keystroke class from AppContext and if null, puts there the
* AWTKeyStroke class.
* Must be called under locked AWTKeyStro
*/
private static Class getAWTKeyStrokeClass() {
Class clazz = (Class)AppContext.getAppContext().get(AWTKeyStroke.class);
if (clazz == null) {
clazz = AWTKeyStroke.class;
AppContext.getAppContext().put(AWTKeyStroke.class, AWTKeyStroke.class);
}
return clazz;
}
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 AWTKeyStroke
with default values.
* The default values used are:
*
Property | Default Value |
---|---|
Key Char | *KeyEvent.CHAR_UNDEFINED |
*
Key Code | *KeyEvent.VK_UNDEFINED |
*
Modifiers | *none | *
On key release? | *false |
*
AWTKeyStroke
s should not be constructed
* by client code. Use a variant of getAWTKeyStroke
* instead.
*
* @see #getAWTKeyStroke
*/
protected AWTKeyStroke() {
}
/**
* Constructs an AWTKeyStroke
with the specified
* values. AWTKeyStroke
s should not be constructed
* by client code. Use a variant of getAWTKeyStroke
* instead.
*
* @param keyChar the character value for a keyboard key
* @param keyCode the key code for this AWTKeyStroke
* @param modifiers a bitwise-ored combination of any modifiers
* @param onKeyRelease true
if this
* AWTKeyStroke
corresponds
* to a key release; false
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
* AWTKeyStroke
will use when generating new
* instances of AWTKeyStroke
s. After invoking this
* method, the factory methods will return instances of the specified
* Class. The specified Class must be either AWTKeyStroke
* or derived from AWTKeyStroke
, and it must have a
* no-arg constructor. The constructor can be of any accessibility,
* including private
. This operation
* flushes the current AWTKeyStroke
cache.
*
* @param subclass the new Class of which the factory methods should create
* instances
* @throws IllegalArgumentException if subclass is null
,
* or if subclass does not have a no-arg constructor
* @throws ClassCastException if subclass is not
* AWTKeyStroke
, or a class derived from
* AWTKeyStroke
*/
protected static void registerSubclass(Class> subclass) {
if (subclass == null) {
throw new IllegalArgumentException("subclass cannot be null");
}
synchronized (AWTKeyStroke.class) {
Class keyStrokeClass = (Class)AppContext.getAppContext().get(AWTKeyStroke.class);
if (keyStrokeClass != null && keyStrokeClass.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((Object[]) 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) {
AppContext.getAppContext().put(AWTKeyStroke.class, subclass);
AppContext.getAppContext().remove(APP_CONTEXT_CACHE_KEY);
AppContext.getAppContext().remove(APP_CONTEXT_KEYSTROKE_KEY);
}
}
/* 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((Class[]) 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)
{
Map cache = (Map)AppContext.getAppContext().get(APP_CONTEXT_CACHE_KEY);
AWTKeyStroke cacheKey = (AWTKeyStroke)AppContext.getAppContext().get(APP_CONTEXT_KEYSTROKE_KEY);
if (cache == null) {
cache = new HashMap();
AppContext.getAppContext().put(APP_CONTEXT_CACHE_KEY, cache);
}
if (cacheKey == null) {
try {
Class clazz = getAWTKeyStrokeClass();
cacheKey = (AWTKeyStroke)getCtor(clazz).newInstance((Object[]) null);
AppContext.getAppContext().put(APP_CONTEXT_KEYSTROKE_KEY, cacheKey);
} 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);
AppContext.getAppContext().remove(APP_CONTEXT_KEYSTROKE_KEY);
}
return stroke;
}
/**
* Returns a shared instance of an AWTKeyStroke
* that represents a KEY_TYPED
event for the
* specified character.
*
* @param keyChar the character value for a keyboard key
* @return an AWTKeyStroke
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}
* that represents a {@code KEY_TYPED} event for the
* specified 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 getAWTKeyStroke(int keyCode, int modifiers)
.
*
* The modifiers consist of any combination of following:AWTKeyStroke
object for that key
* @throws IllegalArgumentException if keyChar
is
* null
*
* @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 AWTKeyStroke
,
* given a numeric key code and a set of modifiers, specifying
* whether the key is activated when it is pressed or released.
*
* The "virtual key" constants defined in
* java.awt.event.KeyEvent
can be
* used to specify the key code. For example:
java.awt.event.KeyEvent.VK_ENTER
* java.awt.event.KeyEvent.VK_TAB
* java.awt.event.KeyEvent.VK_SPACE
* java.awt.event.KeyEvent.getExtendedKeyCodeForChar
.
*
* The modifiers consist of any combination of:true
if the AWTKeyStroke
* should represent a key release; false
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 AWTKeyStroke
,
* given a numeric key code and a set of modifiers. The returned
* AWTKeyStroke
will correspond to a key press.
*
* The "virtual key" constants defined in
* java.awt.event.KeyEvent
can be
* used to specify the key code. For example:
java.awt.event.KeyEvent.VK_ENTER
* java.awt.event.KeyEvent.VK_TAB
* java.awt.event.KeyEvent.VK_SPACE
* AWTKeyStroke
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 AWTKeyStroke
which represents the
* stroke which generated a given KeyEvent
.
*
* This method obtains the keyChar from a KeyTyped
* event, and the keyCode from a KeyPressed
or
* KeyReleased
event. The KeyEvent
modifiers are
* obtained for all three types of KeyEvent
.
*
* @param anEvent the KeyEvent
from which to
* obtain the AWTKeyStroke
* @throws NullPointerException if anEvent
is null
* @return the AWTKeyStroke
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 AWTKeyStroke
.
* The string must have the following syntax:
*
* <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_". ** If typed, pressed or released is not specified, pressed is assumed. Here * are some examples: *
* "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'); ** * @param s a String formatted as described above * @return an
AWTKeyStroke
object for that String
* @throws IllegalArgumentException if s
is null
,
* 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;
synchronized (AWTKeyStroke.class) {
if (modifierKeywords == null) {
Map uninitializedMap = new HashMap(8, 1.0f);
uninitializedMap.put("shift",
Integer.valueOf(InputEvent.SHIFT_DOWN_MASK
|InputEvent.SHIFT_MASK));
uninitializedMap.put("control",
Integer.valueOf(InputEvent.CTRL_DOWN_MASK
|InputEvent.CTRL_MASK));
uninitializedMap.put("ctrl",
Integer.valueOf(InputEvent.CTRL_DOWN_MASK
|InputEvent.CTRL_MASK));
uninitializedMap.put("meta",
Integer.valueOf(InputEvent.META_DOWN_MASK
|InputEvent.META_MASK));
uninitializedMap.put("alt",
Integer.valueOf(InputEvent.ALT_DOWN_MASK
|InputEvent.ALT_MASK));
uninitializedMap.put("altGraph",
Integer.valueOf(InputEvent.ALT_GRAPH_DOWN_MASK
|InputEvent.ALT_GRAPH_MASK));
uninitializedMap.put("button1",
Integer.valueOf(InputEvent.BUTTON1_DOWN_MASK));
uninitializedMap.put("button2",
Integer.valueOf(InputEvent.BUTTON2_DOWN_MASK));
uninitializedMap.put("button3",
Integer.valueOf(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
* key
. This will throw an
* IllegalArgumentException
if key
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 = Integer.valueOf(keyCode);
vkCollect.put(key, value);
}
return value.intValue();
}
/**
* Returns the character for this AWTKeyStroke
.
*
* @return a char value
* @see #getAWTKeyStroke(char)
* @see KeyEvent#getKeyChar
*/
public final char getKeyChar() {
return keyChar;
}
/**
* Returns the numeric key code for this AWTKeyStroke
.
*
* @return an int containing the key code value
* @see #getAWTKeyStroke(int,int)
* @see KeyEvent#getKeyCode
*/
public final int getKeyCode() {
return keyCode;
}
/**
* Returns the modifier keys for this AWTKeyStroke
.
*
* @return an int containing the modifiers
* @see #getAWTKeyStroke(int,int)
*/
public final int getModifiers() {
return modifiers;
}
/**
* Returns whether this AWTKeyStroke
represents a key release.
*
* @return true
if this AWTKeyStroke
* represents a key release; false
otherwise
* @see #getAWTKeyStroke(int,int,boolean)
*/
public final boolean isOnKeyRelease() {
return onKeyRelease;
}
/**
* Returns the type of KeyEvent
which corresponds to
* this AWTKeyStroke
.
*
* @return KeyEvent.KEY_PRESSED
,
* KeyEvent.KEY_TYPED
,
* or KeyEvent.KEY_RELEASED
* @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 String
returned by this method can be passed
* as a parameter to getAWTKeyStroke(String)
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) {
StringBuilder buf = new StringBuilder();
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 = Integer.valueOf(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 AWTKeyStroke
(or a subclass of
* AWTKeyStroke
) 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) {
if (getClass().equals(getAWTKeyStrokeClass())) {
return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
}
}
return this;
}
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);
}
}