blob: 2cf4531f93456726bbfdc479ac8732325653bf8e [file] [log] [blame]
/*
* 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.
*/
package org.apache.pivot.wtk;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.lang.reflect.Field;
import java.util.Locale;
import org.apache.pivot.collections.EnumSet;
import org.apache.pivot.collections.Set;
import org.apache.pivot.util.Utils;
/**
* Class representing the system keyboard.
*/
public final class Keyboard {
/**
* Private constructor for utility class.
*/
private Keyboard() {
}
/**
* Enumeration representing keyboard modifiers.
*/
public enum Modifier {
SHIFT, CTRL, ALT, META;
public int getMask() {
return 1 << ordinal();
}
/**
* The set of all possible keyboard modifiers (for use with {@link #isPressed}
* or {@link #areAnyPressed}).
*/
public static final Set<Modifier> ALL_MODIFIERS =
EnumSet.of(Modifier.SHIFT, Modifier.CTRL, Modifier.ALT, Modifier.META);
}
/**
* Enumeration representing key locations.
*/
public enum KeyLocation {
STANDARD, LEFT, RIGHT, KEYPAD
}
/**
* Represents a keystroke, a combination of a keycode and modifier flags.
*/
public static final class KeyStroke {
private int keyCode = KeyCode.UNDEFINED;
private int keyModifiers = 0x00;
public static final String COMMAND_ABBREVIATION = "CMD";
public KeyStroke(final int keyCode, final int modifiers) {
this.keyCode = keyCode;
this.keyModifiers = modifiers;
}
public int getKeyCode() {
return keyCode;
}
public int getModifiers() {
return keyModifiers;
}
@Override
public boolean equals(final Object object) {
boolean equals = false;
if (object instanceof KeyStroke) {
KeyStroke keyStroke = (KeyStroke) object;
equals = (this.keyCode == keyStroke.keyCode
&& this.keyModifiers == keyStroke.keyModifiers);
}
return equals;
}
@Override
public int hashCode() {
// NOTE Key codes are currently defined as 16-bit values, so
// shifting by 4 bits to append the modifiers should be OK.
// However, if Sun changes the key code values in the future,
// this may no longer be safe.
int hashCode = keyCode << 4 | keyModifiers;
return hashCode;
}
@Override
public String toString() {
int awtModifiers = 0x00;
if (((keyModifiers & Modifier.META.getMask()) > 0)) {
awtModifiers |= InputEvent.META_DOWN_MASK;
}
if (((keyModifiers & Modifier.CTRL.getMask()) > 0)) {
awtModifiers |= InputEvent.CTRL_DOWN_MASK;
}
if (((keyModifiers & Modifier.ALT.getMask()) > 0)) {
awtModifiers |= InputEvent.ALT_DOWN_MASK;
}
if (((keyModifiers & Modifier.SHIFT.getMask()) > 0)) {
awtModifiers |= InputEvent.SHIFT_DOWN_MASK;
}
if (awtModifiers != 0x00) {
return InputEvent.getModifiersExText(awtModifiers)
+ Platform.getKeyStrokeModifierSeparator() + KeyEvent.getKeyText(keyCode);
}
return KeyEvent.getKeyText(keyCode);
}
public static KeyStroke decode(final String value) {
Utils.checkNull(value, "value");
int keyCode = KeyCode.UNDEFINED;
int keyModifiers = 0x00;
String[] keys = value.split("-");
for (int i = 0, n = keys.length; i < n; i++) {
if (i < n - 1) {
// Modifier
String modifierAbbreviation = keys[i].toUpperCase(Locale.ENGLISH);
Modifier modifier;
if (modifierAbbreviation.equals(COMMAND_ABBREVIATION)) {
modifier = Platform.getCommandModifier();
} else {
modifier = Modifier.valueOf(modifierAbbreviation);
}
keyModifiers |= modifier.getMask();
} else {
// Keycode
try {
Field keyCodeField = KeyCode.class.getField(keys[i].toUpperCase(Locale.ENGLISH));
keyCode = ((Integer) keyCodeField.get(null)).intValue();
} catch (Exception exception) {
throw new IllegalArgumentException(exception);
}
}
}
return new KeyStroke(keyCode, keyModifiers);
}
}
/**
* Contains a set of key code constants that are common to all locales.
*/
public static final class KeyCode {
public static final int A = KeyEvent.VK_A;
public static final int B = KeyEvent.VK_B;
public static final int C = KeyEvent.VK_C;
public static final int D = KeyEvent.VK_D;
public static final int E = KeyEvent.VK_E;
public static final int F = KeyEvent.VK_F;
public static final int G = KeyEvent.VK_G;
public static final int H = KeyEvent.VK_H;
public static final int I = KeyEvent.VK_I;
public static final int J = KeyEvent.VK_J;
public static final int K = KeyEvent.VK_K;
public static final int L = KeyEvent.VK_L;
public static final int M = KeyEvent.VK_M;
public static final int N = KeyEvent.VK_N;
public static final int O = KeyEvent.VK_O;
public static final int P = KeyEvent.VK_P;
public static final int Q = KeyEvent.VK_Q;
public static final int R = KeyEvent.VK_R;
public static final int S = KeyEvent.VK_S;
public static final int T = KeyEvent.VK_T;
public static final int U = KeyEvent.VK_U;
public static final int V = KeyEvent.VK_V;
public static final int W = KeyEvent.VK_W;
public static final int X = KeyEvent.VK_X;
public static final int Y = KeyEvent.VK_Y;
public static final int Z = KeyEvent.VK_Z;
public static final int N0 = KeyEvent.VK_0;
public static final int N1 = KeyEvent.VK_1;
public static final int N2 = KeyEvent.VK_2;
public static final int N3 = KeyEvent.VK_3;
public static final int N4 = KeyEvent.VK_4;
public static final int N5 = KeyEvent.VK_5;
public static final int N6 = KeyEvent.VK_6;
public static final int N7 = KeyEvent.VK_7;
public static final int N8 = KeyEvent.VK_8;
public static final int N9 = KeyEvent.VK_9;
public static final int PERIOD = KeyEvent.VK_PERIOD;
public static final int TAB = KeyEvent.VK_TAB;
public static final int SPACE = KeyEvent.VK_SPACE;
public static final int ENTER = KeyEvent.VK_ENTER;
public static final int ESCAPE = KeyEvent.VK_ESCAPE;
public static final int BACKSPACE = KeyEvent.VK_BACK_SPACE;
public static final int DELETE = KeyEvent.VK_DELETE;
public static final int INSERT = KeyEvent.VK_INSERT;
public static final int UP = KeyEvent.VK_UP;
public static final int DOWN = KeyEvent.VK_DOWN;
public static final int LEFT = KeyEvent.VK_LEFT;
public static final int RIGHT = KeyEvent.VK_RIGHT;
public static final int PAGE_UP = KeyEvent.VK_PAGE_UP;
public static final int PAGE_DOWN = KeyEvent.VK_PAGE_DOWN;
public static final int HOME = KeyEvent.VK_HOME;
public static final int END = KeyEvent.VK_END;
public static final int KEYPAD_0 = KeyEvent.VK_NUMPAD0;
public static final int KEYPAD_1 = KeyEvent.VK_NUMPAD1;
public static final int KEYPAD_2 = KeyEvent.VK_NUMPAD2;
public static final int KEYPAD_3 = KeyEvent.VK_NUMPAD3;
public static final int KEYPAD_4 = KeyEvent.VK_NUMPAD4;
public static final int KEYPAD_5 = KeyEvent.VK_NUMPAD5;
public static final int KEYPAD_6 = KeyEvent.VK_NUMPAD6;
public static final int KEYPAD_7 = KeyEvent.VK_NUMPAD7;
public static final int KEYPAD_8 = KeyEvent.VK_NUMPAD8;
public static final int KEYPAD_9 = KeyEvent.VK_NUMPAD9;
public static final int KEYPAD_UP = KeyEvent.VK_KP_UP;
public static final int KEYPAD_DOWN = KeyEvent.VK_KP_DOWN;
public static final int KEYPAD_LEFT = KeyEvent.VK_KP_LEFT;
public static final int KEYPAD_RIGHT = KeyEvent.VK_KP_RIGHT;
public static final int PLUS = KeyEvent.VK_PLUS;
public static final int MINUS = KeyEvent.VK_MINUS;
public static final int EQUALS = KeyEvent.VK_EQUALS;
public static final int ADD = KeyEvent.VK_ADD;
public static final int SUBTRACT = KeyEvent.VK_SUBTRACT;
public static final int MULTIPLY = KeyEvent.VK_MULTIPLY;
public static final int DIVIDE = KeyEvent.VK_DIVIDE;
public static final int SLASH = KeyEvent.VK_SLASH;
public static final int ASTERISK = KeyEvent.VK_ASTERISK;
public static final int F1 = KeyEvent.VK_F1;
public static final int F2 = KeyEvent.VK_F2;
public static final int F3 = KeyEvent.VK_F3;
public static final int F4 = KeyEvent.VK_F4;
public static final int F5 = KeyEvent.VK_F5;
public static final int F6 = KeyEvent.VK_F6;
public static final int F7 = KeyEvent.VK_F7;
public static final int F8 = KeyEvent.VK_F8;
public static final int F9 = KeyEvent.VK_F9;
public static final int F10 = KeyEvent.VK_F10;
public static final int F11 = KeyEvent.VK_F11;
public static final int F12 = KeyEvent.VK_F12;
public static final int UNDEFINED = KeyEvent.VK_UNDEFINED;
}
private static int modifiers = 0;
/**
* @return A bitfield representing the keyboard modifiers that are currently
* pressed.
*/
public static int getModifiers() {
return modifiers;
}
protected static void setModifiers(final int modifiers) {
Keyboard.modifiers = modifiers;
}
/**
* Tests the pressed state of a modifier.
*
* @param modifier The modifier to test.
* @return <tt>true</tt> if the modifier is pressed; <tt>false</tt>,
* otherwise.
*/
public static boolean isPressed(final Modifier modifier) {
return (modifiers & modifier.getMask()) > 0;
}
/**
* Are any of the given set of {@link Modifier}s pressed?
*
* @param modifiers The set of modifiers to test.
* @return <tt>true</tt> if any of them are pressed, <tt>false</tt>
* if none are pressed.
*/
public static boolean areAnyPressed(final Set<Modifier> modifiers) {
boolean result = false;
for (Modifier modifier : modifiers) {
if (isPressed(modifier)) {
result = true;
break;
}
}
return result;
}
/**
* Returns the current drop action.
*
* @return The drop action corresponding to the currently pressed modifier
* keys, or <tt>null</tt> if no modifiers are pressed.
*/
public static DropAction getDropAction() {
// TODO Return an appropriate action for OS:
// Windows: no modifier - move; control - copy; control-shift - link
// Mac OS X: no modifier - move; option - copy; option-command - link
DropAction dropAction = null;
if (isPressed(Modifier.CTRL) && isPressed(Modifier.SHIFT)) {
dropAction = DropAction.LINK;
} else if (isPressed(Modifier.CTRL)) {
dropAction = DropAction.COPY;
} else {
dropAction = DropAction.MOVE;
}
return dropAction;
}
}