From 5ac4638f999db4fea8a9e24171dbceb640a10858 Mon Sep 17 00:00:00 2001
From: Alan Viverette
Date: Tue, 17 May 2011 17:03:25 -0700
Subject: Added support for touch exploration to Latin IME.
Bug: 4379983
Change-Id: I97f22e54827c6229054b514801401ffa5b4ed3b8
---
.../accessibility/KeyCodeDescriptionMapper.java | 226 +++++++++++++++++++++
1 file changed, 226 insertions(+)
create mode 100644 java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
(limited to 'java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java')
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
new file mode 100644
index 000000000..154f4af91
--- /dev/null
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed 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 com.android.inputmethod.accessibility;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.text.TextUtils;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.R;
+
+import java.util.HashMap;
+
+public class KeyCodeDescriptionMapper {
+ private static KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper();
+
+ // Map of key labels to spoken description resource IDs
+ private final HashMap mKeyLabelMap;
+
+ // Map of key codes to spoken description resource IDs
+ private final HashMap mKeyCodeMap;
+
+ // Map of shifted key codes to spoken description resource IDs
+ private final HashMap mShiftedKeyCodeMap;
+
+ // Map of shift-locked key codes to spoken description resource IDs
+ private final HashMap mShiftLockedKeyCodeMap;
+
+ public static void init(Context context, SharedPreferences prefs) {
+ sInstance.initInternal(context, prefs);
+ }
+
+ public static KeyCodeDescriptionMapper getInstance() {
+ return sInstance;
+ }
+
+ private KeyCodeDescriptionMapper() {
+ mKeyLabelMap = new HashMap();
+ mKeyCodeMap = new HashMap();
+ mShiftedKeyCodeMap = new HashMap();
+ mShiftLockedKeyCodeMap = new HashMap();
+ }
+
+ private void initInternal(Context context, SharedPreferences prefs) {
+ // Manual label substitutions for key labels with no string resource
+ mKeyLabelMap.put(":-)", R.string.spoken_description_smiley);
+
+ // Symbols that most TTS engines can't speak
+ mKeyCodeMap.put((int) '.', R.string.spoken_description_period);
+ mKeyCodeMap.put((int) ',', R.string.spoken_description_comma);
+ mKeyCodeMap.put((int) '(', R.string.spoken_description_left_parenthesis);
+ mKeyCodeMap.put((int) ')', R.string.spoken_description_right_parenthesis);
+ mKeyCodeMap.put((int) ':', R.string.spoken_description_colon);
+ mKeyCodeMap.put((int) ';', R.string.spoken_description_semicolon);
+ mKeyCodeMap.put((int) '!', R.string.spoken_description_exclamation_mark);
+ mKeyCodeMap.put((int) '?', R.string.spoken_description_question_mark);
+ mKeyCodeMap.put((int) '\"', R.string.spoken_description_double_quote);
+ mKeyCodeMap.put((int) '\'', R.string.spoken_description_single_quote);
+ mKeyCodeMap.put((int) '*', R.string.spoken_description_star);
+ mKeyCodeMap.put((int) '#', R.string.spoken_description_pound);
+ mKeyCodeMap.put((int) ' ', R.string.spoken_description_space);
+
+ // Non-ASCII symbols (must use escape codes!)
+ mKeyCodeMap.put((int) '\u2022', R.string.spoken_description_dot);
+ mKeyCodeMap.put((int) '\u221A', R.string.spoken_description_square_root);
+ mKeyCodeMap.put((int) '\u03C0', R.string.spoken_description_pi);
+ mKeyCodeMap.put((int) '\u0394', R.string.spoken_description_delta);
+ mKeyCodeMap.put((int) '\u2122', R.string.spoken_description_trademark);
+ mKeyCodeMap.put((int) '\u2105', R.string.spoken_description_care_of);
+ mKeyCodeMap.put((int) '\u2026', R.string.spoken_description_ellipsis);
+ mKeyCodeMap.put((int) '\u201E', R.string.spoken_description_low_double_quote);
+
+ // Special non-character codes defined in Keyboard
+ mKeyCodeMap.put(Keyboard.CODE_DELETE, R.string.spoken_description_delete);
+ mKeyCodeMap.put(Keyboard.CODE_ENTER, R.string.spoken_description_return);
+ mKeyCodeMap.put(Keyboard.CODE_SETTINGS, R.string.spoken_description_settings);
+ mKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_shift);
+ mKeyCodeMap.put(Keyboard.CODE_SHORTCUT, R.string.spoken_description_mic);
+ mKeyCodeMap.put(Keyboard.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol);
+ mKeyCodeMap.put(Keyboard.CODE_TAB, R.string.spoken_description_tab);
+
+ // Shifted versions of non-character codes defined in Keyboard
+ mShiftedKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_shift_shifted);
+
+ // Shift-locked versions of non-character codes defined in Keyboard
+ mShiftLockedKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_caps_lock);
+ }
+
+ /**
+ * Returns the localized description of the action performed by a specified
+ * key based on the current keyboard state.
+ *
+ * The order of precedence for key descriptions is:
+ *
+ * - Manually-defined based on the key label
+ * - Automatic or manually-defined based on the key code
+ * - Automatically based on the key label
+ * - {code null} for keys with no label or key code defined
+ *
+ *
+ * @param context The package's context.
+ * @param keyboard The keyboard on which the key resides.
+ * @param key The key from which to obtain a description.
+ * @return a character sequence describing the action performed by pressing
+ * the key
+ */
+ public CharSequence getDescriptionForKey(Context context, Keyboard keyboard, Key key) {
+ if (key.mCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
+ final CharSequence description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
+ if (description != null)
+ return description;
+ }
+
+ if (!TextUtils.isEmpty(key.mLabel)) {
+ final String label = key.mLabel.toString().trim();
+
+ if (mKeyLabelMap.containsKey(label)) {
+ return context.getString(mKeyLabelMap.get(label));
+ } else if (label.length() == 1
+ || (keyboard.isManualTemporaryUpperCase() && !TextUtils
+ .isEmpty(key.mHintLetter))) {
+ return getDescriptionForKeyCode(context, keyboard, key);
+ } else {
+ return label;
+ }
+ } else if (key.mCode != Keyboard.CODE_DUMMY) {
+ return getDescriptionForKeyCode(context, keyboard, key);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a context-specific description for the CODE_SWITCH_ALPHA_SYMBOL
+ * key or {@code null} if there is not a description provided for the
+ * current keyboard context.
+ *
+ * @param context The package's context.
+ * @param keyboard The keyboard on which the key resides.
+ * @return a character sequence describing the action performed by pressing
+ * the key
+ */
+ private CharSequence getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) {
+ final KeyboardId id = keyboard.mId;
+
+ if (id.isAlphabetKeyboard()) {
+ return context.getString(R.string.spoken_description_to_symbol);
+ } else if (id.isSymbolsKeyboard()) {
+ return context.getString(R.string.spoken_description_to_alpha);
+ } else if (id.isPhoneSymbolsKeyboard()) {
+ return context.getString(R.string.spoken_description_to_numeric);
+ } else if (id.isPhoneKeyboard()) {
+ return context.getString(R.string.spoken_description_to_symbol);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the keycode for the specified key given the current keyboard
+ * state.
+ *
+ * @param keyboard The keyboard on which the key resides.
+ * @param key The key from which to obtain a key code.
+ * @return the key code for the specified key
+ */
+ private int getCorrectKeyCode(Keyboard keyboard, Key key) {
+ if (keyboard.isManualTemporaryUpperCase() && !TextUtils.isEmpty(key.mHintLetter)) {
+ return key.mHintLetter.charAt(0);
+ } else {
+ return key.mCode;
+ }
+ }
+
+ /**
+ * Returns a localized character sequence describing what will happen when
+ * the specified key is pressed based on its key code.
+ *
+ * The order of precedence for key code descriptions is:
+ *
+ * - Manually-defined shift-locked description
+ * - Manually-defined shifted description
+ * - Manually-defined normal description
+ * - Automatic based on the character represented by the key code
+ * - Fall-back for undefined or control characters
+ *
+ *
+ *
+ * @param context The package's context.
+ * @param keyboard The keyboard on which the key resides.
+ * @param key The key from which to obtain a description.
+ * @return a character sequence describing the action performed by pressing
+ * the key
+ */
+ private CharSequence getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key) {
+ final int code = getCorrectKeyCode(keyboard, key);
+
+ if (keyboard.isShiftLocked() && mShiftLockedKeyCodeMap.containsKey(code)) {
+ return context.getString(mShiftLockedKeyCodeMap.get(code));
+ } else if (keyboard.isShiftedOrShiftLocked() && mShiftedKeyCodeMap.containsKey(code)) {
+ return context.getString(mShiftedKeyCodeMap.get(code));
+ } else if (mKeyCodeMap.containsKey(code)) {
+ return context.getString(mKeyCodeMap.get(code));
+ } else if (Character.isDefined(code) && !Character.isISOControl(code)) {
+ return Character.toString((char) code);
+ } else {
+ return context.getString(R.string.spoken_description_unknown, code);
+ }
+ }
+}
--
cgit v1.2.3-83-g751a
From 44f8dc3132ebfd5886749a888b6388963293d298 Mon Sep 17 00:00:00 2001
From: Alan Viverette
Date: Wed, 22 Jun 2011 12:08:10 -0700
Subject: Fixing build error due to refactored import.
Change-Id: I7ed51fa4373fd5d1ebc6ebe52c6e93b27b43cff5
---
.../android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java | 2 +-
.../com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
(limited to 'java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java')
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index 96f7fc9f2..1adef9057 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -27,10 +27,10 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
import com.android.inputmethod.compat.MotionEventCompatUtils;
-import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.PointerTracker;
+import com.android.inputmethod.keyboard.internal.Key;
public class AccessibleKeyboardViewProxy {
private static final String TAG = AccessibleKeyboardViewProxy.class.getSimpleName();
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 154f4af91..5e6f10b04 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -20,9 +20,9 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
-import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.latin.R;
import java.util.HashMap;
--
cgit v1.2.3-83-g751a
From e7759091ddb5ec18268945d70d9212195bf6497b Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka"
Date: Thu, 23 Jun 2011 21:23:44 +0900
Subject: Move Key class out of internal package
Bug: 4903326
Change-Id: I2493d6dae613d2e37dfa8ce96b4cddc9a038160c
---
.../accessibility/AccessibleKeyboardViewProxy.java | 2 +-
.../accessibility/KeyCodeDescriptionMapper.java | 2 +-
java/src/com/android/inputmethod/keyboard/Key.java | 474 +++++++++++++++++++++
.../android/inputmethod/keyboard/KeyDetector.java | 2 -
.../com/android/inputmethod/keyboard/Keyboard.java | 3 +-
.../inputmethod/keyboard/KeyboardSwitcher.java | 1 -
.../android/inputmethod/keyboard/KeyboardView.java | 3 +-
.../inputmethod/keyboard/LatinKeyboard.java | 3 +-
.../inputmethod/keyboard/LatinKeyboardView.java | 1 -
.../android/inputmethod/keyboard/MiniKeyboard.java | 2 -
.../keyboard/MiniKeyboardKeyDetector.java | 2 -
.../inputmethod/keyboard/PointerTracker.java | 13 +-
.../keyboard/PopupMiniKeyboardView.java | 1 -
.../android/inputmethod/keyboard/PopupPanel.java | 2 -
.../inputmethod/keyboard/ProximityInfo.java | 1 -
.../android/inputmethod/keyboard/internal/Key.java | 458 --------------------
.../keyboard/internal/KeyboardParser.java | 3 +-
.../keyboard/internal/MiniKeyboardBuilder.java | 1 +
.../android/inputmethod/latin/SuggestHelper.java | 2 +-
19 files changed, 489 insertions(+), 487 deletions(-)
create mode 100644 java/src/com/android/inputmethod/keyboard/Key.java
delete mode 100644 java/src/com/android/inputmethod/keyboard/internal/Key.java
(limited to 'java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java')
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index 1adef9057..96f7fc9f2 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -27,10 +27,10 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
import com.android.inputmethod.compat.MotionEventCompatUtils;
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.PointerTracker;
-import com.android.inputmethod.keyboard.internal.Key;
public class AccessibleKeyboardViewProxy {
private static final String TAG = AccessibleKeyboardViewProxy.class.getSimpleName();
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 5e6f10b04..154f4af91 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -20,9 +20,9 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.latin.R;
import java.util.HashMap;
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
new file mode 100644
index 000000000..2850c95df
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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 com.android.inputmethod.keyboard;
+
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.Xml;
+
+import com.android.inputmethod.keyboard.internal.KeyStyles;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.keyboard.internal.KeyboardParser;
+import com.android.inputmethod.keyboard.internal.PopupCharactersParser;
+import com.android.inputmethod.keyboard.internal.Row;
+import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
+import com.android.inputmethod.keyboard.internal.KeyboardParser.ParseException;
+import com.android.inputmethod.latin.R;
+
+import java.util.ArrayList;
+
+/**
+ * Class for describing the position and characteristics of a single key in the keyboard.
+ */
+public class Key {
+ /**
+ * The key code (unicode or custom code) that this key generates.
+ */
+ public final int mCode;
+
+ /** Label to display */
+ public final CharSequence mLabel;
+ /** Hint letter to display on the key in conjunction with the label */
+ public final CharSequence mHintLetter;
+ /** Option of the label */
+ public final int mLabelOption;
+ public static final int LABEL_OPTION_ALIGN_LEFT = 0x01;
+ public static final int LABEL_OPTION_ALIGN_RIGHT = 0x02;
+ public static final int LABEL_OPTION_ALIGN_BOTTOM = 0x08;
+ public static final int LABEL_OPTION_FONT_NORMAL = 0x10;
+ public static final int LABEL_OPTION_FONT_FIXED_WIDTH = 0x20;
+ public static final int LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO = 0x40;
+ private static final int LABEL_OPTION_POPUP_HINT = 0x80;
+ private static final int LABEL_OPTION_HAS_UPPERCASE_LETTER = 0x100;
+
+ /** Icon to display instead of a label. Icon takes precedence over a label */
+ private Drawable mIcon;
+ /** Preview version of the icon, for the preview popup */
+ private Drawable mPreviewIcon;
+
+ /** Width of the key, not including the gap */
+ public final int mWidth;
+ /** Height of the key, not including the gap */
+ public final int mHeight;
+ /** The horizontal gap around this key */
+ public final int mGap;
+ /** The visual insets */
+ public final int mVisualInsetsLeft;
+ public final int mVisualInsetsRight;
+ /** Whether this key is sticky, i.e., a toggle key */
+ public final boolean mSticky;
+ /** X coordinate of the key in the keyboard layout */
+ public final int mX;
+ /** Y coordinate of the key in the keyboard layout */
+ public final int mY;
+ /** Text to output when pressed. This can be multiple characters, like ".com" */
+ public final CharSequence mOutputText;
+ /** Popup characters */
+ public final CharSequence[] mPopupCharacters;
+ /** Popup keyboard maximum column number */
+ public final int mMaxPopupColumn;
+
+ /**
+ * Flags that specify the anchoring to edges of the keyboard for detecting touch events
+ * that are just out of the boundary of the key. This is a bit mask of
+ * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT},
+ * {@link Keyboard#EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM}.
+ */
+ public final int mEdgeFlags;
+ /** Whether this is a functional key which has different key top than normal key */
+ public final boolean mFunctional;
+ /** Whether this key repeats itself when held down */
+ public final boolean mRepeatable;
+
+ /** The Keyboard that this key belongs to */
+ private final Keyboard mKeyboard;
+
+ /** The current pressed state of this key */
+ private boolean mPressed;
+ /** If this is a sticky key, is its highlight on? */
+ private boolean mHighlightOn;
+ /** Key is enabled and responds on press */
+ private boolean mEnabled = true;
+
+ // keyWidth constants
+ private static final int KEYWIDTH_FILL_RIGHT = 0;
+ private static final int KEYWIDTH_FILL_BOTH = -1;
+
+ private final static int[] KEY_STATE_NORMAL_ON = {
+ android.R.attr.state_checkable,
+ android.R.attr.state_checked
+ };
+
+ private final static int[] KEY_STATE_PRESSED_ON = {
+ android.R.attr.state_pressed,
+ android.R.attr.state_checkable,
+ android.R.attr.state_checked
+ };
+
+ private final static int[] KEY_STATE_NORMAL_OFF = {
+ android.R.attr.state_checkable
+ };
+
+ private final static int[] KEY_STATE_PRESSED_OFF = {
+ android.R.attr.state_pressed,
+ android.R.attr.state_checkable
+ };
+
+ private final static int[] KEY_STATE_NORMAL = {
+ };
+
+ private final static int[] KEY_STATE_PRESSED = {
+ android.R.attr.state_pressed
+ };
+
+ // functional normal state (with properties)
+ private static final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
+ android.R.attr.state_single
+ };
+
+ // functional pressed state (with properties)
+ private static final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
+ android.R.attr.state_single,
+ android.R.attr.state_pressed
+ };
+
+ /**
+ * This constructor is being used only for key in popup mini keyboard.
+ */
+ public Key(Resources res, Keyboard keyboard, CharSequence popupCharacter, int x, int y,
+ int width, int height, int edgeFlags) {
+ mKeyboard = keyboard;
+ mHeight = height - keyboard.getVerticalGap();
+ mGap = keyboard.getHorizontalGap();
+ mVisualInsetsLeft = mVisualInsetsRight = 0;
+ mWidth = width - mGap;
+ mEdgeFlags = edgeFlags;
+ mHintLetter = null;
+ mLabelOption = 0;
+ mFunctional = false;
+ mSticky = false;
+ mRepeatable = false;
+ mPopupCharacters = null;
+ mMaxPopupColumn = 0;
+ final String popupSpecification = popupCharacter.toString();
+ mLabel = PopupCharactersParser.getLabel(popupSpecification);
+ mOutputText = PopupCharactersParser.getOutputText(popupSpecification);
+ mCode = PopupCharactersParser.getCode(res, popupSpecification);
+ mIcon = keyboard.mIconsSet.getIcon(PopupCharactersParser.getIconId(popupSpecification));
+ // Horizontal gap is divided equally to both sides of the key.
+ mX = x + mGap / 2;
+ mY = y;
+ }
+
+ /**
+ * Create a key with the given top-left coordinate and extract its attributes from the XML
+ * parser.
+ * @param res resources associated with the caller's context
+ * @param row the row that this key belongs to. The row must already be attached to
+ * a {@link Keyboard}.
+ * @param x the x coordinate of the top-left
+ * @param y the y coordinate of the top-left
+ * @param parser the XML parser containing the attributes for this key
+ * @param keyStyles active key styles set
+ */
+ public Key(Resources res, Row row, int x, int y, XmlResourceParser parser,
+ KeyStyles keyStyles) {
+ mKeyboard = row.getKeyboard();
+
+ final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard);
+ int keyWidth;
+ try {
+ mHeight = KeyboardParser.getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_rowHeight,
+ mKeyboard.getKeyboardHeight(), row.mDefaultHeight) - row.mVerticalGap;
+ mGap = KeyboardParser.getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_horizontalGap,
+ mKeyboard.getDisplayWidth(), row.mDefaultHorizontalGap);
+ keyWidth = KeyboardParser.getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyWidth,
+ mKeyboard.getDisplayWidth(), row.mDefaultWidth);
+ } finally {
+ keyboardAttr.recycle();
+ }
+
+ final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ try {
+ final KeyStyle style;
+ if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) {
+ String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
+ style = keyStyles.getKeyStyle(styleName);
+ if (style == null)
+ throw new ParseException("Unknown key style: " + styleName, parser);
+ } else {
+ style = keyStyles.getEmptyKeyStyle();
+ }
+
+ final int keyboardWidth = mKeyboard.getDisplayWidth();
+ int keyXPos = KeyboardParser.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyXPos, keyboardWidth, x);
+ if (keyXPos < 0) {
+ // If keyXPos is negative, the actual x-coordinate will be k + keyXPos.
+ keyXPos += keyboardWidth;
+ if (keyXPos < x) {
+ // keyXPos shouldn't be less than x because drawable area for this key starts
+ // at x. Or, this key will overlaps the adjacent key on its left hand side.
+ keyXPos = x;
+ }
+ }
+ if (keyWidth == KEYWIDTH_FILL_RIGHT) {
+ // If keyWidth is zero, the actual key width will be determined to fill out the
+ // area up to the right edge of the keyboard.
+ keyWidth = keyboardWidth - keyXPos;
+ } else if (keyWidth <= KEYWIDTH_FILL_BOTH) {
+ // If keyWidth is negative, the actual key width will be determined to fill out the
+ // area between the nearest key on the left hand side and the right edge of the
+ // keyboard.
+ keyXPos = x;
+ keyWidth = keyboardWidth - keyXPos;
+ }
+
+ // Horizontal gap is divided equally to both sides of the key.
+ mX = keyXPos + mGap / 2;
+ mY = y;
+ mWidth = keyWidth - mGap;
+
+ final CharSequence[] popupCharacters = style.getTextArray(keyAttr,
+ R.styleable.Keyboard_Key_popupCharacters);
+ if (res.getBoolean(R.bool.config_digit_popup_characters_enabled)) {
+ mPopupCharacters = popupCharacters;
+ } else {
+ mPopupCharacters = filterOutDigitPopupCharacters(popupCharacters);
+ }
+ mMaxPopupColumn = style.getInt(keyboardAttr,
+ R.styleable.Keyboard_Key_maxPopupKeyboardColumn,
+ mKeyboard.getMaxPopupKeyboardColumn());
+
+ mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
+ mFunctional = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isFunctional, false);
+ mSticky = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isSticky, false);
+ mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
+ mEdgeFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyEdgeFlags, 0)
+ | row.mRowEdgeFlags;
+
+ final KeyboardIconsSet iconsSet = mKeyboard.mIconsSet;
+ mVisualInsetsLeft = KeyboardParser.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_visualInsetsLeft, mKeyboard.getDisplayHeight(), 0);
+ mVisualInsetsRight = KeyboardParser.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_visualInsetsRight, mKeyboard.getDisplayHeight(), 0);
+ mPreviewIcon = iconsSet.getIcon(style.getInt(
+ keyAttr, R.styleable.Keyboard_Key_keyIconPreview,
+ KeyboardIconsSet.ICON_UNDEFINED));
+ Keyboard.setDefaultBounds(mPreviewIcon);
+ mIcon = iconsSet.getIcon(style.getInt(
+ keyAttr, R.styleable.Keyboard_Key_keyIcon,
+ KeyboardIconsSet.ICON_UNDEFINED));
+ Keyboard.setDefaultBounds(mIcon);
+ mHintLetter = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLetter);
+
+ mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
+ mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0);
+ mOutputText = style.getText(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
+ // Choose the first letter of the label as primary code if not
+ // specified.
+ final int code = style.getInt(keyAttr, R.styleable.Keyboard_Key_code,
+ Keyboard.CODE_UNSPECIFIED);
+ if (code == Keyboard.CODE_UNSPECIFIED && !TextUtils.isEmpty(mLabel)) {
+ mCode = mLabel.charAt(0);
+ } else if (code != Keyboard.CODE_UNSPECIFIED) {
+ mCode = code;
+ } else {
+ mCode = Keyboard.CODE_DUMMY;
+ }
+
+ final Drawable shiftedIcon = iconsSet.getIcon(style.getInt(
+ keyAttr, R.styleable.Keyboard_Key_keyIconShifted,
+ KeyboardIconsSet.ICON_UNDEFINED));
+ if (shiftedIcon != null)
+ mKeyboard.getShiftedIcons().put(this, shiftedIcon);
+ } finally {
+ keyAttr.recycle();
+ }
+ }
+
+ public boolean hasPopupHint() {
+ return (mLabelOption & LABEL_OPTION_POPUP_HINT) != 0;
+ }
+
+ public boolean hasUppercaseLetter() {
+ return (mLabelOption & LABEL_OPTION_HAS_UPPERCASE_LETTER) != 0;
+ }
+
+ private static boolean isDigitPopupCharacter(CharSequence label) {
+ return label != null && label.length() == 1 && Character.isDigit(label.charAt(0));
+ }
+
+ private static CharSequence[] filterOutDigitPopupCharacters(CharSequence[] popupCharacters) {
+ if (popupCharacters == null || popupCharacters.length < 1)
+ return null;
+ if (popupCharacters.length == 1 && isDigitPopupCharacter(
+ PopupCharactersParser.getLabel(popupCharacters[0].toString())))
+ return null;
+ ArrayList filtered = null;
+ for (int i = 0; i < popupCharacters.length; i++) {
+ final CharSequence popupSpec = popupCharacters[i];
+ if (isDigitPopupCharacter(PopupCharactersParser.getLabel(popupSpec.toString()))) {
+ if (filtered == null) {
+ filtered = new ArrayList();
+ for (int j = 0; j < i; j++)
+ filtered.add(popupCharacters[j]);
+ }
+ } else if (filtered != null) {
+ filtered.add(popupSpec);
+ }
+ }
+ if (filtered == null)
+ return popupCharacters;
+ if (filtered.size() == 0)
+ return null;
+ return filtered.toArray(new CharSequence[filtered.size()]);
+ }
+
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ public Drawable getPreviewIcon() {
+ return mPreviewIcon;
+ }
+
+ public void setIcon(Drawable icon) {
+ mIcon = icon;
+ }
+
+ public void setPreviewIcon(Drawable icon) {
+ mPreviewIcon = icon;
+ }
+
+ /**
+ * Informs the key that it has been pressed, in case it needs to change its appearance or
+ * state.
+ * @see #onReleased()
+ */
+ public void onPressed() {
+ mPressed = true;
+ }
+
+ /**
+ * Informs the key that it has been released, in case it needs to change its appearance or
+ * state.
+ * @see #onPressed()
+ */
+ public void onReleased() {
+ mPressed = false;
+ }
+
+ public void setHighlightOn(boolean highlightOn) {
+ mHighlightOn = highlightOn;
+ }
+
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ /**
+ * Detects if a point falls on this key.
+ * @param x the x-coordinate of the point
+ * @param y the y-coordinate of the point
+ * @return whether or not the point falls on the key. If the key is attached to an edge, it will
+ * assume that all points between the key and the edge are considered to be on the key.
+ */
+ public boolean isOnKey(int x, int y) {
+ final int flags = mEdgeFlags;
+ final boolean leftEdge = (flags & Keyboard.EDGE_LEFT) != 0;
+ final boolean rightEdge = (flags & Keyboard.EDGE_RIGHT) != 0;
+ final boolean topEdge = (flags & Keyboard.EDGE_TOP) != 0;
+ final boolean bottomEdge = (flags & Keyboard.EDGE_BOTTOM) != 0;
+ final int left = mX - mGap / 2;
+ final int right = left + mWidth + mGap;
+ final int top = mY;
+ final int bottom = top + mHeight + mKeyboard.getVerticalGap();
+ // In order to mitigate rounding errors, we use (left <= x <= right) here.
+ return (x >= left || leftEdge) && (x <= right || rightEdge)
+ && (y >= top || topEdge) && (y <= bottom || bottomEdge);
+ }
+
+ /**
+ * Returns the square of the distance to the nearest edge of the key and the given point.
+ * @param x the x-coordinate of the point
+ * @param y the y-coordinate of the point
+ * @return the square of the distance of the point from the nearest edge of the key
+ */
+ public int squaredDistanceToEdge(int x, int y) {
+ final int left = mX;
+ final int right = left + mWidth;
+ final int top = mY;
+ final int bottom = top + mHeight;
+ final int edgeX = x < left ? left : (x > right ? right : x);
+ final int edgeY = y < top ? top : (y > bottom ? bottom : y);
+ final int dx = x - edgeX;
+ final int dy = y - edgeY;
+ return dx * dx + dy * dy;
+ }
+
+ /**
+ * Returns the drawable state for the key, based on the current state and type of the key.
+ * @return the drawable state of the key.
+ * @see android.graphics.drawable.StateListDrawable#setState(int[])
+ */
+ public int[] getCurrentDrawableState() {
+ final boolean pressed = mPressed;
+ if (!mSticky && mFunctional) {
+ if (pressed) {
+ return KEY_STATE_FUNCTIONAL_PRESSED;
+ } else {
+ return KEY_STATE_FUNCTIONAL_NORMAL;
+ }
+ }
+
+ int[] states = KEY_STATE_NORMAL;
+
+ if (mHighlightOn) {
+ if (pressed) {
+ states = KEY_STATE_PRESSED_ON;
+ } else {
+ states = KEY_STATE_NORMAL_ON;
+ }
+ } else {
+ if (mSticky) {
+ if (pressed) {
+ states = KEY_STATE_PRESSED_OFF;
+ } else {
+ states = KEY_STATE_NORMAL_OFF;
+ }
+ } else {
+ if (pressed) {
+ states = KEY_STATE_PRESSED;
+ }
+ }
+ }
+ return states;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index 818f3f925..7add43a6d 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -18,8 +18,6 @@ package com.android.inputmethod.keyboard;
import android.util.Log;
-import com.android.inputmethod.keyboard.internal.Key;
-
import java.util.Arrays;
import java.util.List;
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 889d54bf3..20327c5b2 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -21,7 +21,6 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.util.Log;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.keyboard.internal.KeyboardParser;
import com.android.inputmethod.keyboard.internal.KeyboardShiftState;
@@ -297,7 +296,7 @@ public class Keyboard {
public boolean setShiftLocked(boolean newShiftLockState) {
final Map shiftedIcons = getShiftedIcons();
for (final Key key : getShiftKeys()) {
- key.mHighlightOn = newShiftLockState;
+ key.setHighlightOn(newShiftLockState);
key.setIcon(newShiftLockState ? shiftedIcons.get(key) : mNormalShiftIcons.get(key));
}
mShiftState.setShiftLocked(newShiftLockState);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 1ad5b08eb..eef01a67c 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -28,7 +28,6 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.keyboard.internal.ModifierKeyState;
import com.android.inputmethod.keyboard.internal.ShiftKeyState;
import com.android.inputmethod.latin.LatinIME;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index a6aef27e0..6c6d2df19 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -49,7 +49,6 @@ import android.widget.TextView;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.compat.FrameLayoutCompatUtils;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.keyboard.internal.SwipeTracker;
@@ -745,7 +744,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
} else {
paint.setColor(mKeyTextColor);
}
- if (key.mEnabled) {
+ if (key.isEnabled()) {
// Set a drop shadow for the text
paint.setShadowLayer(mShadowRadius, 0, 0, mShadowColor);
} else {
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
index 0329ee2b3..76eac1ac8 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
@@ -33,7 +33,6 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.keyboard.internal.SlidingLocaleDrawable;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
@@ -175,7 +174,7 @@ public class LatinKeyboard extends Keyboard {
public void updateShortcutKey(boolean available, LatinKeyboardView view) {
if (mShortcutKey == null)
return;
- mShortcutKey.mEnabled = available;
+ mShortcutKey.setEnabled(available);
mShortcutKey.setIcon(available ? mEnabledShortcutIcon : mDisabledShortcutIcon);
if (view != null)
view.invalidateKey(mShortcutKey);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index d25d1f098..901df6ab7 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -24,7 +24,6 @@ import android.util.Log;
import android.view.MotionEvent;
import com.android.inputmethod.deprecated.VoiceProxy;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.Utils;
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index d3d3fa59f..2d6766f2d 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -18,8 +18,6 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
-import com.android.inputmethod.keyboard.internal.Key;
-
import java.util.List;
public class MiniKeyboard extends Keyboard {
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
index 9170c3bd1..cc5c3bbfe 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
@@ -16,8 +16,6 @@
package com.android.inputmethod.keyboard;
-import com.android.inputmethod.keyboard.internal.Key;
-
import java.util.List;
public class MiniKeyboardKeyDetector extends KeyDetector {
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 1d70481f4..c7620f946 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -22,7 +22,6 @@ import android.util.Log;
import android.view.MotionEvent;
import com.android.inputmethod.keyboard.KeyboardView.UIHandler;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.keyboard.internal.PointerTrackerKeyState;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.LatinImeLogger;
@@ -150,7 +149,7 @@ public class PointerTracker {
+ " ignoreModifier=" + ignoreModifierKey);
if (ignoreModifierKey)
return false;
- if (key.mEnabled) {
+ if (key.isEnabled()) {
mListener.onPress(key.mCode, withSliding);
final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged;
mKeyboardLayoutHasBeenChanged = false;
@@ -169,14 +168,14 @@ public class PointerTracker {
+ " ignoreModifier=" + ignoreModifierKey);
if (ignoreModifierKey)
return;
- if (key.mEnabled)
+ if (key.isEnabled())
mListener.onCodeInput(primaryCode, keyCodes, x, y);
}
private void callListenerOnTextInput(Key key) {
if (DEBUG_LISTENER)
Log.d(TAG, "onTextInput: text=" + key.mOutputText);
- if (key.mEnabled)
+ if (key.isEnabled())
mListener.onTextInput(key.mOutputText);
}
@@ -189,7 +188,7 @@ public class PointerTracker {
+ withSliding + " ignoreModifier=" + ignoreModifierKey);
if (ignoreModifierKey)
return;
- if (key.mEnabled)
+ if (key.isEnabled())
mListener.onRelease(primaryCode, withSliding);
}
@@ -269,7 +268,7 @@ public class PointerTracker {
private void setPressedKeyGraphics(int keyIndex) {
final Key key = getKey(keyIndex);
- if (key != null && key.mEnabled) {
+ if (key != null && key.isEnabled()) {
key.onPressed();
mProxy.invalidateKey(key);
}
@@ -618,7 +617,7 @@ public class PointerTracker {
// The modifier key, such as shift key, should not show its key preview.
private boolean isKeyPreviewNotRequired(int keyIndex) {
final Key key = getKey(keyIndex);
- if (key == null || !key.mEnabled)
+ if (key == null || !key.isEnabled())
return true;
// Such as spacebar sliding language switch.
if (mKeyboard.needSpacebarPreview(keyIndex))
diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
index 6180f09c1..3642df0ec 100644
--- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
@@ -25,7 +25,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.PopupWindow;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.latin.R;
/**
diff --git a/java/src/com/android/inputmethod/keyboard/PopupPanel.java b/java/src/com/android/inputmethod/keyboard/PopupPanel.java
index 48454679e..6ecb1c93f 100644
--- a/java/src/com/android/inputmethod/keyboard/PopupPanel.java
+++ b/java/src/com/android/inputmethod/keyboard/PopupPanel.java
@@ -19,8 +19,6 @@ package com.android.inputmethod.keyboard;
import android.view.MotionEvent;
import android.widget.PopupWindow;
-import com.android.inputmethod.keyboard.internal.Key;
-
public interface PopupPanel {
/**
* Show popup panel.
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index a6a07e518..33acc6907 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -16,7 +16,6 @@
package com.android.inputmethod.keyboard;
-import com.android.inputmethod.keyboard.internal.Key;
import com.android.inputmethod.latin.Utils;
import java.util.Arrays;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/Key.java b/java/src/com/android/inputmethod/keyboard/internal/Key.java
deleted file mode 100644
index ebd80be5e..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/Key.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed 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 com.android.inputmethod.keyboard.internal;
-
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.Xml;
-
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
-import com.android.inputmethod.keyboard.internal.KeyboardParser.ParseException;
-import com.android.inputmethod.latin.R;
-
-import java.util.ArrayList;
-
-/**
- * Class for describing the position and characteristics of a single key in the keyboard.
- */
-public class Key {
- /**
- * The key code (unicode or custom code) that this key generates.
- */
- public final int mCode;
-
- /** Label to display */
- public final CharSequence mLabel;
- /** Hint letter to display on the key in conjunction with the label */
- public final CharSequence mHintLetter;
- /** Option of the label */
- public final int mLabelOption;
- public static final int LABEL_OPTION_ALIGN_LEFT = 0x01;
- public static final int LABEL_OPTION_ALIGN_RIGHT = 0x02;
- public static final int LABEL_OPTION_ALIGN_BOTTOM = 0x08;
- public static final int LABEL_OPTION_FONT_NORMAL = 0x10;
- public static final int LABEL_OPTION_FONT_FIXED_WIDTH = 0x20;
- public static final int LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO = 0x40;
- private static final int LABEL_OPTION_POPUP_HINT = 0x80;
- private static final int LABEL_OPTION_HAS_UPPERCASE_LETTER = 0x100;
-
- /** Icon to display instead of a label. Icon takes precedence over a label */
- private Drawable mIcon;
- /** Preview version of the icon, for the preview popup */
- private Drawable mPreviewIcon;
-
- /** Width of the key, not including the gap */
- public final int mWidth;
- /** Height of the key, not including the gap */
- public final int mHeight;
- /** The horizontal gap around this key */
- public final int mGap;
- /** The visual insets */
- public final int mVisualInsetsLeft;
- public final int mVisualInsetsRight;
- /** Whether this key is sticky, i.e., a toggle key */
- public final boolean mSticky;
- /** X coordinate of the key in the keyboard layout */
- public final int mX;
- /** Y coordinate of the key in the keyboard layout */
- public final int mY;
- /** Text to output when pressed. This can be multiple characters, like ".com" */
- public final CharSequence mOutputText;
- /** Popup characters */
- public final CharSequence[] mPopupCharacters;
- /** Popup keyboard maximum column number */
- public final int mMaxPopupColumn;
-
- /**
- * Flags that specify the anchoring to edges of the keyboard for detecting touch events
- * that are just out of the boundary of the key. This is a bit mask of
- * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT},
- * {@link Keyboard#EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM}.
- */
- public final int mEdgeFlags;
- /** Whether this is a functional key which has different key top than normal key */
- public final boolean mFunctional;
- /** Whether this key repeats itself when held down */
- public final boolean mRepeatable;
-
- /** The Keyboard that this key belongs to */
- private final Keyboard mKeyboard;
-
- /** The current pressed state of this key */
- public boolean mPressed;
- /** If this is a sticky key, is its highlight on? */
- public boolean mHighlightOn;
- /** Key is enabled and responds on press */
- public boolean mEnabled = true;
-
- // keyWidth constants
- private static final int KEYWIDTH_FILL_RIGHT = 0;
- private static final int KEYWIDTH_FILL_BOTH = -1;
-
- private final static int[] KEY_STATE_NORMAL_ON = {
- android.R.attr.state_checkable,
- android.R.attr.state_checked
- };
-
- private final static int[] KEY_STATE_PRESSED_ON = {
- android.R.attr.state_pressed,
- android.R.attr.state_checkable,
- android.R.attr.state_checked
- };
-
- private final static int[] KEY_STATE_NORMAL_OFF = {
- android.R.attr.state_checkable
- };
-
- private final static int[] KEY_STATE_PRESSED_OFF = {
- android.R.attr.state_pressed,
- android.R.attr.state_checkable
- };
-
- private final static int[] KEY_STATE_NORMAL = {
- };
-
- private final static int[] KEY_STATE_PRESSED = {
- android.R.attr.state_pressed
- };
-
- // functional normal state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
- android.R.attr.state_single
- };
-
- // functional pressed state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
- android.R.attr.state_single,
- android.R.attr.state_pressed
- };
-
- /**
- * This constructor is being used only for key in popup mini keyboard.
- */
- public Key(Resources res, Keyboard keyboard, CharSequence popupCharacter, int x, int y,
- int width, int height, int edgeFlags) {
- mKeyboard = keyboard;
- mHeight = height - keyboard.getVerticalGap();
- mGap = keyboard.getHorizontalGap();
- mVisualInsetsLeft = mVisualInsetsRight = 0;
- mWidth = width - mGap;
- mEdgeFlags = edgeFlags;
- mHintLetter = null;
- mLabelOption = 0;
- mFunctional = false;
- mSticky = false;
- mRepeatable = false;
- mPopupCharacters = null;
- mMaxPopupColumn = 0;
- final String popupSpecification = popupCharacter.toString();
- mLabel = PopupCharactersParser.getLabel(popupSpecification);
- mOutputText = PopupCharactersParser.getOutputText(popupSpecification);
- mCode = PopupCharactersParser.getCode(res, popupSpecification);
- mIcon = keyboard.mIconsSet.getIcon(PopupCharactersParser.getIconId(popupSpecification));
- // Horizontal gap is divided equally to both sides of the key.
- mX = x + mGap / 2;
- mY = y;
- }
-
- /**
- * Create a key with the given top-left coordinate and extract its attributes from the XML
- * parser.
- * @param res resources associated with the caller's context
- * @param row the row that this key belongs to. The row must already be attached to
- * a {@link Keyboard}.
- * @param x the x coordinate of the top-left
- * @param y the y coordinate of the top-left
- * @param parser the XML parser containing the attributes for this key
- * @param keyStyles active key styles set
- */
- public Key(Resources res, Row row, int x, int y, XmlResourceParser parser,
- KeyStyles keyStyles) {
- mKeyboard = row.getKeyboard();
-
- final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- int keyWidth;
- try {
- mHeight = KeyboardParser.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_rowHeight,
- mKeyboard.getKeyboardHeight(), row.mDefaultHeight) - row.mVerticalGap;
- mGap = KeyboardParser.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_horizontalGap,
- mKeyboard.getDisplayWidth(), row.mDefaultHorizontalGap);
- keyWidth = KeyboardParser.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyWidth,
- mKeyboard.getDisplayWidth(), row.mDefaultWidth);
- } finally {
- keyboardAttr.recycle();
- }
-
- final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Key);
- try {
- final KeyStyle style;
- if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) {
- String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
- style = keyStyles.getKeyStyle(styleName);
- if (style == null)
- throw new ParseException("Unknown key style: " + styleName, parser);
- } else {
- style = keyStyles.getEmptyKeyStyle();
- }
-
- final int keyboardWidth = mKeyboard.getDisplayWidth();
- int keyXPos = KeyboardParser.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyXPos, keyboardWidth, x);
- if (keyXPos < 0) {
- // If keyXPos is negative, the actual x-coordinate will be k + keyXPos.
- keyXPos += keyboardWidth;
- if (keyXPos < x) {
- // keyXPos shouldn't be less than x because drawable area for this key starts
- // at x. Or, this key will overlaps the adjacent key on its left hand side.
- keyXPos = x;
- }
- }
- if (keyWidth == KEYWIDTH_FILL_RIGHT) {
- // If keyWidth is zero, the actual key width will be determined to fill out the
- // area up to the right edge of the keyboard.
- keyWidth = keyboardWidth - keyXPos;
- } else if (keyWidth <= KEYWIDTH_FILL_BOTH) {
- // If keyWidth is negative, the actual key width will be determined to fill out the
- // area between the nearest key on the left hand side and the right edge of the
- // keyboard.
- keyXPos = x;
- keyWidth = keyboardWidth - keyXPos;
- }
-
- // Horizontal gap is divided equally to both sides of the key.
- mX = keyXPos + mGap / 2;
- mY = y;
- mWidth = keyWidth - mGap;
-
- final CharSequence[] popupCharacters = style.getTextArray(keyAttr,
- R.styleable.Keyboard_Key_popupCharacters);
- if (res.getBoolean(R.bool.config_digit_popup_characters_enabled)) {
- mPopupCharacters = popupCharacters;
- } else {
- mPopupCharacters = filterOutDigitPopupCharacters(popupCharacters);
- }
- mMaxPopupColumn = style.getInt(keyboardAttr,
- R.styleable.Keyboard_Key_maxPopupKeyboardColumn,
- mKeyboard.getMaxPopupKeyboardColumn());
-
- mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
- mFunctional = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isFunctional, false);
- mSticky = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isSticky, false);
- mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
- mEdgeFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyEdgeFlags, 0)
- | row.mRowEdgeFlags;
-
- final KeyboardIconsSet iconsSet = mKeyboard.mIconsSet;
- mVisualInsetsLeft = KeyboardParser.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_visualInsetsLeft, mKeyboard.getDisplayHeight(), 0);
- mVisualInsetsRight = KeyboardParser.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_visualInsetsRight, mKeyboard.getDisplayHeight(), 0);
- mPreviewIcon = iconsSet.getIcon(style.getInt(
- keyAttr, R.styleable.Keyboard_Key_keyIconPreview,
- KeyboardIconsSet.ICON_UNDEFINED));
- Keyboard.setDefaultBounds(mPreviewIcon);
- mIcon = iconsSet.getIcon(style.getInt(
- keyAttr, R.styleable.Keyboard_Key_keyIcon,
- KeyboardIconsSet.ICON_UNDEFINED));
- Keyboard.setDefaultBounds(mIcon);
- mHintLetter = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLetter);
-
- mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
- mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0);
- mOutputText = style.getText(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
- // Choose the first letter of the label as primary code if not
- // specified.
- final int code = style.getInt(keyAttr, R.styleable.Keyboard_Key_code,
- Keyboard.CODE_UNSPECIFIED);
- if (code == Keyboard.CODE_UNSPECIFIED && !TextUtils.isEmpty(mLabel)) {
- mCode = mLabel.charAt(0);
- } else if (code != Keyboard.CODE_UNSPECIFIED) {
- mCode = code;
- } else {
- mCode = Keyboard.CODE_DUMMY;
- }
-
- final Drawable shiftedIcon = iconsSet.getIcon(style.getInt(
- keyAttr, R.styleable.Keyboard_Key_keyIconShifted,
- KeyboardIconsSet.ICON_UNDEFINED));
- if (shiftedIcon != null)
- mKeyboard.getShiftedIcons().put(this, shiftedIcon);
- } finally {
- keyAttr.recycle();
- }
- }
-
- public boolean hasPopupHint() {
- return (mLabelOption & LABEL_OPTION_POPUP_HINT) != 0;
- }
-
- public boolean hasUppercaseLetter() {
- return (mLabelOption & LABEL_OPTION_HAS_UPPERCASE_LETTER) != 0;
- }
-
- private static boolean isDigitPopupCharacter(CharSequence label) {
- return label != null && label.length() == 1 && Character.isDigit(label.charAt(0));
- }
-
- private static CharSequence[] filterOutDigitPopupCharacters(CharSequence[] popupCharacters) {
- if (popupCharacters == null || popupCharacters.length < 1)
- return null;
- if (popupCharacters.length == 1 && isDigitPopupCharacter(
- PopupCharactersParser.getLabel(popupCharacters[0].toString())))
- return null;
- ArrayList filtered = null;
- for (int i = 0; i < popupCharacters.length; i++) {
- final CharSequence popupSpec = popupCharacters[i];
- if (isDigitPopupCharacter(PopupCharactersParser.getLabel(popupSpec.toString()))) {
- if (filtered == null) {
- filtered = new ArrayList();
- for (int j = 0; j < i; j++)
- filtered.add(popupCharacters[j]);
- }
- } else if (filtered != null) {
- filtered.add(popupSpec);
- }
- }
- if (filtered == null)
- return popupCharacters;
- if (filtered.size() == 0)
- return null;
- return filtered.toArray(new CharSequence[filtered.size()]);
- }
-
- public Drawable getIcon() {
- return mIcon;
- }
-
- public Drawable getPreviewIcon() {
- return mPreviewIcon;
- }
-
- public void setIcon(Drawable icon) {
- mIcon = icon;
- }
-
- public void setPreviewIcon(Drawable icon) {
- mPreviewIcon = icon;
- }
-
- /**
- * Informs the key that it has been pressed, in case it needs to change its appearance or
- * state.
- * @see #onReleased()
- */
- public void onPressed() {
- mPressed = true;
- }
-
- /**
- * Informs the key that it has been released, in case it needs to change its appearance or
- * state.
- * @see #onPressed()
- */
- public void onReleased() {
- mPressed = false;
- }
-
- /**
- * Detects if a point falls on this key.
- * @param x the x-coordinate of the point
- * @param y the y-coordinate of the point
- * @return whether or not the point falls on the key. If the key is attached to an edge, it will
- * assume that all points between the key and the edge are considered to be on the key.
- */
- public boolean isOnKey(int x, int y) {
- final int flags = mEdgeFlags;
- final boolean leftEdge = (flags & Keyboard.EDGE_LEFT) != 0;
- final boolean rightEdge = (flags & Keyboard.EDGE_RIGHT) != 0;
- final boolean topEdge = (flags & Keyboard.EDGE_TOP) != 0;
- final boolean bottomEdge = (flags & Keyboard.EDGE_BOTTOM) != 0;
- final int left = mX - mGap / 2;
- final int right = left + mWidth + mGap;
- final int top = mY;
- final int bottom = top + mHeight + mKeyboard.getVerticalGap();
- // In order to mitigate rounding errors, we use (left <= x <= right) here.
- return (x >= left || leftEdge) && (x <= right || rightEdge)
- && (y >= top || topEdge) && (y <= bottom || bottomEdge);
- }
-
- /**
- * Returns the square of the distance to the nearest edge of the key and the given point.
- * @param x the x-coordinate of the point
- * @param y the y-coordinate of the point
- * @return the square of the distance of the point from the nearest edge of the key
- */
- public int squaredDistanceToEdge(int x, int y) {
- final int left = mX;
- final int right = left + mWidth;
- final int top = mY;
- final int bottom = top + mHeight;
- final int edgeX = x < left ? left : (x > right ? right : x);
- final int edgeY = y < top ? top : (y > bottom ? bottom : y);
- final int dx = x - edgeX;
- final int dy = y - edgeY;
- return dx * dx + dy * dy;
- }
-
- /**
- * Returns the drawable state for the key, based on the current state and type of the key.
- * @return the drawable state of the key.
- * @see android.graphics.drawable.StateListDrawable#setState(int[])
- */
- public int[] getCurrentDrawableState() {
- final boolean pressed = mPressed;
- if (!mSticky && mFunctional) {
- if (pressed) {
- return KEY_STATE_FUNCTIONAL_PRESSED;
- } else {
- return KEY_STATE_FUNCTIONAL_NORMAL;
- }
- }
-
- int[] states = KEY_STATE_NORMAL;
-
- if (mHighlightOn) {
- if (pressed) {
- states = KEY_STATE_PRESSED_ON;
- } else {
- states = KEY_STATE_NORMAL_ON;
- }
- } else {
- if (mSticky) {
- if (pressed) {
- states = KEY_STATE_PRESSED_OFF;
- } else {
- states = KEY_STATE_NORMAL_OFF;
- }
- } else {
- if (pressed) {
- states = KEY_STATE_PRESSED;
- }
- }
- }
- return states;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java
index d5b364818..8954eec59 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java
@@ -26,6 +26,7 @@ import android.util.Xml;
import android.view.InflateException;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.latin.R;
@@ -331,7 +332,7 @@ public class KeyboardParser {
} else {
Key key = new Key(mResources, row, mCurrentX, mCurrentY, parser, mKeyStyles);
if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d popupCharacters=%s />",
- TAG_KEY, (key.mEnabled ? "" : " disabled"), key.mLabel, key.mCode,
+ TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode,
Arrays.toString(key.mPopupCharacters)));
checkEndTag(TAG_KEY, parser);
keys.add(key);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
index 01faae61d..040c16ded 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
@@ -21,6 +21,7 @@ import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.Rect;
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.MiniKeyboard;
diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
index f1224a25a..87ea011fa 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
@@ -16,10 +16,10 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.LatinKeyboard;
-import com.android.inputmethod.keyboard.internal.Key;
import android.content.Context;
import android.text.TextUtils;
--
cgit v1.2.3-83-g751a