/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Dmitry A. Durnev * @version $Revision$ */ package java.awt; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.io.ObjectStreamException; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; import java.util.StringTokenizer; import org.apache.harmony.awt.internal.nls.Messages; /** * The AWTKeyStroke holds all of the information for the complete act of * typing a character. This includes the events that are generated when * the key is pressed, released, or typed (pressed and released generating * a Unicode character result) which are associated with the event * objects KeyEvent.KEY_PRESSED, KeyEvent.KEY_RELEASED, or KeyEvent.KEY_TYPED. * It also holds information about which modifiers (such as control or * shift) were used in conjunction with the keystroke. The following masks * are available to identify the modifiers: *
* <modifiers>* (<typedID> | <pressedReleasedID>) *
* modifiers := shift | control | ctrl | meta | alt | altGraph
*
* @param s
* the String which contains key stroke parameters.
* @return the AWTKeyStroke for string.
* @throws IllegalArgumentException
* if string has incorrect format or null.
*/
public static AWTKeyStroke getAWTKeyStroke(String s) {
if (s == null) {
// awt.65=null argument
throw new IllegalArgumentException(Messages.getString("awt.65")); //$NON-NLS-1$
}
StringTokenizer tokenizer = new StringTokenizer(s);
Boolean release = null;
int modifiers = 0;
int keyCode = KeyEvent.VK_UNDEFINED;
char keyChar = KeyEvent.CHAR_UNDEFINED;
boolean typed = false;
long modifier = 0;
String token = null;
do {
token = getNextToken(tokenizer);
modifier = parseModifier(token);
modifiers |= modifier;
} while (modifier > 0);
typed = parseTypedID(token);
if (typed) {
token = getNextToken(tokenizer);
keyChar = parseTypedKey(token);
}
if (keyChar == KeyEvent.CHAR_UNDEFINED) {
release = parsePressedReleasedID(token);
if (release != null) {
token = getNextToken(tokenizer);
}
keyCode = parseKey(token);
}
if (tokenizer.hasMoreTokens()) {
// awt.66=Invalid format
throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
}
return getAWTKeyStroke(keyChar, keyCode, modifiers, release == Boolean.TRUE);
}
/**
* Gets the next token.
*
* @param tokenizer
* the tokenizer.
* @return the next token.
*/
private static String getNextToken(StringTokenizer tokenizer) {
try {
return tokenizer.nextToken();
} catch (NoSuchElementException exception) {
// awt.66=Invalid format
throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
}
}
/**
* Gets the key code.
*
* @param s
* the s.
* @return the key code.
*/
static int getKeyCode(String s) {
try {
Field vk = KeyEvent.class.getField("VK_" + s); //$NON-NLS-1$
return vk.getInt(null);
} catch (Exception e) {
if (s.length() != 1) {
// awt.66=Invalid format
throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
}
return KeyEvent.VK_UNDEFINED;
}
}
/**
* Gets an instance of the AWTKeyStroke for specified character.
*
* @param keyChar
* the keyboard character value.
* @return a AWTKeyStroke for specified character.
*/
public static AWTKeyStroke getAWTKeyStroke(char keyChar) {
return getAWTKeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
}
/**
* Returns an instance of AWTKeyStroke for a given key code, set of
* modifiers, and specified key released flag value. The key codes are
* defined in java.awt.event.KeyEvent class. The set of modifiers is given
* as a bitwise combination of masks taken from the following list:
*
* typedID := typed
* typedKey := string of length 1 giving the Unicode character.
* pressedReleasedID := (pressed | released)
* key := KeyEvent key code name, i.e. the name following "VK_".
*
*
*
*
* @param keyCode
* the specified key code of keyboard.
* @param modifiers
* the bit set of modifiers.
* @param onKeyRelease
* the value which represents whether this AWTKeyStroke shall
* represents a key release.
* @return the AWTKeyStroke.
*/
public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers, boolean onKeyRelease) {
return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers, onKeyRelease);
}
/**
* Returns AWTKeyStroke for a specified character and set of modifiers. The
* set of modifiers is given as a bitwise combination of masks taken from
* the following list:
*
*
*
* @param keyChar
* the Character object which represents keyboard character
* value.
* @param modifiers
* the bit set of modifiers.
* @return the AWTKeyStroke object.
* @throws IllegalArgumentException
* if keyChar value is null.
*/
public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers) {
if (keyChar == null) {
// awt.01='{0}' parameter is null
throw new IllegalArgumentException(Messages.getString("awt.01", "keyChar")); //$NON-NLS-1$ //$NON-NLS-2$
}
return getAWTKeyStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED, modifiers, false);
}
/**
* Returns an instance of AWTKeyStroke for a specified key code and set of
* modifiers. The key codes are defined in java.awt.event.KeyEvent class.
* The set of modifiers is given as a bitwise combination of masks taken
* from the following list:
*
*
*
* @param keyCode
* the specified key code of keyboard.
* @param modifiers
* the bit set of modifiers.
* @return the AWTKeyStroke.
*/
public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) {
return getAWTKeyStroke(keyCode, modifiers, false);
}
/**
* Gets the AWTKeyStroke for a key event. This method obtains the key char
* and key code from the specified key event.
*
* @param anEvent
* the key event which identifies the desired AWTKeyStroke.
* @return the AWTKeyStroke for the key event.
*/
public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) {
int id = anEvent.getID();
char undef = KeyEvent.CHAR_UNDEFINED;
char keyChar = (id == KeyEvent.KEY_TYPED ? anEvent.getKeyChar() : undef);
int keyCode = (keyChar == undef ? anEvent.getKeyCode() : KeyEvent.VK_UNDEFINED);
return getAWTKeyStroke(keyChar, keyCode, anEvent.getModifiersEx(),
id == KeyEvent.KEY_RELEASED);
}
/**
* Gets the key event type for the AWTKeyStroke object.
*
* @return the key event type: KeyEvent.KEY_PRESSED, KeyEvent.KEY_TYPED, or
* KeyEvent.KEY_RELEASED.
*/
public final int getKeyEventType() {
if (keyCode == KeyEvent.VK_UNDEFINED) {
return KeyEvent.KEY_TYPED;
}
return (onKeyRelease ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED);
}
/**
* Returns true if the key event is associated with the AWTKeyStroke is
* KEY_RELEASED, false otherwise.
*
* @return true, if if the key event associated with the AWTKeyStroke is
* KEY_RELEASED, false otherwise.
*/
public final boolean isOnKeyRelease() {
return onKeyRelease;
}
/**
* Read resolve.
*
* @return the object.
* @throws ObjectStreamException
* the object stream exception.
*/
protected Object readResolve() throws ObjectStreamException {
return getAWTKeyStroke(this.keyChar, this.keyCode, this.modifiers, this.onKeyRelease);
}
/**
* Register subclass.
*
* @param subclass
* the subclass.
*/
protected static void registerSubclass(Class> subclass) {
// ???AWT
/*
* if (subclass == null) { // awt.01='{0}' parameter is null throw new
* IllegalArgumentException(Messages.getString("awt.01", "subclass"));
* //$NON-NLS-1$ //$NON-NLS-2$ } if (!
* AWTKeyStroke.class.isAssignableFrom(subclass)) { // awt.67=subclass
* is not derived from AWTKeyStroke throw new
* ClassCastException(Messages.getString("awt.67")); //$NON-NLS-1$ } try
* { subConstructor = subclass.getDeclaredConstructor();
* subConstructor.setAccessible(true); } catch (SecurityException e) {
* throw new RuntimeException(e); } catch (NoSuchMethodException e) { //
* awt.68=subclass could not be instantiated throw new
* IllegalArgumentException(Messages.getString("awt.68")); //$NON-NLS-1$
* } cache.clear(); //flush the cache
*/
}
/**
* Parses the modifier.
*
* @param strMod
* the str mod.
* @return the long.
*/
private static long parseModifier(String strMod) {
long modifiers = 0l;
if (strMod.equals("shift")) { //$NON-NLS-1$
modifiers |= InputEvent.SHIFT_DOWN_MASK;
} else if (strMod.equals("control") || strMod.equals("ctrl")) { //$NON-NLS-1$ //$NON-NLS-2$
modifiers |= InputEvent.CTRL_DOWN_MASK;
} else if (strMod.equals("meta")) { //$NON-NLS-1$
modifiers |= InputEvent.META_DOWN_MASK;
} else if (strMod.equals("alt")) { //$NON-NLS-1$
modifiers |= InputEvent.ALT_DOWN_MASK;
} else if (strMod.equals("altGraph")) { //$NON-NLS-1$
modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
} else if (strMod.equals("button1")) { //$NON-NLS-1$
modifiers |= InputEvent.BUTTON1_DOWN_MASK;
} else if (strMod.equals("button2")) { //$NON-NLS-1$
modifiers |= InputEvent.BUTTON2_DOWN_MASK;
} else if (strMod.equals("button3")) { //$NON-NLS-1$
modifiers |= InputEvent.BUTTON3_DOWN_MASK;
}
return modifiers;
}
/**
* Parses the typed id.
*
* @param strTyped
* the str typed.
* @return true, if successful.
*/
private static boolean parseTypedID(String strTyped) {
if (strTyped.equals("typed")) { //$NON-NLS-1$
return true;
}
return false;
}
/**
* Parses the typed key.
*
* @param strChar
* the str char.
* @return the char.
*/
private static char parseTypedKey(String strChar) {
char keyChar = KeyEvent.CHAR_UNDEFINED;
if (strChar.length() != 1) {
// awt.66=Invalid format
throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
}
keyChar = strChar.charAt(0);
return keyChar;
}
/**
* Parses the pressed released id.
*
* @param str
* the str.
* @return the boolean.
*/
private static Boolean parsePressedReleasedID(String str) {
if (str.equals("pressed")) { //$NON-NLS-1$
return Boolean.FALSE;
} else if (str.equals("released")) { //$NON-NLS-1$
return Boolean.TRUE;
}
return null;
}
/**
* Parses the key.
*
* @param strCode
* the str code.
* @return the int.
*/
private static int parseKey(String strCode) {
int keyCode = KeyEvent.VK_UNDEFINED;
keyCode = getKeyCode(strCode);
if (keyCode == KeyEvent.VK_UNDEFINED) {
// awt.66=Invalid format
throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
}
return keyCode;
}
}