aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
authorTadashi G. Takaoka <takaoka@google.com>2010-12-02 03:07:43 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-12-02 03:07:43 -0800
commit26dae3f4e8ffd0f25b78c58598752cd393419bcc (patch)
treefd7280e7e0c0c879958a5c7d8b9376942d447e9b /java/src/com/android/inputmethod/latin
parent18c28f431eadc1b451ca25d14fd683db4b234838 (diff)
parent5a309f57155fb95667c2ccdda730eaf175de8876 (diff)
downloadlatinime-26dae3f4e8ffd0f25b78c58598752cd393419bcc.tar.gz
latinime-26dae3f4e8ffd0f25b78c58598752cd393419bcc.tar.xz
latinime-26dae3f4e8ffd0f25b78c58598752cd393419bcc.zip
Merge "Move some inner static class to top class in new package"
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
-rw-r--r--java/src/com/android/inputmethod/latin/BaseKeyboard.java717
-rw-r--r--java/src/com/android/inputmethod/latin/BaseKeyboardParser.java571
-rw-r--r--java/src/com/android/inputmethod/latin/BaseKeyboardView.java1585
-rw-r--r--java/src/com/android/inputmethod/latin/InputLanguageSelection.java1
-rw-r--r--java/src/com/android/inputmethod/latin/KeyDetector.java112
-rw-r--r--java/src/com/android/inputmethod/latin/KeyStyles.java238
-rw-r--r--java/src/com/android/inputmethod/latin/KeyboardSwitcher.java147
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java116
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIMEDebugSettings.java1
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIMESettings.java3
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIMEUtil.java3
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java4
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboard.java720
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java89
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboardView.java376
-rw-r--r--java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java60
-rw-r--r--java/src/com/android/inputmethod/latin/PointerTracker.java546
-rw-r--r--java/src/com/android/inputmethod/latin/ProximityKeyDetector.java77
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java5
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java1
-rw-r--r--java/src/com/android/inputmethod/latin/SwipeTracker.java157
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java2
-rw-r--r--java/src/com/android/inputmethod/latin/Tutorial.java4
-rw-r--r--java/src/com/android/inputmethod/latin/UserDictionary.java1
24 files changed, 102 insertions, 5434 deletions
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboard.java b/java/src/com/android/inputmethod/latin/BaseKeyboard.java
deleted file mode 100644
index e2331f334..000000000
--- a/java/src/com/android/inputmethod/latin/BaseKeyboard.java
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboardParser.ParseException;
-import com.android.inputmethod.latin.KeyStyles.KeyStyle;
-import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-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.Log;
-import android.util.Xml;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
- * consists of rows of keys.
- * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
- * <pre>
- * &lt;Keyboard
- * latin:keyWidth="%10p"
- * latin:keyHeight="50px"
- * latin:horizontalGap="2px"
- * latin:verticalGap="2px" &gt;
- * &lt;Row latin:keyWidth="32px" &gt;
- * &lt;Key latin:keyLabel="A" /&gt;
- * ...
- * &lt;/Row&gt;
- * ...
- * &lt;/Keyboard&gt;
- * </pre>
- */
-public class BaseKeyboard {
-
- static final String TAG = "BaseKeyboard";
-
- public static final int EDGE_LEFT = 0x01;
- public static final int EDGE_RIGHT = 0x02;
- public static final int EDGE_TOP = 0x04;
- public static final int EDGE_BOTTOM = 0x08;
-
- public static final int KEYCODE_SHIFT = -1;
- public static final int KEYCODE_MODE_CHANGE = -2;
- public static final int KEYCODE_CANCEL = -3;
- public static final int KEYCODE_DONE = -4;
- public static final int KEYCODE_DELETE = -5;
- public static final int KEYCODE_ALT = -6;
-
- /** Horizontal gap default for all rows */
- private int mDefaultHorizontalGap;
-
- /** Default key width */
- private int mDefaultWidth;
-
- /** Default key height */
- private int mDefaultHeight;
-
- /** Default gap between rows */
- private int mDefaultVerticalGap;
-
- /** Is the keyboard in the shifted state */
- private boolean mShifted;
-
- /** List of shift keys in this keyboard */
- private final List<Key> mShiftKeys = new ArrayList<Key>();
-
- /** List of shift keys and its shifted state icon */
- private final HashMap<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>();
-
- /** Total height of the keyboard, including the padding and keys */
- private int mTotalHeight;
-
- /**
- * Total width of the keyboard, including left side gaps and keys, but not any gaps on the
- * right side.
- */
- private int mTotalWidth;
-
- /** List of keys in this keyboard */
- private final List<Key> mKeys = new ArrayList<Key>();
-
- /** Width of the screen available to fit the keyboard */
- private final int mDisplayWidth;
-
- /** Height of the screen */
- private final int mDisplayHeight;
-
- protected final KeyboardId mId;
-
- // Variables for pre-computing nearest keys.
-
- public final int GRID_WIDTH;
- public final int GRID_HEIGHT;
- private final int GRID_SIZE;
- private int mCellWidth;
- private int mCellHeight;
- private int[][] mGridNeighbors;
- private int mProximityThreshold;
- private static int[] EMPTY_INT_ARRAY = new int[0];
- /** Number of key widths from current touch point to search for nearest keys. */
- private static float SEARCH_DISTANCE = 1.2f;
-
- /**
- * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
- * Some of the key size defaults can be overridden per row from what the {@link BaseKeyboard}
- * defines.
- */
- public static class Row {
- /** Default width of a key in this row. */
- public int defaultWidth;
- /** Default height of a key in this row. */
- public int defaultHeight;
- /** Default horizontal gap between keys in this row. */
- public int defaultHorizontalGap;
- /** Vertical gap following this row. */
- public int verticalGap;
- /**
- * Edge flags for this row of keys. Possible values that can be assigned are
- * {@link BaseKeyboard#EDGE_TOP EDGE_TOP} and {@link BaseKeyboard#EDGE_BOTTOM EDGE_BOTTOM}
- */
- public int rowEdgeFlags;
-
- private final BaseKeyboard parent;
-
- private Row(BaseKeyboard parent) {
- this.parent = parent;
- }
-
- public Row(Resources res, BaseKeyboard parent, XmlResourceParser parser) {
- this.parent = parent;
- TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard);
- defaultWidth = BaseKeyboardParser.getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_keyWidth,
- parent.mDisplayWidth, parent.mDefaultWidth);
- defaultHeight = BaseKeyboardParser.getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_keyHeight,
- parent.mDisplayHeight, parent.mDefaultHeight);
- defaultHorizontalGap = BaseKeyboardParser.getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_horizontalGap,
- parent.mDisplayWidth, parent.mDefaultHorizontalGap);
- verticalGap = BaseKeyboardParser.getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_verticalGap,
- parent.mDisplayHeight, parent.mDefaultVerticalGap);
- a.recycle();
- a = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard_Row);
- rowEdgeFlags = a.getInt(R.styleable.BaseKeyboard_Row_rowEdgeFlags, 0);
- }
- }
-
- /**
- * Class for describing the position and characteristics of a single key in the keyboard.
- */
- public static class Key {
- /**
- * All the key codes (unicode or custom code) that this key could generate, zero'th
- * being the most important.
- */
- public int[] codes;
- /** The unicode that this key generates in manual temporary upper case mode. */
- public int manualTemporaryUpperCaseCode;
-
- /** Label to display */
- public CharSequence label;
- /** Option of the label */
- public int labelOption;
-
- /** Icon to display instead of a label. Icon takes precedence over a label */
- public Drawable icon;
- /** Hint icon to display on the key in conjunction with the label */
- public Drawable hintIcon;
- /** Preview version of the icon, for the preview popup */
- /**
- * The hint icon to display on the key when keyboard is in manual temporary upper case
- * mode.
- */
- public Drawable manualTemporaryUpperCaseHintIcon;
-
- public Drawable iconPreview;
- /** Width of the key, not including the gap */
- public int width;
- /** Height of the key, not including the gap */
- public int height;
- /** The horizontal gap before this key */
- public int gap;
- /** Whether this key is sticky, i.e., a toggle key */
- public boolean sticky;
- /** X coordinate of the key in the keyboard layout */
- public int x;
- /** Y coordinate of the key in the keyboard layout */
- public int y;
- /** The current pressed state of this key */
- public boolean pressed;
- /** If this is a sticky key, is it on? */
- public boolean on;
- /** Text to output when pressed. This can be multiple characters, like ".com" */
- public CharSequence text;
- /** Popup characters */
- public CharSequence popupCharacters;
-
- /**
- * 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 BaseKeyboard#EDGE_LEFT}, {@link BaseKeyboard#EDGE_RIGHT},
- * {@link BaseKeyboard#EDGE_TOP} and {@link BaseKeyboard#EDGE_BOTTOM}.
- */
- public int edgeFlags;
- /** Whether this is a modifier key, such as Shift or Alt */
- public boolean modifier;
- /** The BaseKeyboard that this key belongs to */
- protected final BaseKeyboard keyboard;
- /**
- * If this key pops up a mini keyboard, this is the resource id for the XML layout for that
- * keyboard.
- */
- public int popupResId;
- /** Whether this key repeats itself when held down */
- public boolean repeatable;
-
-
- 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
- };
-
- /** Create an empty key with no attributes. */
- public Key(Row parent) {
- keyboard = parent.parent;
- height = parent.defaultHeight;
- gap = parent.defaultHorizontalGap;
- width = parent.defaultWidth - gap;
- edgeFlags = parent.rowEdgeFlags;
- }
-
- /** 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 parent the row that this key belongs to. The row must already be attached to
- * a {@link BaseKeyboard}.
- * @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
- */
- public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser,
- KeyStyles keyStyles) {
- this(parent);
-
- TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard);
- height = BaseKeyboardParser.getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_keyHeight,
- keyboard.mDisplayHeight, parent.defaultHeight);
- gap = BaseKeyboardParser.getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_horizontalGap,
- keyboard.mDisplayWidth, parent.defaultHorizontalGap);
- width = BaseKeyboardParser.getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_keyWidth,
- keyboard.mDisplayWidth, parent.defaultWidth) - gap;
- a.recycle();
-
- a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.BaseKeyboard_Key);
-
- final KeyStyle style;
- if (a.hasValue(R.styleable.BaseKeyboard_Key_keyStyle)) {
- String styleName = a.getString(R.styleable.BaseKeyboard_Key_keyStyle);
- style = keyStyles.getKeyStyle(styleName);
- if (style == null)
- throw new ParseException("Unknown key style: " + styleName, parser);
- } else {
- style = keyStyles.getEmptyKeyStyle();
- }
-
- // Horizontal gap is divided equally to both sides of the key.
- this.x = x + gap / 2;
- this.y = y;
-
- codes = style.getIntArray(a, R.styleable.BaseKeyboard_Key_codes);
- iconPreview = style.getDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview);
- setDefaultBounds(iconPreview);
- popupCharacters = style.getText(a, R.styleable.BaseKeyboard_Key_popupCharacters);
- popupResId = style.getResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard, 0);
- repeatable = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable, false);
- modifier = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isModifier, false);
- sticky = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isSticky, false);
- edgeFlags = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyEdgeFlags, 0);
- edgeFlags |= parent.rowEdgeFlags;
-
- icon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon);
- setDefaultBounds(icon);
- hintIcon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon);
- setDefaultBounds(hintIcon);
- manualTemporaryUpperCaseHintIcon = style.getDrawable(a,
- R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseHintIcon);
- setDefaultBounds(manualTemporaryUpperCaseHintIcon);
-
- label = style.getText(a, R.styleable.BaseKeyboard_Key_keyLabel);
- labelOption = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption, 0);
- manualTemporaryUpperCaseCode = style.getInt(a,
- R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseCode, 0);
- text = style.getText(a, R.styleable.BaseKeyboard_Key_keyOutputText);
- final Drawable shiftedIcon = style.getDrawable(a,
- R.styleable.BaseKeyboard_Key_shiftedIcon);
- if (shiftedIcon != null)
- keyboard.getShiftedIcons().put(this, shiftedIcon);
-
- if (codes == null && !TextUtils.isEmpty(label)) {
- codes = new int[] { label.charAt(0) };
- }
- a.recycle();
- }
-
- /**
- * Informs the key that it has been pressed, in case it needs to change its appearance or
- * state.
- * @see #onReleased(boolean)
- */
- public void onPressed() {
- pressed = !pressed;
- }
-
- /**
- * Changes the pressed state of the key. If it is a sticky key, it will also change the
- * toggled state of the key if the finger was release inside.
- * @param inside whether the finger was released inside the key
- * @see #onPressed()
- */
- public void onReleased(boolean inside) {
- pressed = !pressed;
- if (sticky) {
- on = !on;
- }
- }
-
- /**
- * Detects if a point falls inside 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 inside 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
- * inside the key.
- */
- public boolean isInside(int x, int y) {
- boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0;
- boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0;
- boolean topEdge = (edgeFlags & EDGE_TOP) > 0;
- boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0;
- if ((x >= this.x || (leftEdge && x <= this.x + this.width))
- && (x < this.x + this.width || (rightEdge && x >= this.x))
- && (y >= this.y || (topEdge && y <= this.y + this.height))
- && (y < this.y + this.height || (bottomEdge && y >= this.y))) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * 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 = this.x;
- final int right = left + this.width;
- final int top = this.y;
- final int bottom = top + this.height;
- 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() {
- int[] states = KEY_STATE_NORMAL;
-
- if (on) {
- if (pressed) {
- states = KEY_STATE_PRESSED_ON;
- } else {
- states = KEY_STATE_NORMAL_ON;
- }
- } else {
- if (sticky) {
- if (pressed) {
- states = KEY_STATE_PRESSED_OFF;
- } else {
- states = KEY_STATE_NORMAL_OFF;
- }
- } else {
- if (pressed) {
- states = KEY_STATE_PRESSED;
- }
- }
- }
- return states;
- }
- }
-
- /**
- * Creates a keyboard from the given xml key layout file.
- * @param context the application or service context
- * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
- */
- public BaseKeyboard(Context context, int xmlLayoutResId) {
- this(context, xmlLayoutResId, null);
- }
-
- /**
- * Creates a keyboard from the given keyboard identifier.
- * @param context the application or service context
- * @param id keyboard identifier
- */
- public BaseKeyboard(Context context, KeyboardId id) {
- this(context, id.getXmlId(), id);
- }
-
- /**
- * Creates a keyboard from the given xml key layout file.
- * @param context the application or service context
- * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
- * @param id keyboard identifier
- */
- private BaseKeyboard(Context context, int xmlLayoutResId, KeyboardId id) {
- this(context, xmlLayoutResId, id,
- context.getResources().getDisplayMetrics().widthPixels,
- context.getResources().getDisplayMetrics().heightPixels);
- }
-
- private BaseKeyboard(Context context, int xmlLayoutResId, KeyboardId id, int width,
- int height) {
- Resources res = context.getResources();
- GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
- GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
- GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
-
- mDisplayWidth = width;
- mDisplayHeight = height;
-
- mDefaultHorizontalGap = 0;
- setKeyWidth(mDisplayWidth / 10);
- mDefaultVerticalGap = 0;
- mDefaultHeight = mDefaultWidth;
- mId = id;
- loadKeyboard(context, xmlLayoutResId);
- }
-
- /**
- * <p>Creates a blank keyboard from the given resource file and populates it with the specified
- * characters in left-to-right, top-to-bottom fashion, using the specified number of columns.
- * </p>
- * <p>If the specified number of columns is -1, then the keyboard will fit as many keys as
- * possible in each row.</p>
- * @param context the application or service context
- * @param layoutTemplateResId the layout template file, containing no keys.
- * @param characters the list of characters to display on the keyboard. One key will be created
- * for each character.
- * @param columns the number of columns of keys to display. If this number is greater than the
- * number of keys that can fit in a row, it will be ignored. If this number is -1, the
- * keyboard will fit as many keys as possible in each row.
- */
- public BaseKeyboard(Context context, int layoutTemplateResId,
- CharSequence characters, int columns, int horizontalPadding) {
- this(context, layoutTemplateResId);
- int x = 0;
- int y = 0;
- int column = 0;
- mTotalWidth = 0;
-
- Row row = new Row(this);
- row.defaultHeight = mDefaultHeight;
- row.defaultWidth = mDefaultWidth;
- row.defaultHorizontalGap = mDefaultHorizontalGap;
- row.verticalGap = mDefaultVerticalGap;
- row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM;
- final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns;
- for (int i = 0; i < characters.length(); i++) {
- char c = characters.charAt(i);
- if (column >= maxColumns
- || x + mDefaultWidth + horizontalPadding > mDisplayWidth) {
- x = 0;
- y += mDefaultVerticalGap + mDefaultHeight;
- column = 0;
- }
- final Key key = new Key(row);
- // Horizontal gap is divided equally to both sides of the key.
- key.x = x + key.gap / 2;
- key.y = y;
- key.label = String.valueOf(c);
- key.codes = new int[] { c };
- column++;
- x += key.width + key.gap;
- mKeys.add(key);
- if (x > mTotalWidth) {
- mTotalWidth = x;
- }
- }
- mTotalHeight = y + mDefaultHeight;
- }
-
- public KeyboardId getKeyboardId() {
- return mId;
- }
-
- public List<Key> getKeys() {
- return mKeys;
- }
-
- protected int getHorizontalGap() {
- return mDefaultHorizontalGap;
- }
-
- protected void setHorizontalGap(int gap) {
- mDefaultHorizontalGap = gap;
- }
-
- protected int getVerticalGap() {
- return mDefaultVerticalGap;
- }
-
- protected void setVerticalGap(int gap) {
- mDefaultVerticalGap = gap;
- }
-
- protected int getKeyHeight() {
- return mDefaultHeight;
- }
-
- protected void setKeyHeight(int height) {
- mDefaultHeight = height;
- }
-
- protected int getKeyWidth() {
- return mDefaultWidth;
- }
-
- protected void setKeyWidth(int width) {
- mDefaultWidth = width;
- final int threshold = (int) (width * SEARCH_DISTANCE);
- mProximityThreshold = threshold * threshold;
- }
-
- /**
- * Returns the total height of the keyboard
- * @return the total height of the keyboard
- */
- public int getHeight() {
- return mTotalHeight;
- }
-
- public int getMinWidth() {
- return mTotalWidth;
- }
-
- public int getKeyboardHeight() {
- return mDisplayHeight;
- }
-
- public int getKeyboardWidth() {
- return mDisplayWidth;
- }
-
- public boolean setShifted(boolean shiftState) {
- for (final Key key : mShiftKeys) {
- key.on = shiftState;
- }
- if (mShifted != shiftState) {
- mShifted = shiftState;
- return true;
- }
- return false;
- }
-
- public boolean isShiftedOrShiftLocked() {
- return mShifted;
- }
-
- public List<Key> getShiftKeys() {
- return mShiftKeys;
- }
-
- public Map<Key, Drawable> getShiftedIcons() {
- return mShiftedIcons;
- }
-
- private void computeNearestNeighbors() {
- // Round-up so we don't have any pixels outside the grid
- mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
- mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
- mGridNeighbors = new int[GRID_SIZE][];
- final int[] indices = new int[mKeys.size()];
- final int gridWidth = GRID_WIDTH * mCellWidth;
- final int gridHeight = GRID_HEIGHT * mCellHeight;
- final int threshold = mProximityThreshold;
- for (int x = 0; x < gridWidth; x += mCellWidth) {
- for (int y = 0; y < gridHeight; y += mCellHeight) {
- final int centerX = x + mCellWidth / 2;
- final int centerY = y + mCellHeight / 2;
- int count = 0;
- for (int i = 0; i < mKeys.size(); i++) {
- final Key key = mKeys.get(i);
- if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
- indices[count++] = i;
- }
- final int[] cell = new int[count];
- System.arraycopy(indices, 0, cell, 0, count);
- mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
- }
- }
- }
-
- /**
- * Returns the indices of the keys that are closest to the given point.
- * @param x the x-coordinate of the point
- * @param y the y-coordinate of the point
- * @return the array of integer indices for the nearest keys to the given point. If the given
- * point is out of range, then an array of size zero is returned.
- */
- public int[] getNearestKeys(int x, int y) {
- if (mGridNeighbors == null) computeNearestNeighbors();
- if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
- int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
- if (index < GRID_SIZE) {
- return mGridNeighbors[index];
- }
- }
- return EMPTY_INT_ARRAY;
- }
-
- // TODO should be private
- protected BaseKeyboard.Row createRowFromXml(Resources res, XmlResourceParser parser) {
- return new BaseKeyboard.Row(res, this, parser);
- }
-
- // TODO should be private
- protected BaseKeyboard.Key createKeyFromXml(Resources res, Row parent, int x, int y,
- XmlResourceParser parser, KeyStyles keyStyles) {
- return new BaseKeyboard.Key(res, parent, x, y, parser, keyStyles);
- }
-
- private void loadKeyboard(Context context, int xmlLayoutResId) {
- try {
- final Resources res = context.getResources();
- BaseKeyboardParser parser = new BaseKeyboardParser(this, res);
- parser.parseKeyboard(res.getXml(xmlLayoutResId));
- // mTotalWidth is the width of this keyboard which is maximum width of row.
- mTotalWidth = parser.getMaxRowWidth();
- mTotalHeight = parser.getTotalHeight();
- } catch (XmlPullParserException e) {
- Log.w(TAG, "keyboard XML parse error: " + e);
- throw new IllegalArgumentException(e);
- } catch (IOException e) {
- Log.w(TAG, "keyboard XML parse error: " + e);
- throw new RuntimeException(e);
- }
- }
-
- protected static void setDefaultBounds(Drawable drawable) {
- if (drawable != null)
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight());
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
deleted file mode 100644
index 38b2a1b57..000000000
--- a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboard.Key;
-import com.android.inputmethod.latin.BaseKeyboard.Row;
-import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.util.Log;
-import android.util.TypedValue;
-import android.util.Xml;
-import android.view.InflateException;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Parser for BaseKeyboard.
- *
- * This class parses Keyboard XML file and fill out keys in BaseKeyboard.
- * The Keyboard XML file looks like:
- * <pre>
- * &gt;!-- xml/keyboard.xml --&lt;
- * &gt;Keyboard keyboard_attributes*&lt;
- * &gt;!-- Keyboard Content --&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;!-- Row Content --&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;Spacer horizontalGap="0.2in" /&lt;
- * &gt;include keyboardLayout="@xml/other_keys"&lt;
- * ...
- * &gt;/Row&lt;
- * &gt;include keyboardLayout="@xml/other_rows"&lt;
- * ...
- * &gt;/Keyboard&lt;
- * </pre>
- * The XML file which is included in other file must have &gt;merge&lt; as root element, such as:
- * <pre>
- * &gt;!-- xml/other_keys.xml --&lt;
- * &gt;merge&lt;
- * &gt;Key key_attributes* /&lt;
- * ...
- * &gt;/merge&lt;
- * </pre>
- * and
- * <pre>
- * &gt;!-- xml/other_rows.xml --&lt;
- * &gt;merge&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;/Row&lt;
- * ...
- * &gt;/merge&lt;
- * </pre>
- * You can also use switch-case-default tags to select Rows and Keys.
- * <pre>
- * &gt;switch&lt;
- * &gt;case case_attribute*&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/case&lt;
- * ...
- * &gt;default&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/default&lt;
- * &gt;/switch&lt;
- * </pre>
- * You can declare Key style and specify styles within Key tags.
- * <pre>
- * &gt;switch&lt;
- * &gt;case colorScheme="white"&lt;
- * &gt;key-style styleName="shift-key" parentStyle="modifier-key"
- * keyIcon="@drawable/sym_keyboard_shift"
- * /&lt;
- * &gt;/case&lt;
- * &gt;case colorScheme="black"&lt;
- * &gt;key-style styleName="shift-key" parentStyle="modifier-key"
- * keyIcon="@drawable/sym_bkeyboard_shift"
- * /&lt;
- * &gt;/case&lt;
- * &gt;/switch&lt;
- * ...
- * &gt;Key keyStyle="shift-key" ... /&lt;
- * </pre>
- */
-
-public class BaseKeyboardParser {
- private static final String TAG = "BaseKeyboardParser";
- private static final boolean DEBUG_TAG = false;
-
- // Keyboard XML Tags
- private static final String TAG_KEYBOARD = "Keyboard";
- private static final String TAG_ROW = "Row";
- private static final String TAG_KEY = "Key";
- private static final String TAG_SPACER = "Spacer";
- private static final String TAG_INCLUDE = "include";
- private static final String TAG_MERGE = "merge";
- private static final String TAG_SWITCH = "switch";
- private static final String TAG_CASE = "case";
- private static final String TAG_DEFAULT = "default";
- private static final String TAG_KEY_STYLE = "key-style";
-
- private final BaseKeyboard mKeyboard;
- private final Resources mResources;
-
- private int mCurrentX = 0;
- private int mCurrentY = 0;
- private int mMaxRowWidth = 0;
- private int mTotalHeight = 0;
- private Row mCurrentRow = null;
- private final KeyStyles mKeyStyles = new KeyStyles();
-
- public BaseKeyboardParser(BaseKeyboard keyboard, Resources res) {
- mKeyboard = keyboard;
- mResources = res;
- }
-
- public int getMaxRowWidth() {
- return mMaxRowWidth;
- }
-
- public int getTotalHeight() {
- return mTotalHeight;
- }
-
- public void parseKeyboard(XmlResourceParser parser)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
- if (event == XmlResourceParser.START_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugStartTag("parseKeyboard", tag, false);
- if (TAG_KEYBOARD.equals(tag)) {
- parseKeyboardAttributes(parser);
- parseKeyboardContent(parser, mKeyboard.getKeys());
- break;
- } else {
- throw new IllegalStartTag(parser, TAG_KEYBOARD);
- }
- }
- }
- }
-
- private void parseKeyboardAttributes(XmlResourceParser parser) {
- final BaseKeyboard keyboard = mKeyboard;
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard);
- final int width = keyboard.getKeyboardWidth();
- final int height = keyboard.getKeyboardHeight();
- keyboard.setKeyWidth(getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_keyWidth, width, width / 10));
- keyboard.setKeyHeight(getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_keyHeight, height, 50));
- keyboard.setHorizontalGap(getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_horizontalGap, width, 0));
- keyboard.setVerticalGap(getDimensionOrFraction(a,
- R.styleable.BaseKeyboard_verticalGap, height, 0));
- a.recycle();
- if (DEBUG_TAG) Log.d(TAG, "id=" + keyboard.mId);
- }
-
- private void parseKeyboardContent(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
- if (event == XmlResourceParser.START_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugStartTag("parseKeyboardContent", tag, keys == null);
- if (TAG_ROW.equals(tag)) {
- Row row = mKeyboard.createRowFromXml(mResources, parser);
- if (keys != null)
- startRow(row);
- parseRowContent(parser, row, keys);
- } else if (TAG_INCLUDE.equals(tag)) {
- parseIncludeKeyboardContent(parser, keys);
- } else if (TAG_SWITCH.equals(tag)) {
- parseSwitchKeyboardContent(parser, keys);
- } else if (TAG_KEY_STYLE.equals(tag)) {
- parseKeyStyle(parser, keys);
- } else {
- throw new IllegalStartTag(parser, TAG_ROW);
- }
- } else if (event == XmlResourceParser.END_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugEndTag("parseKeyboardContent", tag, keys == null);
- if (TAG_KEYBOARD.equals(tag)) {
- endKeyboard(mKeyboard.getVerticalGap());
- break;
- } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)) {
- break;
- } else if (TAG_MERGE.equals(tag)) {
- break;
- } else if (TAG_KEY_STYLE.equals(tag)) {
- continue;
- } else {
- throw new IllegalEndTag(parser, TAG_ROW);
- }
- }
- }
- }
-
- private void parseRowContent(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
- if (event == XmlResourceParser.START_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugStartTag("parseRowContent", tag, keys == null);
- if (TAG_KEY.equals(tag)) {
- parseKey(parser, row, keys);
- } else if (TAG_SPACER.equals(tag)) {
- parseSpacer(parser, keys);
- } else if (TAG_INCLUDE.equals(tag)) {
- parseIncludeRowContent(parser, row, keys);
- } else if (TAG_SWITCH.equals(tag)) {
- parseSwitchRowContent(parser, row, keys);
- } else if (TAG_KEY_STYLE.equals(tag)) {
- parseKeyStyle(parser, keys);
- } else {
- throw new IllegalStartTag(parser, TAG_KEY);
- }
- } else if (event == XmlResourceParser.END_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugEndTag("parseRowContent", tag, keys == null);
- if (TAG_ROW.equals(tag)) {
- if (keys != null)
- endRow();
- break;
- } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)) {
- break;
- } else if (TAG_MERGE.equals(tag)) {
- break;
- } else if (TAG_KEY_STYLE.equals(tag)) {
- continue;
- } else {
- throw new IllegalEndTag(parser, TAG_KEY);
- }
- }
- }
- }
-
- private void parseKey(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (keys == null) {
- checkEndTag(TAG_KEY, parser);
- } else {
- Key key = mKeyboard.createKeyFromXml(mResources, row, mCurrentX, mCurrentY, parser,
- mKeyStyles);
- checkEndTag(TAG_KEY, parser);
- keys.add(key);
- if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT)
- mKeyboard.getShiftKeys().add(key);
- endKey(key);
- }
- }
-
- private void parseSpacer(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (keys == null) {
- checkEndTag(TAG_SPACER, parser);
- } else {
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard);
- final int gap = getDimensionOrFraction(a, R.styleable.BaseKeyboard_horizontalGap,
- mKeyboard.getKeyboardWidth(), 0);
- a.recycle();
- checkEndTag(TAG_SPACER, parser);
- setSpacer(gap);
- }
- }
-
- private void parseIncludeKeyboardContent(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseIncludeInternal(parser, null, keys);
- }
-
- private void parseIncludeRowContent(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseIncludeInternal(parser, row, keys);
- }
-
- private void parseIncludeInternal(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (keys == null) {
- checkEndTag(TAG_INCLUDE, parser);
- } else {
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard_Include);
- final int keyboardLayout = a.getResourceId(
- R.styleable.BaseKeyboard_Include_keyboardLayout, 0);
- a.recycle();
-
- checkEndTag(TAG_INCLUDE, parser);
- if (keyboardLayout == 0)
- throw new ParseException("No keyboardLayout attribute in <include/>", parser);
- if (DEBUG_TAG) Log.d(TAG, String.format(" keyboardLayout=0x%08x", keyboardLayout));
- parseMerge(mResources.getLayout(keyboardLayout), row, keys);
- }
- }
-
- private void parseMerge(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
- if (event == XmlResourceParser.START_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugStartTag("parseMerge", tag, keys == null);
- if (TAG_MERGE.equals(tag)) {
- if (row == null) {
- parseKeyboardContent(parser, keys);
- } else {
- parseRowContent(parser, row, keys);
- }
- break;
- } else {
- throw new ParseException(
- "Included keyboard layout must have <merge> root element", parser);
- }
- }
- }
- }
-
- private void parseSwitchKeyboardContent(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseSwitchInternal(parser, null, keys);
- }
-
- private void parseSwitchRowContent(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseSwitchInternal(parser, row, keys);
- }
-
- private void parseSwitchInternal(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- boolean selected = false;
- int event;
- if (DEBUG_TAG) Log.d(TAG, "parseSwitchInternal: id=" + mKeyboard.mId);
- while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
- if (event == XmlResourceParser.START_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugStartTag("parseSwitchInternal", tag, keys == null);
- if (TAG_CASE.equals(tag)) {
- selected |= parseCase(parser, row, selected ? null : keys);
- } else if (TAG_DEFAULT.equals(tag)) {
- selected |= parseDefault(parser, row, selected ? null : keys);
- } else {
- throw new IllegalStartTag(parser, TAG_KEY);
- }
- } else if (event == XmlResourceParser.END_TAG) {
- final String tag = parser.getName();
- if (DEBUG_TAG) debugEndTag("parseRowContent", tag, keys == null);
- if (TAG_SWITCH.equals(tag)) {
- break;
- } else {
- throw new IllegalEndTag(parser, TAG_KEY);
- }
- }
- }
- }
-
- private boolean parseCase(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- final boolean selected = parseCaseCondition(parser);
- if (row == null) {
- // Processing Rows.
- parseKeyboardContent(parser, selected ? keys : null);
- } else {
- // Processing Keys.
- parseRowContent(parser, row, selected ? keys : null);
- }
- return selected;
- }
-
- private boolean parseCaseCondition(XmlResourceParser parser) {
- final KeyboardId id = mKeyboard.mId;
- if (id == null)
- return true;
-
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard_Case);
- final TypedArray viewAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboardView);
- try {
- final boolean modeMatched = matchInteger(a,
- R.styleable.BaseKeyboard_Case_mode, id.mMode);
- final boolean settingsKeyMatched = matchBoolean(a,
- R.styleable.BaseKeyboard_Case_hasSettingsKey, id.mHasSettingsKey);
- final boolean voiceEnabledMatched = matchBoolean(a,
- R.styleable.BaseKeyboard_Case_voiceKeyEnabled, id.mVoiceKeyEnabled);
- final boolean voiceKeyMatched = matchBoolean(a,
- R.styleable.BaseKeyboard_Case_hasVoiceKey, id.mHasVoiceKey);
- final boolean colorSchemeMatched = matchInteger(viewAttr,
- R.styleable.BaseKeyboardView_colorScheme, id.mColorScheme);
- // As noted at KeyboardSwitcher.KeyboardId class, we are interested only in
- // enum value masked by IME_MASK_ACTION and IME_FLAG_NO_ENTER_ACTION. So matching
- // this attribute with id.mImeOptions as integer value is enough for our purpose.
- final boolean imeOptionsMatched = matchInteger(a,
- R.styleable.BaseKeyboard_Case_imeOptions, id.mImeOptions);
- final boolean selected = modeMatched && settingsKeyMatched && voiceEnabledMatched
- && voiceKeyMatched && colorSchemeMatched && imeOptionsMatched;
-
- if (DEBUG_TAG) {
- Log.d(TAG, String.format(
- "parseCaseCondition: %s%s%s%s%s%s%s",
- Boolean.toString(selected).toUpperCase(),
- debugInteger(a, R.styleable.BaseKeyboard_Case_mode, "mode"),
- debugBoolean(a, R.styleable.BaseKeyboard_Case_hasSettingsKey,
- "hasSettingsKey"),
- debugBoolean(a, R.styleable.BaseKeyboard_Case_voiceKeyEnabled,
- "voiceKeyEnabled"),
- debugBoolean(a, R.styleable.BaseKeyboard_Case_hasVoiceKey, "hasVoiceKey"),
- debugInteger(viewAttr, R.styleable.BaseKeyboardView_colorScheme,
- "colorScheme"),
- debugInteger(a, R.styleable.BaseKeyboard_Case_imeOptions, "imeOptions")));
- }
-
- return selected;
- } finally {
- a.recycle();
- viewAttr.recycle();
- }
- }
-
- private static boolean matchInteger(TypedArray a, int index, int value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || a.getInt(index, 0) == value;
- }
-
- private static boolean matchBoolean(TypedArray a, int index, boolean value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || a.getBoolean(index, false) == value;
- }
-
- private boolean parseDefault(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (row == null) {
- parseKeyboardContent(parser, keys);
- } else {
- parseRowContent(parser, row, keys);
- }
- return true;
- }
-
- private void parseKeyStyle(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard_KeyStyle);
- TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.BaseKeyboard_Key);
- try {
- if (!a.hasValue(R.styleable.BaseKeyboard_KeyStyle_styleName))
- throw new ParseException("<" + TAG_KEY_STYLE
- + "/> needs styleName attribute", parser);
- if (keys != null)
- mKeyStyles.parseKeyStyleAttributes(a, keyAttrs, parser);
- } finally {
- a.recycle();
- keyAttrs.recycle();
- }
- }
-
- private static void checkEndTag(String tag, XmlResourceParser parser)
- throws XmlPullParserException, IOException {
- if (parser.next() == XmlResourceParser.END_TAG && tag.equals(parser.getName()))
- return;
- throw new NonEmptyTag(tag, parser);
- }
-
- private void startRow(Row row) {
- mCurrentX = 0;
- mCurrentRow = row;
- }
-
- private void endRow() {
- if (mCurrentRow == null)
- throw new InflateException("orphant end row tag");
- mCurrentY += mCurrentRow.verticalGap + mCurrentRow.defaultHeight;
- mCurrentRow = null;
- }
-
- private void endKey(Key key) {
- mCurrentX += key.gap + key.width;
- if (mCurrentX > mMaxRowWidth)
- mMaxRowWidth = mCurrentX;
- }
-
- private void endKeyboard(int defaultVerticalGap) {
- mTotalHeight = mCurrentY - defaultVerticalGap;
- }
-
- private void setSpacer(int gap) {
- mCurrentX += gap;
- }
-
- public static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) {
- final TypedValue value = a.peekValue(index);
- if (value == null)
- return defValue;
- if (value.type == TypedValue.TYPE_DIMENSION) {
- return a.getDimensionPixelOffset(index, defValue);
- } else if (value.type == TypedValue.TYPE_FRACTION) {
- // Round it to avoid values like 47.9999 from getting truncated
- return Math.round(a.getFraction(index, base, base, defValue));
- }
- return defValue;
- }
-
- @SuppressWarnings("serial")
- public static class ParseException extends InflateException {
- public ParseException(String msg, XmlResourceParser parser) {
- super(msg + " at line " + parser.getLineNumber());
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalStartTag extends ParseException {
- public IllegalStartTag(XmlResourceParser parser, String parent) {
- super("Illegal start tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalEndTag extends ParseException {
- public IllegalEndTag(XmlResourceParser parser, String parent) {
- super("Illegal end tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class NonEmptyTag extends ParseException {
- public NonEmptyTag(String tag, XmlResourceParser parser) {
- super(tag + " must be empty tag", parser);
- }
- }
-
- private static void debugStartTag(String title, String tag, boolean skip) {
- Log.d(TAG, title + ": <" + tag + ">" + (skip ? " skip" : ""));
- }
-
- private static void debugEndTag(String title, String tag, boolean skip) {
- Log.d(TAG, title + ": </" + tag + ">" + (skip ? " skip" : ""));
- }
-
- private static String debugInteger(TypedArray a, int index, String name) {
- return a.hasValue(index) ? " " + name + "=" + a.getInt(index, 0) : "";
- }
-
- private static String debugBoolean(TypedArray a, int index, String name) {
- return a.hasValue(index) ? " " + name + "=" + a.getBoolean(index, false) : "";
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java b/java/src/com/android/inputmethod/latin/BaseKeyboardView.java
deleted file mode 100644
index 3193cd46e..000000000
--- a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java
+++ /dev/null
@@ -1,1585 +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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboard.Key;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.Region.Op;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.GestureDetector;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.widget.PopupWindow;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.WeakHashMap;
-
-/**
- * A view that renders a virtual {@link LatinKeyboard}. It handles rendering of keys and
- * detecting key presses and touch movements.
- *
- * TODO: References to LatinKeyboard in this class should be replaced with ones to its base class.
- *
- * @attr ref R.styleable#BaseKeyboardView_keyBackground
- * @attr ref R.styleable#BaseKeyboardView_keyPreviewLayout
- * @attr ref R.styleable#BaseKeyboardView_keyPreviewOffset
- * @attr ref R.styleable#BaseKeyboardView_labelTextSize
- * @attr ref R.styleable#BaseKeyboardView_keyTextSize
- * @attr ref R.styleable#BaseKeyboardView_keyTextColor
- * @attr ref R.styleable#BaseKeyboardView_verticalCorrection
- * @attr ref R.styleable#BaseKeyboardView_popupLayout
- */
-public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
- private static final String TAG = "BaseKeyboardView";
- private static final boolean DEBUG = false;
- private static final boolean DEBUG_SHOW_ALIGN = false;
- private static final boolean DEBUG_KEYBOARD_GRID = false;
-
- public static final int COLOR_SCHEME_WHITE = 0;
- public static final int COLOR_SCHEME_BLACK = 1;
-
- public static final int NOT_A_TOUCH_COORDINATE = -1;
-
- public interface OnKeyboardActionListener {
-
- /**
- * Called when the user presses a key. This is sent before the
- * {@link #onKey} is called. For keys that repeat, this is only
- * called once.
- *
- * @param primaryCode
- * the unicode of the key being pressed. If the touch is
- * not on a valid key, the value will be zero.
- */
- void onPress(int primaryCode);
-
- /**
- * Called when the user releases a key. This is sent after the
- * {@link #onKey} is called. For keys that repeat, this is only
- * called once.
- *
- * @param primaryCode
- * the code of the key that was released
- */
- void onRelease(int primaryCode);
-
- /**
- * Send a key press to the listener.
- *
- * @param primaryCode
- * this is the key that was pressed
- * @param keyCodes
- * the codes for all the possible alternative keys with
- * the primary code being the first. If the primary key
- * code is a single character such as an alphabet or
- * number or symbol, the alternatives will include other
- * characters that may be on the same key or adjacent
- * keys. These codes are useful to correct for
- * accidental presses of a key adjacent to the intended
- * key.
- * @param x
- * x-coordinate pixel of touched event. If onKey is not called by onTouchEvent,
- * the value should be NOT_A_TOUCH_COORDINATE.
- * @param y
- * y-coordinate pixel of touched event. If onKey is not called by onTouchEvent,
- * the value should be NOT_A_TOUCH_COORDINATE.
- */
- void onKey(int primaryCode, int[] keyCodes, int x, int y);
-
- /**
- * Sends a sequence of characters to the listener.
- *
- * @param text
- * the sequence of characters to be displayed.
- */
- void onText(CharSequence text);
-
- /**
- * Called when user released a finger outside any key.
- */
- void onCancel();
-
- /**
- * Called when the user quickly moves the finger from right to
- * left.
- */
- void swipeLeft();
-
- /**
- * Called when the user quickly moves the finger from left to
- * right.
- */
- void swipeRight();
-
- /**
- * Called when the user quickly moves the finger from up to down.
- */
- void swipeDown();
-
- /**
- * Called when the user quickly moves the finger from down to up.
- */
- void swipeUp();
- }
-
- // Timing constants
- private final int mKeyRepeatInterval;
-
- // Miscellaneous constants
- /* package */ static final int NOT_A_KEY = -1;
- private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable };
- private static final int HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL = -1;
-
- // XML attribute
- private int mKeyLetterSize;
- private int mKeyTextColor;
- private int mKeyTextColorDisabled;
- private Typeface mKeyLetterStyle = Typeface.DEFAULT;
- private int mLabelTextSize;
- private int mColorScheme = COLOR_SCHEME_WHITE;
- private int mShadowColor;
- private float mShadowRadius;
- private Drawable mKeyBackground;
- private float mBackgroundDimAmount;
- private float mKeyHysteresisDistance;
- private float mVerticalCorrection;
- private int mPreviewOffset;
- private int mPreviewHeight;
- private int mPopupLayout;
-
- // Main keyboard
- private BaseKeyboard mKeyboard;
- private Key[] mKeys;
-
- // Key preview popup
- private boolean mInForeground;
- private TextView mPreviewText;
- private PopupWindow mPreviewPopup;
- private int mPreviewTextSizeLarge;
- private int[] mOffsetInWindow;
- private int mOldPreviewKeyIndex = NOT_A_KEY;
- private boolean mShowPreview = true;
- private boolean mShowTouchPoints = true;
- private int mPopupPreviewOffsetX;
- private int mPopupPreviewOffsetY;
- private int mWindowY;
- private int mPopupPreviewDisplayedY;
- private final int mDelayBeforePreview;
- private final int mDelayAfterPreview;
-
- // Popup mini keyboard
- private PopupWindow mMiniKeyboardPopup;
- private BaseKeyboardView mMiniKeyboard;
- private View mMiniKeyboardParent;
- private final WeakHashMap<Key, View> mMiniKeyboardCache = new WeakHashMap<Key, View>();
- private int mMiniKeyboardOriginX;
- private int mMiniKeyboardOriginY;
- private long mMiniKeyboardPopupTime;
- private int[] mWindowOffset;
- private final float mMiniKeyboardSlideAllowance;
- private int mMiniKeyboardTrackerId;
-
- /** Listener for {@link OnKeyboardActionListener}. */
- private OnKeyboardActionListener mKeyboardActionListener;
-
- private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
-
- // TODO: Let the PointerTracker class manage this pointer queue
- private final PointerQueue mPointerQueue = new PointerQueue();
-
- private final boolean mHasDistinctMultitouch;
- private int mOldPointerCount = 1;
-
- protected KeyDetector mKeyDetector = new ProximityKeyDetector();
-
- // Swipe gesture detector
- private GestureDetector mGestureDetector;
- private final SwipeTracker mSwipeTracker = new SwipeTracker();
- private final int mSwipeThreshold;
- private final boolean mDisambiguateSwipe;
-
- // Drawing
- /** Whether the keyboard bitmap needs to be redrawn before it's blitted. **/
- private boolean mDrawPending;
- /** The dirty region in the keyboard bitmap */
- private final Rect mDirtyRect = new Rect();
- /** The keyboard bitmap for faster updates */
- private Bitmap mBuffer;
- /** Notes if the keyboard just changed, so that we could possibly reallocate the mBuffer. */
- private boolean mKeyboardChanged;
- private Key mInvalidatedKey;
- /** The canvas for the above mutable keyboard bitmap */
- private Canvas mCanvas;
- private final Paint mPaint;
- private final Rect mPadding;
- private final Rect mClipRegion = new Rect(0, 0, 0, 0);
- // This map caches key label text height in pixel as value and key label text size as map key.
- private final HashMap<Integer, Integer> mTextHeightCache = new HashMap<Integer, Integer>();
- // Distance from horizontal center of the key, proportional to key label text height and width.
- private final float KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER = 0.55f;
- private final float KEY_LABEL_VERTICAL_PADDING_FACTOR = 1.60f;
- private final String KEY_LABEL_REFERENCE_CHAR = "H";
- private final int KEY_LABEL_OPTION_ALIGN_LEFT = 1;
- private final int KEY_LABEL_OPTION_ALIGN_RIGHT = 2;
- private final int KEY_LABEL_OPTION_ALIGN_BOTTOM = 8;
- private final int KEY_LABEL_OPTION_FONT_NORMAL = 16;
- private final int mKeyLabelHorizontalPadding;
-
- private final UIHandler mHandler = new UIHandler();
-
- class UIHandler extends Handler {
- private static final int MSG_POPUP_PREVIEW = 1;
- private static final int MSG_DISMISS_PREVIEW = 2;
- private static final int MSG_REPEAT_KEY = 3;
- private static final int MSG_LONGPRESS_KEY = 4;
- private static final int MSG_LONGPRESS_SHIFT_KEY = 5;
-
- private boolean mInKeyRepeat;
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_POPUP_PREVIEW:
- showKey(msg.arg1, (PointerTracker)msg.obj);
- break;
- case MSG_DISMISS_PREVIEW:
- mPreviewPopup.dismiss();
- break;
- case MSG_REPEAT_KEY: {
- final PointerTracker tracker = (PointerTracker)msg.obj;
- tracker.repeatKey(msg.arg1);
- startKeyRepeatTimer(mKeyRepeatInterval, msg.arg1, tracker);
- break;
- }
- case MSG_LONGPRESS_KEY: {
- final PointerTracker tracker = (PointerTracker)msg.obj;
- openPopupIfRequired(msg.arg1, tracker);
- break;
- }
- case MSG_LONGPRESS_SHIFT_KEY: {
- final PointerTracker tracker = (PointerTracker)msg.obj;
- onLongPressShiftKey(tracker);
- break;
- }
- }
- }
-
- public void popupPreview(long delay, int keyIndex, PointerTracker tracker) {
- removeMessages(MSG_POPUP_PREVIEW);
- if (mPreviewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) {
- // Show right away, if it's already visible and finger is moving around
- showKey(keyIndex, tracker);
- } else {
- sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, tracker),
- delay);
- }
- }
-
- public void cancelPopupPreview() {
- removeMessages(MSG_POPUP_PREVIEW);
- }
-
- public void dismissPreview(long delay) {
- if (mPreviewPopup.isShowing()) {
- sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay);
- }
- }
-
- public void cancelDismissPreview() {
- removeMessages(MSG_DISMISS_PREVIEW);
- }
-
- public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {
- mInKeyRepeat = true;
- sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, tracker), delay);
- }
-
- public void cancelKeyRepeatTimer() {
- mInKeyRepeat = false;
- removeMessages(MSG_REPEAT_KEY);
- }
-
- public boolean isInKeyRepeat() {
- return mInKeyRepeat;
- }
-
- public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {
- cancelLongPressTimers();
- sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay);
- }
-
- public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {
- cancelLongPressTimers();
- sendMessageDelayed(
- obtainMessage(MSG_LONGPRESS_SHIFT_KEY, keyIndex, 0, tracker), delay);
- }
-
- public void cancelLongPressTimers() {
- removeMessages(MSG_LONGPRESS_KEY);
- removeMessages(MSG_LONGPRESS_SHIFT_KEY);
- }
-
- public void cancelKeyTimers() {
- cancelKeyRepeatTimer();
- cancelLongPressTimers();
- }
-
- public void cancelAllMessages() {
- cancelKeyTimers();
- cancelPopupPreview();
- cancelDismissPreview();
- }
- };
-
- static class PointerQueue {
- private LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();
-
- public void add(PointerTracker tracker) {
- mQueue.add(tracker);
- }
-
- public int lastIndexOf(PointerTracker tracker) {
- LinkedList<PointerTracker> queue = mQueue;
- for (int index = queue.size() - 1; index >= 0; index--) {
- PointerTracker t = queue.get(index);
- if (t == tracker)
- return index;
- }
- return -1;
- }
-
- public void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) {
- LinkedList<PointerTracker> queue = mQueue;
- int oldestPos = 0;
- for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) {
- if (t.isModifier()) {
- oldestPos++;
- } else {
- t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
- t.setAlreadyProcessed();
- queue.remove(oldestPos);
- }
- }
- }
-
- public void releaseAllPointersExcept(PointerTracker tracker, long eventTime) {
- for (PointerTracker t : mQueue) {
- if (t == tracker)
- continue;
- t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
- t.setAlreadyProcessed();
- }
- mQueue.clear();
- if (tracker != null)
- mQueue.add(tracker);
- }
-
- public void remove(PointerTracker tracker) {
- mQueue.remove(tracker);
- }
- }
-
- public BaseKeyboardView(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.keyboardViewStyle);
- }
-
- public BaseKeyboardView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(
- attrs, R.styleable.BaseKeyboardView, defStyle, R.style.BaseKeyboardView);
- LayoutInflater inflate =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- int previewLayout = 0;
- int keyTextSize = 0;
-
- int n = a.getIndexCount();
-
- for (int i = 0; i < n; i++) {
- int attr = a.getIndex(i);
-
- switch (attr) {
- case R.styleable.BaseKeyboardView_keyBackground:
- mKeyBackground = a.getDrawable(attr);
- break;
- case R.styleable.BaseKeyboardView_keyHysteresisDistance:
- mKeyHysteresisDistance = a.getDimensionPixelOffset(attr, 0);
- break;
- case R.styleable.BaseKeyboardView_verticalCorrection:
- mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
- break;
- case R.styleable.BaseKeyboardView_keyPreviewLayout:
- previewLayout = a.getResourceId(attr, 0);
- break;
- case R.styleable.BaseKeyboardView_keyPreviewOffset:
- mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
- break;
- case R.styleable.BaseKeyboardView_keyPreviewHeight:
- mPreviewHeight = a.getDimensionPixelSize(attr, 80);
- break;
- case R.styleable.BaseKeyboardView_keyLetterSize:
- mKeyLetterSize = a.getDimensionPixelSize(attr, 18);
- break;
- case R.styleable.BaseKeyboardView_keyTextColor:
- mKeyTextColor = a.getColor(attr, 0xFF000000);
- break;
- case R.styleable.BaseKeyboardView_keyTextColorDisabled:
- mKeyTextColorDisabled = a.getColor(attr, 0xFF000000);
- break;
- case R.styleable.BaseKeyboardView_labelTextSize:
- mLabelTextSize = a.getDimensionPixelSize(attr, 14);
- break;
- case R.styleable.BaseKeyboardView_popupLayout:
- mPopupLayout = a.getResourceId(attr, 0);
- break;
- case R.styleable.BaseKeyboardView_shadowColor:
- mShadowColor = a.getColor(attr, 0);
- break;
- case R.styleable.BaseKeyboardView_shadowRadius:
- mShadowRadius = a.getFloat(attr, 0f);
- break;
- // TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount)
- case R.styleable.BaseKeyboardView_backgroundDimAmount:
- mBackgroundDimAmount = a.getFloat(attr, 0.5f);
- break;
- case R.styleable.BaseKeyboardView_keyLetterStyle:
- mKeyLetterStyle = Typeface.defaultFromStyle(a.getInt(attr, Typeface.NORMAL));
- break;
- case R.styleable.BaseKeyboardView_colorScheme:
- mColorScheme = a.getInt(attr, COLOR_SCHEME_WHITE);
- break;
- }
- }
-
- final Resources res = getResources();
-
- mPreviewPopup = new PopupWindow(context);
- if (previewLayout != 0) {
- mPreviewText = (TextView) inflate.inflate(previewLayout, null);
- mPreviewTextSizeLarge = (int) res.getDimension(R.dimen.key_preview_text_size_large);
- mPreviewPopup.setContentView(mPreviewText);
- mPreviewPopup.setBackgroundDrawable(null);
- } else {
- mShowPreview = false;
- }
- mPreviewPopup.setTouchable(false);
- mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation);
- mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview);
- mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview);
- mKeyLabelHorizontalPadding = (int)res.getDimension(
- R.dimen.key_label_horizontal_alignment_padding);
-
- mMiniKeyboardParent = this;
- mMiniKeyboardPopup = new PopupWindow(context);
- mMiniKeyboardPopup.setBackgroundDrawable(null);
- mMiniKeyboardPopup.setAnimationStyle(R.style.MiniKeyboardAnimation);
-
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setTextSize(keyTextSize);
- mPaint.setTextAlign(Align.CENTER);
- mPaint.setAlpha(255);
-
- mPadding = new Rect(0, 0, 0, 0);
- mKeyBackground.getPadding(mPadding);
-
- mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density);
- // TODO: Refer frameworks/base/core/res/res/values/config.xml
- mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation);
- mMiniKeyboardSlideAllowance = res.getDimension(R.dimen.mini_keyboard_slide_allowance);
-
- GestureDetector.SimpleOnGestureListener listener =
- new GestureDetector.SimpleOnGestureListener() {
- @Override
- public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX,
- float velocityY) {
- final float absX = Math.abs(velocityX);
- final float absY = Math.abs(velocityY);
- float deltaX = me2.getX() - me1.getX();
- float deltaY = me2.getY() - me1.getY();
- int travelX = getWidth() / 2; // Half the keyboard width
- int travelY = getHeight() / 2; // Half the keyboard height
- mSwipeTracker.computeCurrentVelocity(1000);
- final float endingVelocityX = mSwipeTracker.getXVelocity();
- final float endingVelocityY = mSwipeTracker.getYVelocity();
- if (velocityX > mSwipeThreshold && absY < absX && deltaX > travelX) {
- if (mDisambiguateSwipe && endingVelocityX >= velocityX / 4) {
- swipeRight();
- return true;
- }
- } else if (velocityX < -mSwipeThreshold && absY < absX && deltaX < -travelX) {
- if (mDisambiguateSwipe && endingVelocityX <= velocityX / 4) {
- swipeLeft();
- return true;
- }
- } else if (velocityY < -mSwipeThreshold && absX < absY && deltaY < -travelY) {
- if (mDisambiguateSwipe && endingVelocityY <= velocityY / 4) {
- swipeUp();
- return true;
- }
- } else if (velocityY > mSwipeThreshold && absX < absY / 2 && deltaY > travelY) {
- if (mDisambiguateSwipe && endingVelocityY >= velocityY / 4) {
- swipeDown();
- return true;
- }
- }
- return false;
- }
- };
-
- final boolean ignoreMultitouch = true;
- mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch);
- mGestureDetector.setIsLongpressEnabled(false);
-
- mHasDistinctMultitouch = context.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
- mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
- }
-
- public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
- mKeyboardActionListener = listener;
- for (PointerTracker tracker : mPointerTrackers) {
- tracker.setOnKeyboardActionListener(listener);
- }
- }
-
- /**
- * Returns the {@link OnKeyboardActionListener} object.
- * @return the listener attached to this keyboard
- */
- protected OnKeyboardActionListener getOnKeyboardActionListener() {
- return mKeyboardActionListener;
- }
-
- /**
- * Attaches a keyboard to this view. The keyboard can be switched at any time and the
- * view will re-layout itself to accommodate the keyboard.
- * @see BaseKeyboard
- * @see #getKeyboard()
- * @param keyboard the keyboard to display in this view
- */
- protected void setKeyboard(BaseKeyboard keyboard) {
- if (mKeyboard != null) {
- dismissKeyPreview();
- }
- // Remove any pending messages, except dismissing preview
- mHandler.cancelKeyTimers();
- mHandler.cancelPopupPreview();
- mKeyboard = keyboard;
- LatinImeLogger.onSetKeyboard(keyboard);
- mKeys = mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
- -getPaddingTop() + mVerticalCorrection);
- for (PointerTracker tracker : mPointerTrackers) {
- tracker.setKeyboard(keyboard, mKeys, mKeyHysteresisDistance);
- }
- requestLayout();
- // Hint to reallocate the buffer if the size changed
- mKeyboardChanged = true;
- invalidateAllKeys();
- computeProximityThreshold(keyboard, mKeys);
- mMiniKeyboardCache.clear();
- }
-
- /**
- * Returns the current keyboard being displayed by this view.
- * @return the currently attached keyboard
- * @see #setKeyboard(BaseKeyboard)
- */
- protected BaseKeyboard getKeyboard() {
- return mKeyboard;
- }
-
- /**
- * Return whether the device has distinct multi-touch panel.
- * @return true if the device has distinct multi-touch panel.
- */
- public boolean hasDistinctMultitouch() {
- return mHasDistinctMultitouch;
- }
-
- /**
- * Enables or disables the key feedback popup. This is a popup that shows a magnified
- * version of the depressed key. By default the preview is enabled.
- * @param previewEnabled whether or not to enable the key feedback popup
- * @see #isPreviewEnabled()
- */
- public void setPreviewEnabled(boolean previewEnabled) {
- mShowPreview = previewEnabled;
- }
-
- /**
- * Returns the enabled state of the key feedback popup.
- * @return whether or not the key feedback popup is enabled
- * @see #setPreviewEnabled(boolean)
- */
- public boolean isPreviewEnabled() {
- return mShowPreview;
- }
-
- public int getColorScheme() {
- return mColorScheme;
- }
-
- public void setPopupParent(View v) {
- mMiniKeyboardParent = v;
- }
-
- public void setPopupOffset(int x, int y) {
- mPopupPreviewOffsetX = x;
- mPopupPreviewOffsetY = y;
- mPreviewPopup.dismiss();
- }
-
- /**
- * When enabled, calls to {@link OnKeyboardActionListener#onKey} will include key
- * codes for adjacent keys. When disabled, only the primary key code will be
- * reported.
- * @param enabled whether or not the proximity correction is enabled
- */
- public void setProximityCorrectionEnabled(boolean enabled) {
- mKeyDetector.setProximityCorrectionEnabled(enabled);
- }
-
- /**
- * Returns true if proximity correction is enabled.
- */
- public boolean isProximityCorrectionEnabled() {
- return mKeyDetector.isProximityCorrectionEnabled();
- }
-
- protected CharSequence adjustCase(CharSequence label) {
- if (mKeyboard.isShiftedOrShiftLocked() && label != null && label.length() < 3
- && Character.isLowerCase(label.charAt(0))) {
- label = label.toString().toUpperCase();
- }
- return label;
- }
-
- @Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Round up a little
- if (mKeyboard == null) {
- setMeasuredDimension(
- getPaddingLeft() + getPaddingRight(), getPaddingTop() + getPaddingBottom());
- } else {
- int width = mKeyboard.getMinWidth() + getPaddingLeft() + getPaddingRight();
- if (MeasureSpec.getSize(widthMeasureSpec) < width + 10) {
- width = MeasureSpec.getSize(widthMeasureSpec);
- }
- setMeasuredDimension(
- width, mKeyboard.getHeight() + getPaddingTop() + getPaddingBottom());
- }
- }
-
- /**
- * Compute the most common key width and use it as proximity key detection threshold.
- * @param keyboard
- * @param keys
- */
- private void computeProximityThreshold(BaseKeyboard keyboard, Key[] keys) {
- if (keyboard == null || keys == null || keys.length == 0) return;
- final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
- int maxCount = 0;
- int mostCommonWidth = 0;
- for (Key key : keys) {
- final Integer width = key.width + key.gap;
- Integer count = histogram.get(width);
- if (count == null)
- count = 0;
- histogram.put(width, ++count);
- if (count > maxCount) {
- maxCount = count;
- mostCommonWidth = width;
- }
- }
- mKeyDetector.setProximityThreshold(mostCommonWidth);
- }
-
- @Override
- public void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- // Release the buffer, if any and it will be reallocated on the next draw
- mBuffer = null;
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mDrawPending || mBuffer == null || mKeyboardChanged) {
- onBufferDraw();
- }
- canvas.drawBitmap(mBuffer, 0, 0, null);
- }
-
- private void onBufferDraw() {
- if (mBuffer == null || mKeyboardChanged) {
- if (mBuffer == null || mKeyboardChanged &&
- (mBuffer.getWidth() != getWidth() || mBuffer.getHeight() != getHeight())) {
- // Make sure our bitmap is at least 1x1
- final int width = Math.max(1, getWidth());
- final int height = Math.max(1, getHeight());
- mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- mCanvas = new Canvas(mBuffer);
- }
- invalidateAllKeys();
- mKeyboardChanged = false;
- }
- final Canvas canvas = mCanvas;
- canvas.clipRect(mDirtyRect, Op.REPLACE);
-
- if (mKeyboard == null) return;
-
- final Paint paint = mPaint;
- final Drawable keyBackground = mKeyBackground;
- final Rect clipRegion = mClipRegion;
- final Rect padding = mPadding;
- final int kbdPaddingLeft = getPaddingLeft();
- final int kbdPaddingTop = getPaddingTop();
- final Key[] keys = mKeys;
- final Key invalidKey = mInvalidatedKey;
- final boolean isManualTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard
- && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase());
-
- boolean drawSingleKey = false;
- if (invalidKey != null && canvas.getClipBounds(clipRegion)) {
- // TODO we should use Rect.inset and Rect.contains here.
- // Is clipRegion completely contained within the invalidated key?
- if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left &&
- invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top &&
- invalidKey.x + invalidKey.width + kbdPaddingLeft + 1 >= clipRegion.right &&
- invalidKey.y + invalidKey.height + kbdPaddingTop + 1 >= clipRegion.bottom) {
- drawSingleKey = true;
- }
- }
- canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
- final int keyCount = keys.length;
- for (int i = 0; i < keyCount; i++) {
- final Key key = keys[i];
- if (drawSingleKey && invalidKey != key) {
- continue;
- }
- int[] drawableState = key.getCurrentDrawableState();
- keyBackground.setState(drawableState);
-
- // Switch the character to uppercase if shift is pressed
- String label = key.label == null? null : adjustCase(key.label).toString();
-
- final Rect bounds = keyBackground.getBounds();
- if (key.width != bounds.right || key.height != bounds.bottom) {
- keyBackground.setBounds(0, 0, key.width, key.height);
- }
- canvas.translate(key.x + kbdPaddingLeft, key.y + kbdPaddingTop);
- keyBackground.draw(canvas);
-
- final int rowHeight = padding.top + key.height;
- // Draw key label
- if (label != null) {
- // For characters, use large font. For labels like "Done", use small font.
- final int labelSize = getLabelSizeAndSetPaint(label, key, paint);
- final int labelCharHeight = getLabelCharHeight(labelSize, paint);
-
- // Vertical label text alignment.
- final float baseline;
- if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_BOTTOM) != 0) {
- baseline = key.height -
- + labelCharHeight * KEY_LABEL_VERTICAL_PADDING_FACTOR;
- if (DEBUG_SHOW_ALIGN)
- drawHorizontalLine(canvas, (int)baseline, key.width, 0xc0008000,
- new Paint());
- } else { // Align center
- final float centerY = (key.height + padding.top - padding.bottom) / 2;
- baseline = centerY
- + labelCharHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER;
- }
- // Horizontal label text alignment
- final int positionX;
- if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) {
- positionX = mKeyLabelHorizontalPadding + padding.left;
- paint.setTextAlign(Align.LEFT);
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, positionX, rowHeight, 0xc0800080, new Paint());
- } else if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_RIGHT) != 0) {
- positionX = key.width - mKeyLabelHorizontalPadding - padding.right;
- paint.setTextAlign(Align.RIGHT);
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, positionX, rowHeight, 0xc0808000, new Paint());
- } else {
- positionX = (key.width + padding.left - padding.right) / 2;
- paint.setTextAlign(Align.CENTER);
- if (DEBUG_SHOW_ALIGN && label.length() > 1)
- drawVerticalLine(canvas, positionX, rowHeight, 0xc0008080, new Paint());
- }
- if (key.manualTemporaryUpperCaseHintIcon != null && isManualTemporaryUpperCase) {
- paint.setColor(mKeyTextColorDisabled);
- } else {
- paint.setColor(mKeyTextColor);
- }
- // Set a drop shadow for the text
- paint.setShadowLayer(mShadowRadius, 0, 0, mShadowColor);
- canvas.drawText(label, positionX, baseline, paint);
- // Turn off drop shadow
- paint.setShadowLayer(0, 0, 0, 0);
- }
- // Draw key icon
- if (key.label == null && key.icon != null) {
- final int drawableWidth = key.icon.getIntrinsicWidth();
- final int drawableHeight = key.icon.getIntrinsicHeight();
- final int drawableX;
- final int drawableY = (
- key.height + padding.top - padding.bottom - drawableHeight) / 2;
- if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) {
- drawableX = padding.left + mKeyLabelHorizontalPadding;
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, drawableX, rowHeight, 0xc0800080, new Paint());
- } else if ((key.labelOption & KEY_LABEL_OPTION_ALIGN_RIGHT) != 0) {
- drawableX = key.width - padding.right - mKeyLabelHorizontalPadding
- - drawableWidth;
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, drawableX + drawableWidth, rowHeight,
- 0xc0808000, new Paint());
- } else { // Align center
- drawableX = (key.width + padding.left - padding.right - drawableWidth) / 2;
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, drawableX + drawableWidth / 2, rowHeight,
- 0xc0008080, new Paint());
- }
- drawIcon(canvas, key.icon, drawableX, drawableY, drawableWidth, drawableHeight);
- if (DEBUG_SHOW_ALIGN)
- drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
- 0x80c00000, new Paint());
- }
- if (key.hintIcon != null) {
- final int drawableWidth = key.width;
- final int drawableHeight = key.height;
- final int drawableX = 0;
- final int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL;
- Drawable icon = (isManualTemporaryUpperCase
- && key.manualTemporaryUpperCaseHintIcon != null)
- ? key.manualTemporaryUpperCaseHintIcon : key.hintIcon;
- drawIcon(canvas, icon, drawableX, drawableY, drawableWidth, drawableHeight);
- if (DEBUG_SHOW_ALIGN)
- drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
- 0x80c0c000, new Paint());
- }
- canvas.translate(-key.x - kbdPaddingLeft, -key.y - kbdPaddingTop);
- }
-
- if (DEBUG_KEYBOARD_GRID) {
- Paint p = new Paint();
- p.setStyle(Paint.Style.STROKE);
- p.setStrokeWidth(1.0f);
- p.setColor(0x800000c0);
- int cw = (mKeyboard.getMinWidth() + mKeyboard.GRID_WIDTH - 1) / mKeyboard.GRID_WIDTH;
- int ch = (mKeyboard.getHeight() + mKeyboard.GRID_HEIGHT - 1) / mKeyboard.GRID_HEIGHT;
- for (int i = 0; i <= mKeyboard.GRID_WIDTH; i++)
- canvas.drawLine(i * cw, 0, i * cw, ch * mKeyboard.GRID_HEIGHT, p);
- for (int i = 0; i <= mKeyboard.GRID_HEIGHT; i++)
- canvas.drawLine(0, i * ch, cw * mKeyboard.GRID_WIDTH, i * ch, p);
- }
-
- mInvalidatedKey = null;
- // Overlay a dark rectangle to dim the keyboard
- if (mMiniKeyboard != null) {
- paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
- canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
- }
-
- if (DEBUG) {
- if (mShowTouchPoints) {
- for (PointerTracker tracker : mPointerTrackers) {
- int startX = tracker.getStartX();
- int startY = tracker.getStartY();
- int lastX = tracker.getLastX();
- int lastY = tracker.getLastY();
- paint.setAlpha(128);
- paint.setColor(0xFFFF0000);
- canvas.drawCircle(startX, startY, 3, paint);
- canvas.drawLine(startX, startY, lastX, lastY, paint);
- paint.setColor(0xFF0000FF);
- canvas.drawCircle(lastX, lastY, 3, paint);
- paint.setColor(0xFF00FF00);
- canvas.drawCircle((startX + lastX) / 2, (startY + lastY) / 2, 2, paint);
- }
- }
- }
-
- mDrawPending = false;
- mDirtyRect.setEmpty();
- }
-
- private int getLabelSizeAndSetPaint(CharSequence label, Key key, Paint paint) {
- // For characters, use large font. For labels like "Done", use small font.
- final int labelSize;
- final Typeface labelStyle;
- if (label.length() > 1 && key.codes.length < 2) {
- labelSize = mLabelTextSize;
- if ((key.labelOption & KEY_LABEL_OPTION_FONT_NORMAL) != 0) {
- labelStyle = Typeface.DEFAULT;
- } else {
- labelStyle = Typeface.DEFAULT_BOLD;
- }
- } else {
- labelSize = mKeyLetterSize;
- labelStyle = mKeyLetterStyle;
- }
- paint.setTextSize(labelSize);
- paint.setTypeface(labelStyle);
- return labelSize;
- }
-
- private int getLabelCharHeight(int labelSize, Paint paint) {
- Integer labelHeightValue = mTextHeightCache.get(labelSize);
- final int labelCharHeight;
- if (labelHeightValue != null) {
- labelCharHeight = labelHeightValue;
- } else {
- Rect textBounds = new Rect();
- paint.getTextBounds(KEY_LABEL_REFERENCE_CHAR, 0, 1, textBounds);
- labelCharHeight = textBounds.height();
- mTextHeightCache.put(labelSize, labelCharHeight);
- }
- return labelCharHeight;
- }
-
- private static void drawIcon(Canvas canvas, Drawable icon, int x, int y, int width,
- int height) {
- canvas.translate(x, y);
- icon.setBounds(0, 0, width, height);
- icon.draw(canvas);
- canvas.translate(-x, -y);
- }
-
- private static void drawHorizontalLine(Canvas canvas, int y, int w, int color, Paint paint) {
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(1.0f);
- paint.setColor(color);
- canvas.drawLine(0, y, w, y, paint);
- }
-
- private static void drawVerticalLine(Canvas canvas, int x, int h, int color, Paint paint) {
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(1.0f);
- paint.setColor(color);
- canvas.drawLine(x, 0, x, h, paint);
- }
-
- private static void drawRectangle(Canvas canvas, int x, int y, int w, int h, int color,
- Paint paint) {
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(1.0f);
- paint.setColor(color);
- canvas.translate(x, y);
- canvas.drawRect(0, 0, w, h, paint);
- canvas.translate(-x, -y);
- }
-
- public void setForeground(boolean foreground) {
- mInForeground = foreground;
- }
-
- // TODO: clean up this method.
- private void dismissKeyPreview() {
- for (PointerTracker tracker : mPointerTrackers)
- tracker.releaseKey();
- showPreview(NOT_A_KEY, null);
- }
-
- public void showPreview(int keyIndex, PointerTracker tracker) {
- int oldKeyIndex = mOldPreviewKeyIndex;
- mOldPreviewKeyIndex = keyIndex;
- // We should re-draw popup preview when 1) we need to hide the preview, 2) we will show
- // the space key preview and 3) pointer moves off the space key to other letter key, we
- // should hide the preview of the previous key.
- final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
- || (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
- && SubtypeSwitcher.getInstance().needsToDisplayLanguage()
- && (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex)));
- // If key changed and preview is on or the key is space (language switch is enabled)
- if (oldKeyIndex != keyIndex && (mShowPreview || (hidePreviewOrShowSpaceKeyPreview))) {
- if (keyIndex == NOT_A_KEY) {
- mHandler.cancelPopupPreview();
- mHandler.dismissPreview(mDelayAfterPreview);
- } else if (tracker != null) {
- mHandler.popupPreview(mDelayBeforePreview, keyIndex, tracker);
- }
- }
- }
-
- // TODO Must fix popup preview on xlarge layout
- private void showKey(final int keyIndex, PointerTracker tracker) {
- Key key = tracker.getKey(keyIndex);
- // If keyIndex is invalid or IME is already closed, we must not show key preview.
- // Trying to show preview PopupWindow while root window is closed causes
- // WindowManager.BadTokenException.
- if (key == null || !mInForeground)
- return;
- // What we show as preview should match what we show on key top in onBufferDraw().
- if (key.label != null) {
- // TODO Should take care of temporaryShiftLabel here.
- mPreviewText.setCompoundDrawables(null, null, null, null);
- mPreviewText.setText(adjustCase(tracker.getPreviewText(key)));
- if (key.label.length() > 1 && key.codes.length < 2) {
- mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyLetterSize);
- mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
- } else {
- mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSizeLarge);
- mPreviewText.setTypeface(mKeyLetterStyle);
- }
- } else {
- mPreviewText.setCompoundDrawables(null, null, null,
- key.iconPreview != null ? key.iconPreview : key.icon);
- mPreviewText.setText(null);
- }
- mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width
- + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
- final int popupHeight = mPreviewHeight;
- LayoutParams lp = mPreviewText.getLayoutParams();
- if (lp != null) {
- lp.width = popupWidth;
- lp.height = popupHeight;
- }
-
- int popupPreviewX = key.x - (popupWidth - key.width) / 2;
- int popupPreviewY = key.y - popupHeight + mPreviewOffset;
-
- mHandler.cancelDismissPreview();
- if (mOffsetInWindow == null) {
- mOffsetInWindow = new int[2];
- getLocationInWindow(mOffsetInWindow);
- mOffsetInWindow[0] += mPopupPreviewOffsetX; // Offset may be zero
- mOffsetInWindow[1] += mPopupPreviewOffsetY; // Offset may be zero
- int[] windowLocation = new int[2];
- getLocationOnScreen(windowLocation);
- mWindowY = windowLocation[1];
- }
- // Set the preview background state
- mPreviewText.getBackground().setState(
- key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
- popupPreviewX += mOffsetInWindow[0];
- popupPreviewY += mOffsetInWindow[1];
-
- // If the popup cannot be shown above the key, put it on the side
- if (popupPreviewY + mWindowY < 0) {
- // If the key you're pressing is on the left side of the keyboard, show the popup on
- // the right, offset by enough to see at least one key to the left/right.
- if (key.x + key.width <= getWidth() / 2) {
- popupPreviewX += (int) (key.width * 2.5);
- } else {
- popupPreviewX -= (int) (key.width * 2.5);
- }
- popupPreviewY += popupHeight;
- }
-
- try {
- if (mPreviewPopup.isShowing()) {
- mPreviewPopup.update(popupPreviewX, popupPreviewY, popupWidth, popupHeight);
- } else {
- mPreviewPopup.setWidth(popupWidth);
- mPreviewPopup.setHeight(popupHeight);
- mPreviewPopup.showAtLocation(mMiniKeyboardParent, Gravity.NO_GRAVITY,
- popupPreviewX, popupPreviewY);
- }
- } catch (WindowManager.BadTokenException e) {
- // Swallow the exception which will be happened when IME is already closed.
- Log.w(TAG, "LatinIME is already closed when tried showing key preview.");
- }
- // Record popup preview position to display mini-keyboard later at the same positon
- mPopupPreviewDisplayedY = popupPreviewY;
- mPreviewText.setVisibility(VISIBLE);
- }
-
- /**
- * Requests a redraw of the entire keyboard. Calling {@link #invalidate} is not sufficient
- * because the keyboard renders the keys to an off-screen buffer and an invalidate() only
- * draws the cached buffer.
- * @see #invalidateKey(Key)
- */
- public void invalidateAllKeys() {
- mDirtyRect.union(0, 0, getWidth(), getHeight());
- mDrawPending = true;
- invalidate();
- }
-
- /**
- * Invalidates a key so that it will be redrawn on the next repaint. Use this method if only
- * one key is changing it's content. Any changes that affect the position or size of the key
- * may not be honored.
- * @param key key in the attached {@link BaseKeyboard}.
- * @see #invalidateAllKeys
- */
- public void invalidateKey(Key key) {
- if (key == null)
- return;
- mInvalidatedKey = key;
- // TODO we should clean up this and record key's region to use in onBufferDraw.
- mDirtyRect.union(key.x + getPaddingLeft(), key.y + getPaddingTop(),
- key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop());
- onBufferDraw();
- invalidate(key.x + getPaddingLeft(), key.y + getPaddingTop(),
- key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop());
- }
-
- private boolean openPopupIfRequired(int keyIndex, PointerTracker tracker) {
- // Check if we have a popup layout specified first.
- if (mPopupLayout == 0) {
- return false;
- }
-
- Key popupKey = tracker.getKey(keyIndex);
- if (popupKey == null)
- return false;
- boolean result = onLongPress(popupKey);
- if (result) {
- dismissKeyPreview();
- mMiniKeyboardTrackerId = tracker.mPointerId;
- // Mark this tracker "already processed" and remove it from the pointer queue
- tracker.setAlreadyProcessed();
- mPointerQueue.remove(tracker);
- }
- return result;
- }
-
- private void onLongPressShiftKey(PointerTracker tracker) {
- tracker.setAlreadyProcessed();
- mPointerQueue.remove(tracker);
- mKeyboardActionListener.onKey(LatinKeyboardView.KEYCODE_CAPSLOCK, null, 0, 0);
- }
-
- private View inflateMiniKeyboardContainer(Key popupKey) {
- int popupKeyboardId = popupKey.popupResId;
- LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- View container = inflater.inflate(mPopupLayout, null);
- if (container == null)
- throw new NullPointerException();
-
- BaseKeyboardView miniKeyboard =
- (BaseKeyboardView)container.findViewById(R.id.BaseKeyboardView);
- miniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() {
- public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
- mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y);
- dismissPopupKeyboard();
- }
-
- public void onText(CharSequence text) {
- mKeyboardActionListener.onText(text);
- dismissPopupKeyboard();
- }
-
- public void onCancel() {
- dismissPopupKeyboard();
- }
-
- public void swipeLeft() {
- }
- public void swipeRight() {
- }
- public void swipeUp() {
- }
- public void swipeDown() {
- }
- public void onPress(int primaryCode) {
- mKeyboardActionListener.onPress(primaryCode);
- }
- public void onRelease(int primaryCode) {
- mKeyboardActionListener.onRelease(primaryCode);
- }
- });
- // Override default ProximityKeyDetector.
- miniKeyboard.mKeyDetector = new MiniKeyboardKeyDetector(mMiniKeyboardSlideAllowance);
- // Remove gesture detector on mini-keyboard
- miniKeyboard.mGestureDetector = null;
-
- BaseKeyboard keyboard;
- if (popupKey.popupCharacters != null) {
- keyboard = new BaseKeyboard(getContext(), popupKeyboardId, popupKey.popupCharacters,
- -1, getPaddingLeft() + getPaddingRight());
- } else {
- keyboard = new BaseKeyboard(getContext(), popupKeyboardId);
- }
- miniKeyboard.setKeyboard(keyboard);
- miniKeyboard.setPopupParent(this);
-
- container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
-
- return container;
- }
-
- private static boolean isOneRowKeys(List<Key> keys) {
- if (keys.size() == 0) return false;
- final int edgeFlags = keys.get(0).edgeFlags;
- // HACK: The first key of mini keyboard which was inflated from xml and has multiple rows,
- // does not have both top and bottom edge flags on at the same time. On the other hand,
- // the first key of mini keyboard that was created with popupCharacters must have both top
- // and bottom edge flags on.
- // When you want to use one row mini-keyboard from xml file, make sure that the row has
- // both top and bottom edge flags set.
- return (edgeFlags & BaseKeyboard.EDGE_TOP) != 0
- && (edgeFlags & BaseKeyboard.EDGE_BOTTOM) != 0;
- }
-
- /**
- * Called when a key is long pressed. By default this will open any popup keyboard associated
- * with this key through the attributes popupLayout and popupCharacters.
- * @param popupKey the key that was long pressed
- * @return true if the long press is handled, false otherwise. Subclasses should call the
- * method on the base class if the subclass doesn't wish to handle the call.
- */
- protected boolean onLongPress(Key popupKey) {
- // TODO if popupKey.popupCharacters has only one letter, send it as key without opening
- // mini keyboard.
-
- if (popupKey.popupResId == 0)
- return false;
-
- View container = mMiniKeyboardCache.get(popupKey);
- if (container == null) {
- container = inflateMiniKeyboardContainer(popupKey);
- mMiniKeyboardCache.put(popupKey, container);
- }
- mMiniKeyboard = (BaseKeyboardView)container.findViewById(R.id.BaseKeyboardView);
- if (mWindowOffset == null) {
- mWindowOffset = new int[2];
- getLocationInWindow(mWindowOffset);
- }
-
- // Get width of a key in the mini popup keyboard = "miniKeyWidth".
- // On the other hand, "popupKey.width" is width of the pressed key on the main keyboard.
- // We adjust the position of mini popup keyboard with the edge key in it:
- // a) When we have the leftmost key in popup keyboard directly above the pressed key
- // Right edges of both keys should be aligned for consistent default selection
- // b) When we have the rightmost key in popup keyboard directly above the pressed key
- // Left edges of both keys should be aligned for consistent default selection
- final List<Key> miniKeys = mMiniKeyboard.getKeyboard().getKeys();
- final int miniKeyWidth = miniKeys.size() > 0 ? miniKeys.get(0).width : 0;
-
- // HACK: Have the leftmost number in the popup characters right above the key
- boolean isNumberAtLeftmost =
- hasMultiplePopupChars(popupKey) && isNumberAtLeftmostPopupChar(popupKey);
- int popupX = popupKey.x + mWindowOffset[0];
- popupX += getPaddingLeft();
- if (isNumberAtLeftmost) {
- popupX += popupKey.width - miniKeyWidth; // adjustment for a) described above
- popupX -= container.getPaddingLeft();
- } else {
- popupX += miniKeyWidth; // adjustment for b) described above
- popupX -= container.getMeasuredWidth();
- popupX += container.getPaddingRight();
- }
- int popupY = popupKey.y + mWindowOffset[1];
- popupY += getPaddingTop();
- popupY -= container.getMeasuredHeight();
- popupY += container.getPaddingBottom();
- final int x = popupX;
- final int y = mShowPreview && isOneRowKeys(miniKeys) ? mPopupPreviewDisplayedY : popupY;
-
- int adjustedX = x;
- if (x < 0) {
- adjustedX = 0;
- } else if (x > (getMeasuredWidth() - container.getMeasuredWidth())) {
- adjustedX = getMeasuredWidth() - container.getMeasuredWidth();
- }
- mMiniKeyboardOriginX = adjustedX + container.getPaddingLeft() - mWindowOffset[0];
- mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1];
- mMiniKeyboard.setPopupOffset(adjustedX, y);
- // TODO: change the below line to use getLatinKeyboard() instead of getKeyboard()
- BaseKeyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard();
- if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null
- ? false : mKeyboard.isShiftedOrShiftLocked())) {
- mMiniKeyboard.invalidateAllKeys();
- }
- // Mini keyboard needs no pop-up key preview displayed.
- mMiniKeyboard.setPreviewEnabled(false);
- mMiniKeyboardPopup.setContentView(container);
- mMiniKeyboardPopup.setWidth(container.getMeasuredWidth());
- mMiniKeyboardPopup.setHeight(container.getMeasuredHeight());
- mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
-
- // Inject down event on the key to mini keyboard.
- long eventTime = SystemClock.uptimeMillis();
- mMiniKeyboardPopupTime = eventTime;
- MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, popupKey.x
- + popupKey.width / 2, popupKey.y + popupKey.height / 2, eventTime);
- mMiniKeyboard.onTouchEvent(downEvent);
- downEvent.recycle();
-
- invalidateAllKeys();
- return true;
- }
-
- private static boolean hasMultiplePopupChars(Key key) {
- if (key.popupCharacters != null && key.popupCharacters.length() > 1) {
- return true;
- }
- return false;
- }
-
- private static boolean isNumberAtLeftmostPopupChar(Key key) {
- if (key.popupCharacters != null && key.popupCharacters.length() > 0
- && isAsciiDigit(key.popupCharacters.charAt(0))) {
- return true;
- }
- return false;
- }
-
- private static boolean isAsciiDigit(char c) {
- return (c < 0x80) && Character.isDigit(c);
- }
-
- private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) {
- return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action,
- x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0);
- }
-
- private PointerTracker getPointerTracker(final int id) {
- final ArrayList<PointerTracker> pointers = mPointerTrackers;
- final Key[] keys = mKeys;
- final OnKeyboardActionListener listener = mKeyboardActionListener;
-
- // Create pointer trackers until we can get 'id+1'-th tracker, if needed.
- for (int i = pointers.size(); i <= id; i++) {
- final PointerTracker tracker =
- new PointerTracker(i, mHandler, mKeyDetector, this, getResources());
- if (keys != null)
- tracker.setKeyboard(mKeyboard, keys, mKeyHysteresisDistance);
- if (listener != null)
- tracker.setOnKeyboardActionListener(listener);
- pointers.add(tracker);
- }
-
- return pointers.get(id);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- final int pointerCount = me.getPointerCount();
- final int action = me.getActionMasked();
-
- // TODO: cleanup this code into a multi-touch to single-touch event converter class?
- // If the device does not have distinct multi-touch support panel, ignore all multi-touch
- // events except a transition from/to single-touch.
- if (!mHasDistinctMultitouch && pointerCount > 1 && mOldPointerCount > 1) {
- return true;
- }
-
- // Track the last few movements to look for spurious swipes.
- mSwipeTracker.addMovement(me);
-
- // Gesture detector must be enabled only when mini-keyboard is not on the screen.
- if (mMiniKeyboard == null
- && mGestureDetector != null && mGestureDetector.onTouchEvent(me)) {
- dismissKeyPreview();
- mHandler.cancelKeyTimers();
- return true;
- }
-
- final long eventTime = me.getEventTime();
- final int index = me.getActionIndex();
- final int id = me.getPointerId(index);
- final int x = (int)me.getX(index);
- final int y = (int)me.getY(index);
-
- // Needs to be called after the gesture detector gets a turn, as it may have
- // displayed the mini keyboard
- if (mMiniKeyboard != null) {
- final int miniKeyboardPointerIndex = me.findPointerIndex(mMiniKeyboardTrackerId);
- if (miniKeyboardPointerIndex >= 0 && miniKeyboardPointerIndex < pointerCount) {
- final int miniKeyboardX = (int)me.getX(miniKeyboardPointerIndex);
- final int miniKeyboardY = (int)me.getY(miniKeyboardPointerIndex);
- MotionEvent translated = generateMiniKeyboardMotionEvent(action,
- miniKeyboardX, miniKeyboardY, eventTime);
- mMiniKeyboard.onTouchEvent(translated);
- translated.recycle();
- }
- return true;
- }
-
- if (mHandler.isInKeyRepeat()) {
- // It will keep being in the key repeating mode while the key is being pressed.
- if (action == MotionEvent.ACTION_MOVE) {
- return true;
- }
- final PointerTracker tracker = getPointerTracker(id);
- // Key repeating timer will be canceled if 2 or more keys are in action, and current
- // event (UP or DOWN) is non-modifier key.
- if (pointerCount > 1 && !tracker.isModifier()) {
- mHandler.cancelKeyRepeatTimer();
- }
- // Up event will pass through.
- }
-
- // TODO: cleanup this code into a multi-touch to single-touch event converter class?
- // Translate mutli-touch event to single-touch events on the device that has no distinct
- // multi-touch panel.
- if (!mHasDistinctMultitouch) {
- // Use only main (id=0) pointer tracker.
- PointerTracker tracker = getPointerTracker(0);
- int oldPointerCount = mOldPointerCount;
- if (pointerCount == 1 && oldPointerCount == 2) {
- // Multi-touch to single touch transition.
- // Send a down event for the latest pointer.
- tracker.onDownEvent(x, y, eventTime);
- } else if (pointerCount == 2 && oldPointerCount == 1) {
- // Single-touch to multi-touch transition.
- // Send an up event for the last pointer.
- tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime);
- } else if (pointerCount == 1 && oldPointerCount == 1) {
- tracker.onTouchEvent(action, x, y, eventTime);
- } else {
- Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
- + " (old " + oldPointerCount + ")");
- }
- mOldPointerCount = pointerCount;
- return true;
- }
-
- if (action == MotionEvent.ACTION_MOVE) {
- for (int i = 0; i < pointerCount; i++) {
- PointerTracker tracker = getPointerTracker(me.getPointerId(i));
- tracker.onMoveEvent((int)me.getX(i), (int)me.getY(i), eventTime);
- }
- } else {
- PointerTracker tracker = getPointerTracker(id);
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- onDownEvent(tracker, x, y, eventTime);
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- onUpEvent(tracker, x, y, eventTime);
- break;
- case MotionEvent.ACTION_CANCEL:
- onCancelEvent(tracker, x, y, eventTime);
- break;
- }
- }
-
- return true;
- }
-
- private void onDownEvent(PointerTracker tracker, int x, int y, long eventTime) {
- if (tracker.isOnModifierKey(x, y)) {
- // Before processing a down event of modifier key, all pointers already being tracked
- // should be released.
- mPointerQueue.releaseAllPointersExcept(null, eventTime);
- }
- tracker.onDownEvent(x, y, eventTime);
- mPointerQueue.add(tracker);
- }
-
- private void onUpEvent(PointerTracker tracker, int x, int y, long eventTime) {
- if (tracker.isModifier()) {
- // Before processing an up event of modifier key, all pointers already being tracked
- // should be released.
- mPointerQueue.releaseAllPointersExcept(tracker, eventTime);
- } else {
- int index = mPointerQueue.lastIndexOf(tracker);
- if (index >= 0) {
- mPointerQueue.releaseAllPointersOlderThan(tracker, eventTime);
- } else {
- Log.w(TAG, "onUpEvent: corresponding down event not found for pointer "
- + tracker.mPointerId);
- }
- }
- tracker.onUpEvent(x, y, eventTime);
- mPointerQueue.remove(tracker);
- }
-
- private void onCancelEvent(PointerTracker tracker, int x, int y, long eventTime) {
- tracker.onCancelEvent(x, y, eventTime);
- mPointerQueue.remove(tracker);
- }
-
- protected void swipeRight() {
- mKeyboardActionListener.swipeRight();
- }
-
- protected void swipeLeft() {
- mKeyboardActionListener.swipeLeft();
- }
-
- protected void swipeUp() {
- mKeyboardActionListener.swipeUp();
- }
-
- protected void swipeDown() {
- mKeyboardActionListener.swipeDown();
- }
-
- public void closing() {
- mPreviewPopup.dismiss();
- mHandler.cancelAllMessages();
-
- dismissPopupKeyboard();
- mBuffer = null;
- mCanvas = null;
- mMiniKeyboardCache.clear();
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- closing();
- }
-
- private void dismissPopupKeyboard() {
- if (mMiniKeyboardPopup.isShowing()) {
- mMiniKeyboardPopup.dismiss();
- mMiniKeyboard = null;
- mMiniKeyboardOriginX = 0;
- mMiniKeyboardOriginY = 0;
- invalidateAllKeys();
- }
- }
-
- public boolean handleBack() {
- if (mMiniKeyboardPopup.isShowing()) {
- dismissPopupKeyboard();
- return true;
- }
- return false;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java
index fc517aeb7..ad3f1db9b 100644
--- a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java
+++ b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java
@@ -57,6 +57,7 @@ public class InputLanguageSelection extends PreferenceActivity {
return this.label;
}
+ @Override
public int compareTo(Object o) {
return sCollator.compare(this.label, ((Loc) o).label);
}
diff --git a/java/src/com/android/inputmethod/latin/KeyDetector.java b/java/src/com/android/inputmethod/latin/KeyDetector.java
deleted file mode 100644
index 600a12fe5..000000000
--- a/java/src/com/android/inputmethod/latin/KeyDetector.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboard.Key;
-
-import java.util.Arrays;
-import java.util.List;
-
-abstract class KeyDetector {
- protected BaseKeyboard mKeyboard;
-
- private Key[] mKeys;
-
- protected int mCorrectionX;
-
- protected int mCorrectionY;
-
- protected boolean mProximityCorrectOn;
-
- protected int mProximityThresholdSquare;
-
- public Key[] setKeyboard(BaseKeyboard keyboard, float correctionX, float correctionY) {
- if (keyboard == null)
- throw new NullPointerException();
- mCorrectionX = (int)correctionX;
- mCorrectionY = (int)correctionY;
- mKeyboard = keyboard;
- List<Key> keys = mKeyboard.getKeys();
- Key[] array = keys.toArray(new Key[keys.size()]);
- mKeys = array;
- return array;
- }
-
- protected int getTouchX(int x) {
- return x + mCorrectionX;
- }
-
- protected int getTouchY(int y) {
- return y + mCorrectionY;
- }
-
- protected Key[] getKeys() {
- if (mKeys == null)
- throw new IllegalStateException("keyboard isn't set");
- // mKeyboard is guaranteed not to be null at setKeybaord() method if mKeys is not null
- return mKeys;
- }
-
- public void setProximityCorrectionEnabled(boolean enabled) {
- mProximityCorrectOn = enabled;
- }
-
- public boolean isProximityCorrectionEnabled() {
- return mProximityCorrectOn;
- }
-
- public void setProximityThreshold(int threshold) {
- mProximityThresholdSquare = threshold * threshold;
- }
-
- /**
- * Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes}
- * method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}.
- *
- * @return Allocates and returns an array that can hold all key indices returned by
- * {@link #getKeyIndexAndNearbyCodes} method. All elements in the returned array are
- * initialized by {@link com.android.inputmethod.latin.LatinKeyboardView.NOT_A_KEY}
- * value.
- */
- public int[] newCodeArray() {
- int[] codes = new int[getMaxNearbyKeys()];
- Arrays.fill(codes, BaseKeyboardView.NOT_A_KEY);
- return codes;
- }
-
- /**
- * Computes maximum size of the array that can contain all nearby key indices returned by
- * {@link #getKeyIndexAndNearbyCodes}.
- *
- * @return Returns maximum size of the array that can contain all nearby key indices returned
- * by {@link #getKeyIndexAndNearbyCodes}.
- */
- abstract protected int getMaxNearbyKeys();
-
- /**
- * Finds all possible nearby key indices around a touch event point and returns the nearest key
- * index. The algorithm to determine the nearby keys depends on the threshold set by
- * {@link #setProximityThreshold(int)} and the mode set by
- * {@link #setProximityCorrectionEnabled(boolean)}.
- *
- * @param x The x-coordinate of a touch point
- * @param y The y-coordinate of a touch point
- * @param allKeys All nearby key indices are returned in this array
- * @return The nearest key index
- */
- abstract public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys);
-}
diff --git a/java/src/com/android/inputmethod/latin/KeyStyles.java b/java/src/com/android/inputmethod/latin/KeyStyles.java
deleted file mode 100644
index fceede7c3..000000000
--- a/java/src/com/android/inputmethod/latin/KeyStyles.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboardParser.ParseException;
-
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-import android.util.TypedValue;
-
-import java.util.HashMap;
-import java.util.StringTokenizer;
-
-public class KeyStyles {
- private static final String TAG = "KeyStyles";
-
- private final HashMap<String, DeclaredKeyStyle> mStyles =
- new HashMap<String, DeclaredKeyStyle>();
- private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle();
-
- public interface KeyStyle {
- public int[] getIntArray(TypedArray a, int index);
- public Drawable getDrawable(TypedArray a, int index);
- public CharSequence getText(TypedArray a, int index);
- public int getResourceId(TypedArray a, int index, int defaultValue);
- public int getInt(TypedArray a, int index, int defaultValue);
- public int getFlag(TypedArray a, int index, int defaultValue);
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue);
- }
-
- public static class EmptyKeyStyle implements KeyStyle {
- private EmptyKeyStyle() {
- }
-
- public int[] getIntArray(TypedArray a, int index) {
- return parseIntArray(a, index);
- }
-
- public Drawable getDrawable(TypedArray a, int index) {
- return a.getDrawable(index);
- }
-
- public CharSequence getText(TypedArray a, int index) {
- return a.getText(index);
- }
-
- public int getResourceId(TypedArray a, int index, int defaultValue) {
- return a.getResourceId(index, defaultValue);
- }
-
- public int getInt(TypedArray a, int index, int defaultValue) {
- return a.getInt(index, defaultValue);
- }
-
- public int getFlag(TypedArray a, int index, int defaultValue) {
- return a.getInt(index, defaultValue);
- }
-
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
- return a.getBoolean(index, defaultValue);
- }
-
- protected static int[] parseIntArray(TypedArray a, int index) {
- TypedValue v = new TypedValue();
- a.getValue(index, v);
- if (v.type == TypedValue.TYPE_INT_DEC || v.type == TypedValue.TYPE_INT_HEX) {
- return new int[] { v.data };
- } else if (v.type == TypedValue.TYPE_STRING) {
- return parseCSV(v.string.toString());
- } else {
- return null;
- }
- }
-
- private static int[] parseCSV(String value) {
- int count = 0;
- int lastIndex = 0;
- if (value.length() > 0) {
- count++;
- while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) {
- count++;
- }
- }
- int[] values = new int[count];
- count = 0;
- StringTokenizer st = new StringTokenizer(value, ",");
- while (st.hasMoreTokens()) {
- try {
- values[count++] = Integer.parseInt(st.nextToken());
- } catch (NumberFormatException nfe) {
- Log.w(TAG, "Error parsing integer CSV " + value);
- }
- }
- return values;
- }
- }
-
- public static class DeclaredKeyStyle extends EmptyKeyStyle {
- private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>();
-
- @Override
- public int[] getIntArray(TypedArray a, int index) {
- return a.hasValue(index)
- ? super.getIntArray(a, index) : (int[])mAttributes.get(index);
- }
-
- @Override
- public Drawable getDrawable(TypedArray a, int index) {
- return a.hasValue(index)
- ? super.getDrawable(a, index) : (Drawable)mAttributes.get(index);
- }
-
- @Override
- public CharSequence getText(TypedArray a, int index) {
- return a.hasValue(index)
- ? super.getText(a, index) : (CharSequence)mAttributes.get(index);
- }
-
- @Override
- public int getResourceId(TypedArray a, int index, int defaultValue) {
- final Integer value = (Integer)mAttributes.get(index);
- return super.getResourceId(a, index, (value != null) ? value : defaultValue);
- }
-
- @Override
- public int getFlag(TypedArray a, int index, int defaultValue) {
- final Integer value = (Integer)mAttributes.get(index);
- return super.getFlag(a, index, defaultValue) | (value != null ? value : 0);
- }
-
- @Override
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
- final Boolean value = (Boolean)mAttributes.get(index);
- return super.getBoolean(a, index, (value != null) ? value : defaultValue);
- }
-
- private DeclaredKeyStyle() {
- super();
- }
-
- private void parseKeyStyleAttributes(TypedArray a) {
- // TODO: Currently not all Key attributes can be declared as style.
- readIntArray(a, R.styleable.BaseKeyboard_Key_codes);
- readText(a, R.styleable.BaseKeyboard_Key_keyLabel);
- readFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption);
- readText(a, R.styleable.BaseKeyboard_Key_keyOutputText);
- readDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon);
- readDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview);
- readDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon);
- readDrawable(a, R.styleable.BaseKeyboard_Key_shiftedIcon);
- readResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard);
- readBoolean(a, R.styleable.BaseKeyboard_Key_isModifier);
- readBoolean(a, R.styleable.BaseKeyboard_Key_isSticky);
- readBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable);
- }
-
- private void readDrawable(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getDrawable(index));
- }
-
- private void readText(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getText(index));
- }
-
- private void readResourceId(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getResourceId(index, 0));
- }
-
- private void readFlag(TypedArray a, int index) {
- final Integer value = (Integer)mAttributes.get(index);
- if (a.hasValue(index))
- mAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0));
- }
-
- private void readBoolean(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getBoolean(index, false));
- }
-
- private void readIntArray(TypedArray a, int index) {
- if (a.hasValue(index)) {
- final int[] value = parseIntArray(a, index);
- if (value != null)
- mAttributes.put(index, value);
- }
- }
-
- private void addParent(DeclaredKeyStyle parentStyle) {
- mAttributes.putAll(parentStyle.mAttributes);
- }
- }
-
- public void parseKeyStyleAttributes(TypedArray a, TypedArray keyAttrs,
- XmlResourceParser parser) {
- String styleName = a.getString(R.styleable.BaseKeyboard_KeyStyle_styleName);
- if (mStyles.containsKey(styleName))
- throw new ParseException("duplicate key style declared: " + styleName, parser);
-
- final DeclaredKeyStyle style = new DeclaredKeyStyle();
- if (a.hasValue(R.styleable.BaseKeyboard_KeyStyle_parentStyle)) {
- String parentStyle = a.getString(
- R.styleable.BaseKeyboard_KeyStyle_parentStyle);
- final DeclaredKeyStyle parent = mStyles.get(parentStyle);
- if (parent == null)
- throw new ParseException("Unknown parentStyle " + parent, parser);
- style.addParent(parent);
- }
- style.parseKeyStyleAttributes(keyAttrs);
- mStyles.put(styleName, style);
- }
-
- public KeyStyle getKeyStyle(String styleName) {
- return mStyles.get(styleName);
- }
-
- public KeyStyle getEmptyKeyStyle() {
- return EMPTY_KEY_STYLE;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
index 00b6f0a43..e8487e798 100644
--- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
@@ -16,16 +16,19 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.LatinKeyboard;
+import com.android.inputmethod.keyboard.LatinKeyboardView;
+
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.Log;
import android.view.InflateException;
-import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import java.lang.ref.SoftReference;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
@@ -34,14 +37,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final boolean DEBUG = false;
public static final boolean DEBUG_STATE = false;
- public static final int MODE_TEXT = 0;
- public static final int MODE_URL = 1;
- public static final int MODE_EMAIL = 2;
- public static final int MODE_IM = 3;
- public static final int MODE_WEB = 4;
- public static final int MODE_PHONE = 5;
- public static final int MODE_NUMBER = 6;
-
// Changing DEFAULT_LAYOUT_ID also requires prefs_for_debug.xml to be matched with.
public static final String DEFAULT_LAYOUT_ID = "5";
public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
@@ -74,7 +69,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
- private int mMode = MODE_TEXT; /* default value */
+ private int mMode = KeyboardId.MODE_TEXT; /* default value */
private int mImeOptions;
private boolean mIsSymbols;
/** mIsAutoCompletionActive indicates that auto completed word will be input instead of
@@ -132,129 +127,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
// respectively here for xlarge device's layout switching.
mSymbolsId = new KeyboardId(locale, orientation, mode,
- mode == MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols,
+ mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols,
colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true);
mSymbolsShiftedId = new KeyboardId(locale, orientation, mode,
- mode == MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift,
+ mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift,
colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true);
}
- /**
- * Represents the parameters necessary to construct a new LatinKeyboard,
- * which also serve as a unique identifier for each keyboard type.
- */
- public static class KeyboardId {
- public final Locale mLocale;
- public final int mOrientation;
- public final int mMode;
- public final int mXmlId;
- public final int mColorScheme;
- public final boolean mHasSettingsKey;
- public final boolean mVoiceKeyEnabled;
- public final boolean mHasVoiceKey;
- public final int mImeOptions;
- public final boolean mEnableShiftLock;
-
- private final int mHashCode;
-
- public KeyboardId(Locale locale, int orientation, int mode,
- int xmlId, int colorScheme, boolean hasSettingsKey, boolean voiceKeyEnabled,
- boolean hasVoiceKey, int imeOptions, boolean enableShiftLock) {
- this.mLocale = locale;
- this.mOrientation = orientation;
- this.mMode = mode;
- this.mXmlId = xmlId;
- this.mColorScheme = colorScheme;
- this.mHasSettingsKey = hasSettingsKey;
- this.mVoiceKeyEnabled = voiceKeyEnabled;
- this.mHasVoiceKey = hasVoiceKey;
- // We are interested only in IME_MASK_ACTION enum value and IME_FLAG_NO_ENTER_ACTION.
- this.mImeOptions = imeOptions
- & (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
- this.mEnableShiftLock = enableShiftLock;
-
- this.mHashCode = Arrays.hashCode(new Object[] {
- locale,
- orientation,
- mode,
- xmlId,
- colorScheme,
- hasSettingsKey,
- voiceKeyEnabled,
- hasVoiceKey,
- imeOptions,
- enableShiftLock,
- });
- }
-
- public int getXmlId() {
- return mXmlId;
- }
-
- public boolean isAlphabetMode() {
- return mXmlId == R.xml.kbd_qwerty;
- }
-
- @Override
- public boolean equals(Object other) {
- return other instanceof KeyboardId && equals((KeyboardId) other);
- }
-
- private boolean equals(KeyboardId other) {
- return other.mLocale.equals(this.mLocale)
- && other.mOrientation == this.mOrientation
- && other.mMode == this.mMode
- && other.mXmlId == this.mXmlId
- && other.mColorScheme == this.mColorScheme
- && other.mHasSettingsKey == this.mHasSettingsKey
- && other.mVoiceKeyEnabled == this.mVoiceKeyEnabled
- && other.mHasVoiceKey == this.mHasVoiceKey
- && other.mImeOptions == this.mImeOptions
- && other.mEnableShiftLock == this.mEnableShiftLock;
- }
-
- @Override
- public int hashCode() {
- return mHashCode;
- }
-
- @Override
- public String toString() {
- return String.format("[%s %s %5s imeOptions=0x%08x xml=0x%08x %s%s%s%s%s]",
- mLocale,
- (mOrientation == 1 ? "port" : "land"),
- modeName(mMode),
- mImeOptions,
- mXmlId,
- colorSchemeName(mColorScheme),
- (mHasSettingsKey ? " hasSettingsKey" : ""),
- (mVoiceKeyEnabled ? " voiceKeyEnabled" : ""),
- (mHasVoiceKey ? " hasVoiceKey" : ""),
- (mEnableShiftLock ? " enableShiftLock" : ""));
- }
-
- private static String modeName(int mode) {
- switch (mode) {
- case MODE_TEXT: return "text";
- case MODE_URL: return "url";
- case MODE_EMAIL: return "email";
- case MODE_IM: return "im";
- case MODE_WEB: return "web";
- case MODE_PHONE: return "phone";
- case MODE_NUMBER: return "number";
- }
- return null;
- }
-
- private static String colorSchemeName(int colorScheme) {
- switch (colorScheme) {
- case BaseKeyboardView.COLOR_SCHEME_WHITE: return "white";
- case BaseKeyboardView.COLOR_SCHEME_BLACK: return "black";
- }
- return null;
- }
- }
-
private boolean hasVoiceKey(boolean isSymbols) {
return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary);
}
@@ -327,9 +206,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final boolean enableShiftLock;
if (isSymbols) {
- if (mode == MODE_PHONE) {
+ if (mode == KeyboardId.MODE_PHONE) {
xmlId = R.xml.kbd_phone_symbols;
- } else if (mode == MODE_NUMBER) {
+ } else if (mode == KeyboardId.MODE_NUMBER) {
// Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key.
xmlId = R.xml.kbd_number;
} else {
@@ -337,10 +216,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
enableShiftLock = false;
} else {
- if (mode == MODE_PHONE) {
+ if (mode == KeyboardId.MODE_PHONE) {
xmlId = R.xml.kbd_phone;
enableShiftLock = false;
- } else if (mode == MODE_NUMBER) {
+ } else if (mode == KeyboardId.MODE_NUMBER) {
xmlId = R.xml.kbd_number;
enableShiftLock = false;
} else {
@@ -731,7 +610,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private int getColorScheme() {
return (mInputView != null)
- ? mInputView.getColorScheme() : BaseKeyboardView.COLOR_SCHEME_WHITE;
+ ? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE;
}
public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 36c77efaf..4f4112fa8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,6 +16,12 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardActionListener;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.LatinKeyboard;
+import com.android.inputmethod.keyboard.LatinKeyboardView;
import com.android.inputmethod.latin.LatinIMEUtil.RingCharBuffer;
import com.android.inputmethod.voice.VoiceIMEConnector;
@@ -73,7 +79,7 @@ import java.util.Locale;
* Input method implementation for Qwerty'ish keyboard.
*/
public class LatinIME extends InputMethodService
- implements BaseKeyboardView.OnKeyboardActionListener,
+ implements KeyboardActionListener,
SharedPreferences.OnSharedPreferenceChangeListener,
Tutorial.TutorialListener {
private static final String TAG = "LatinIME";
@@ -548,10 +554,10 @@ public class LatinIME extends InputMethodService
switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
case EditorInfo.TYPE_CLASS_NUMBER:
case EditorInfo.TYPE_CLASS_DATETIME:
- mode = KeyboardSwitcher.MODE_NUMBER;
+ mode = KeyboardId.MODE_NUMBER;
break;
case EditorInfo.TYPE_CLASS_PHONE:
- mode = KeyboardSwitcher.MODE_PHONE;
+ mode = KeyboardId.MODE_PHONE;
break;
case EditorInfo.TYPE_CLASS_TEXT:
//startPrediction();
@@ -568,24 +574,24 @@ public class LatinIME extends InputMethodService
}
if (isEmailVariation(variation)) {
mPredictionOn = false;
- mode = KeyboardSwitcher.MODE_EMAIL;
+ mode = KeyboardId.MODE_EMAIL;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
mPredictionOn = false;
- mode = KeyboardSwitcher.MODE_URL;
+ mode = KeyboardId.MODE_URL;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
- mode = KeyboardSwitcher.MODE_IM;
+ mode = KeyboardId.MODE_IM;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
mPredictionOn = false;
- mode = KeyboardSwitcher.MODE_TEXT;
+ mode = KeyboardId.MODE_TEXT;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
- mode = KeyboardSwitcher.MODE_WEB;
+ mode = KeyboardId.MODE_WEB;
// If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on.
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
mInputTypeNoAutoCorrect = true;
}
} else {
- mode = KeyboardSwitcher.MODE_TEXT;
+ mode = KeyboardId.MODE_TEXT;
}
// If NO_SUGGESTIONS is set, don't do prediction.
@@ -604,7 +610,7 @@ public class LatinIME extends InputMethodService
}
break;
default:
- mode = KeyboardSwitcher.MODE_TEXT;
+ mode = KeyboardId.MODE_TEXT;
break;
}
inputView.closing();
@@ -675,7 +681,7 @@ public class LatinIME extends InputMethodService
mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging);
- BaseKeyboardView inputView = mKeyboardSwitcher.getInputView();
+ KeyboardView inputView = mKeyboardSwitcher.getInputView();
if (inputView != null)
inputView.closing();
if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites();
@@ -685,7 +691,7 @@ public class LatinIME extends InputMethodService
@Override
public void onFinishInputView(boolean finishingInput) {
super.onFinishInputView(finishingInput);
- BaseKeyboardView inputView = mKeyboardSwitcher.getInputView();
+ KeyboardView inputView = mKeyboardSwitcher.getInputView();
if (inputView != null)
inputView.setForeground(false);
// Remove pending messages related to update suggestions
@@ -1073,51 +1079,52 @@ public class LatinIME extends InputMethodService
// Implementation of KeyboardViewListener
+ @Override
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
long when = SystemClock.uptimeMillis();
- if (primaryCode != BaseKeyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
+ if (primaryCode != Keyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
mDeleteCount = 0;
}
mLastKeyTime = when;
KeyboardSwitcher switcher = mKeyboardSwitcher;
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
switch (primaryCode) {
- case BaseKeyboard.KEYCODE_DELETE:
+ case Keyboard.KEYCODE_DELETE:
handleBackspace();
mDeleteCount++;
LatinImeLogger.logOnDelete();
break;
- case BaseKeyboard.KEYCODE_SHIFT:
+ case Keyboard.KEYCODE_SHIFT:
// Shift key is handled in onPress() when device has distinct multi-touch panel.
if (!distinctMultiTouch)
switcher.toggleShift();
break;
- case BaseKeyboard.KEYCODE_MODE_CHANGE:
+ case Keyboard.KEYCODE_MODE_CHANGE:
// Symbol key is handled in onPress() when device has distinct multi-touch panel.
if (!distinctMultiTouch)
switcher.changeKeyboardMode();
break;
- case BaseKeyboard.KEYCODE_CANCEL:
+ case Keyboard.KEYCODE_CANCEL:
if (!isShowingOptionDialog()) {
handleClose();
}
break;
- case LatinKeyboardView.KEYCODE_OPTIONS:
+ case LatinKeyboard.KEYCODE_OPTIONS:
onOptionKeyPressed();
break;
- case LatinKeyboardView.KEYCODE_OPTIONS_LONGPRESS:
+ case LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS:
onOptionKeyLongPressed();
break;
- case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
+ case LatinKeyboard.KEYCODE_NEXT_LANGUAGE:
toggleLanguage(false, true);
break;
- case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
+ case LatinKeyboard.KEYCODE_PREV_LANGUAGE:
toggleLanguage(false, false);
break;
- case LatinKeyboardView.KEYCODE_CAPSLOCK:
+ case LatinKeyboard.KEYCODE_CAPSLOCK:
switcher.toggleCapsLock();
break;
- case LatinKeyboardView.KEYCODE_VOICE: /* was a button press, was not a swipe */
+ case LatinKeyboard.KEYCODE_VOICE: /* was a button press, was not a swipe */
mVoiceConnector.startListening(false,
mKeyboardSwitcher.getInputView().getWindowToken(), mConfigurationChanging);
break;
@@ -1143,6 +1150,7 @@ public class LatinIME extends InputMethodService
mEnteredText = null;
}
+ @Override
public void onText(CharSequence text) {
mVoiceConnector.commitVoiceInput();
InputConnection ic = getCurrentInputConnection();
@@ -1161,6 +1169,7 @@ public class LatinIME extends InputMethodService
mEnteredText = text;
}
+ @Override
public void onCancel() {
// User released a finger outside any key
}
@@ -1420,24 +1429,26 @@ public class LatinIME extends InputMethodService
}
public void switchToKeyboardView() {
- mHandler.post(new Runnable() {
- public void run() {
- if (DEBUG) {
- Log.d(TAG, "Switch to keyboard view.");
- }
- View v = mKeyboardSwitcher.getInputView();
- if (v != null) {
- // Confirms that the keyboard view doesn't have parent view.
- ViewParent p = v.getParent();
- if (p != null && p instanceof ViewGroup) {
- ((ViewGroup)p).removeView(v);
- }
- setInputView(v);
- }
- setCandidatesViewShown(isCandidateStripVisible());
- updateInputViewShown();
- mHandler.postUpdateSuggestions();
- }});
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG) {
+ Log.d(TAG, "Switch to keyboard view.");
+ }
+ View v = mKeyboardSwitcher.getInputView();
+ if (v != null) {
+ // Confirms that the keyboard view doesn't have parent view.
+ ViewParent p = v.getParent();
+ if (p != null && p instanceof ViewGroup) {
+ ((ViewGroup) p).removeView(v);
+ }
+ setInputView(v);
+ }
+ setCandidatesViewShown(isCandidateStripVisible());
+ updateInputViewShown();
+ mHandler.postUpdateSuggestions();
+ }
+ });
}
public void clearSuggestions() {
@@ -1586,8 +1597,8 @@ public class LatinIME extends InputMethodService
LatinImeLogger.logOnManualSuggestion(
"", suggestion.toString(), index, suggestions);
final char primaryCode = suggestion.charAt(0);
- onKey(primaryCode, new int[]{primaryCode}, BaseKeyboardView.NOT_A_TOUCH_COORDINATE,
- BaseKeyboardView.NOT_A_TOUCH_COORDINATE);
+ onKey(primaryCode, new int[]{primaryCode}, KeyboardView.NOT_A_TOUCH_COORDINATE,
+ KeyboardView.NOT_A_TOUCH_COORDINATE);
if (ic != null) {
ic.endBatchEdit();
}
@@ -1877,6 +1888,7 @@ public class LatinIME extends InputMethodService
switcher.updateShiftState();
}
+ @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
mSubtypeSwitcher.onSharedPreferenceChanged(sharedPreferences, key);
@@ -1888,6 +1900,7 @@ public class LatinIME extends InputMethodService
}
}
+ @Override
public void swipeRight() {
if (LatinKeyboardView.DEBUG_AUTO_PLAY) {
CharSequence text = ((android.text.ClipboardManager)getSystemService(
@@ -1898,38 +1911,43 @@ public class LatinIME extends InputMethodService
}
}
+ @Override
public void swipeLeft() {
}
+ @Override
public void swipeDown() {
handleClose();
}
+ @Override
public void swipeUp() {
}
+ @Override
public void onPress(int primaryCode) {
vibrate();
playKeyClick(primaryCode);
KeyboardSwitcher switcher = mKeyboardSwitcher;
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
- if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
+ if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
switcher.onPressShift();
- } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
+ } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
switcher.onPressSymbol();
} else {
switcher.onOtherKeyPressed();
}
}
+ @Override
public void onRelease(int primaryCode) {
KeyboardSwitcher switcher = mKeyboardSwitcher;
// Reset any drag flags in the keyboard
switcher.keyReleased();
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
- if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
+ if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
switcher.onReleaseShift();
- } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
+ } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
switcher.onReleaseSymbol();
}
}
@@ -1966,7 +1984,7 @@ public class LatinIME extends InputMethodService
// FIXME: These should be triggered after auto-repeat logic
int sound = AudioManager.FX_KEYPRESS_STANDARD;
switch (primaryCode) {
- case BaseKeyboard.KEYCODE_DELETE:
+ case Keyboard.KEYCODE_DELETE:
sound = AudioManager.FX_KEYPRESS_DELETE;
break;
case KEYCODE_ENTER:
@@ -2006,6 +2024,7 @@ public class LatinIME extends InputMethodService
}
// Tutorial.TutorialListener
+ @Override
public void onTutorialDone() {
sendDownUpKeyEvents(-1); // Inform the setupwizard that tutorial is in last bubble
mTutorial = null;
@@ -2171,6 +2190,7 @@ public class LatinIME extends InputMethodService
itemInputMethod, itemSettings},
new DialogInterface.OnClickListener() {
+ @Override
public void onClick(DialogInterface di, int position) {
di.dismiss();
switch (position) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIMEDebugSettings.java b/java/src/com/android/inputmethod/latin/LatinIMEDebugSettings.java
index cba1a0af9..68738eca1 100644
--- a/java/src/com/android/inputmethod/latin/LatinIMEDebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/LatinIMEDebugSettings.java
@@ -43,6 +43,7 @@ public class LatinIMEDebugSettings extends PreferenceActivity
updateDebugMode();
}
+ @Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals(DEBUG_MODE_KEY)) {
if (mDebugMode != null) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIMESettings.java b/java/src/com/android/inputmethod/latin/LatinIMESettings.java
index ae6646113..187b6d394 100644
--- a/java/src/com/android/inputmethod/latin/LatinIMESettings.java
+++ b/java/src/com/android/inputmethod/latin/LatinIMESettings.java
@@ -137,6 +137,7 @@ public class LatinIMESettings extends PreferenceActivity
super.onDestroy();
}
+ @Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
(new BackupManager(this)).dataChanged();
// If turning on voice input, show dialog
@@ -181,6 +182,7 @@ public class LatinIMESettings extends PreferenceActivity
switch (id) {
case VOICE_INPUT_CONFIRM_DIALOG:
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int whichButton) {
if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
mVoicePreference.setValue(mVoiceModeOff);
@@ -226,6 +228,7 @@ public class LatinIMESettings extends PreferenceActivity
}
}
+ @Override
public void onDismiss(DialogInterface dialog) {
mLogger.settingsWarningDialogDismissed();
if (!mOkClicked) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java
index a58f630cd..f508b9ab8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java
+++ b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java
@@ -310,6 +310,7 @@ public class LatinIMEUtil {
public void write(final String log) {
mLoggingHandler.post(new Runnable() {
+ @Override
public void run() {
createLogFileIfNotExist();
final long currentTime = System.currentTimeMillis();
@@ -327,6 +328,7 @@ public class LatinIMEUtil {
public void printAll() {
mLoggingHandler.post(new Runnable() {
+ @Override
public void run() {
mWriter.flush();
StringBuilder sb = new StringBuilder();
@@ -355,6 +357,7 @@ public class LatinIMEUtil {
public void clearAll() {
mLoggingHandler.post(new Runnable() {
+ @Override
public void run() {
if (mFile != null && mFile.exists()) {
if (LatinImeLogger.sDBG) {
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index b64e3ddb2..de194d21b 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.Dictionary.DataType;
import android.content.Context;
@@ -27,6 +28,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static boolean sDBG = false;
+ @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
@@ -67,7 +69,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void onAddSuggestedWord(String word, int typeId, DataType dataType) {
}
- public static void onSetKeyboard(BaseKeyboard kb) {
+ public static void onSetKeyboard(Keyboard kb) {
}
public static void onPrintAllUsabilityStudtyLogs() {
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
deleted file mode 100644
index cae0b10b3..000000000
--- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ /dev/null
@@ -1,720 +0,0 @@
-/*
- * Copyright (C) 2008 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.latin;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.text.TextPaint;
-import android.util.Log;
-import android.view.ViewConfiguration;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-public class LatinKeyboard extends BaseKeyboard {
-
- private static final boolean DEBUG_PREFERRED_LETTER = false;
- private static final String TAG = "LatinKeyboard";
- private static final int OPACITY_FULLY_OPAQUE = 255;
- private static final int SPACE_LED_LENGTH_PERCENT = 80;
-
- private Drawable mShiftLockPreviewIcon;
- private final HashMap<Key, Drawable> mNormalShiftIcons = new HashMap<Key, Drawable>();
- private Drawable mSpaceIcon;
- private Drawable mSpaceAutoCompletionIndicator;
- private Drawable mSpacePreviewIcon;
- private final Drawable mButtonArrowLeftIcon;
- private final Drawable mButtonArrowRightIcon;
- private final int mSpaceBarTextShadowColor;
- private Key mSpaceKey;
- private int mSpaceKeyIndex = -1;
- private int mSpaceDragStartX;
- private int mSpaceDragLastDiff;
- private final Resources mRes;
- private final Context mContext;
- private boolean mCurrentlyInSpace;
- private SlidingLocaleDrawable mSlidingLocaleIcon;
- private int[] mPrefLetterFrequencies;
- private int mPrefLetter;
- private int mPrefLetterX;
- private int mPrefLetterY;
- private int mPrefDistance;
-
- private LatinKeyboardShiftState mShiftState = new LatinKeyboardShiftState();
-
- private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
- private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f;
- private static final float OVERLAP_PERCENTAGE_HIGH_PROB = 0.85f;
- // Minimum width of space key preview (proportional to keyboard width)
- private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f;
- // Height in space key the language name will be drawn. (proportional to space key height)
- private static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
- // If the full language name needs to be smaller than this value to be drawn on space key,
- // its short language name will be used instead.
- private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
-
- private static int sSpacebarVerticalCorrection;
-
- public LatinKeyboard(Context context, KeyboardSwitcher.KeyboardId id) {
- super(context, id);
- final Resources res = context.getResources();
- mContext = context;
- mRes = res;
- if (id.mColorScheme == BaseKeyboardView.COLOR_SCHEME_BLACK) {
- mSpaceBarTextShadowColor = res.getColor(
- R.color.latinkeyboard_bar_language_shadow_black);
- } else { // default color scheme is BaseKeyboardView.COLOR_SCHEME_WHITE
- mSpaceBarTextShadowColor = res.getColor(
- R.color.latinkeyboard_bar_language_shadow_white);
- }
- mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked);
- setDefaultBounds(mShiftLockPreviewIcon);
- mSpaceAutoCompletionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led);
- mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left);
- mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right);
- sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
- R.dimen.spacebar_vertical_correction);
- mSpaceKeyIndex = indexOf(LatinIME.KEYCODE_SPACE);
- }
-
- @Override
- protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
- XmlResourceParser parser, KeyStyles keyStyles) {
- Key key = new LatinKey(res, parent, x, y, parser, keyStyles);
- switch (key.codes[0]) {
- case LatinIME.KEYCODE_SPACE:
- mSpaceKey = key;
- mSpaceIcon = key.icon;
- mSpacePreviewIcon = key.iconPreview;
- break;
- }
-
- return key;
- }
-
- public void enableShiftLock() {
- for (final Key key : getShiftKeys()) {
- if (key instanceof LatinKey) {
- ((LatinKey)key).enableShiftLock();
- }
- mNormalShiftIcons.put(key, key.icon);
- }
- }
-
- public boolean setShiftLocked(boolean newShiftLockState) {
- final Map<Key, Drawable> shiftedIcons = getShiftedIcons();
- for (final Key key : getShiftKeys()) {
- key.on = newShiftLockState;
- key.icon = newShiftLockState ? shiftedIcons.get(key) : mNormalShiftIcons.get(key);
- }
- mShiftState.setShiftLocked(newShiftLockState);
- return true;
- }
-
- public boolean isShiftLocked() {
- return mShiftState.isShiftLocked();
- }
-
- @Override
- public boolean setShifted(boolean newShiftState) {
- if (getShiftKeys().size() == 0)
- return super.setShifted(newShiftState);
-
- final Map<Key, Drawable> shiftedIcons = getShiftedIcons();
- for (final Key key : getShiftKeys()) {
- if (!newShiftState && !mShiftState.isShiftLocked()) {
- key.icon = mNormalShiftIcons.get(key);
- } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) {
- key.icon = shiftedIcons.get(key);
- }
- }
- return mShiftState.setShifted(newShiftState);
- }
-
- @Override
- public boolean isShiftedOrShiftLocked() {
- if (getShiftKeys().size() > 0) {
- return mShiftState.isShiftedOrShiftLocked();
- } else {
- return super.isShiftedOrShiftLocked();
- }
- }
-
- public void setAutomaticTemporaryUpperCase() {
- setShifted(true);
- mShiftState.setAutomaticTemporaryUpperCase();
- }
-
- public boolean isAutomaticTemporaryUpperCase() {
- return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase();
- }
-
- public boolean isManualTemporaryUpperCase() {
- return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
- }
-
- /* package */ LatinKeyboardShiftState getKeyboardShiftState() {
- return mShiftState;
- }
-
- public boolean isAlphaKeyboard() {
- return mId.getXmlId() == R.xml.kbd_qwerty;
- }
-
- public boolean isPhoneKeyboard() {
- return mId.mMode == KeyboardSwitcher.MODE_PHONE;
- }
-
- public boolean isNumberKeyboard() {
- return mId.mMode == KeyboardSwitcher.MODE_NUMBER;
- }
-
- /**
- * @return a key which should be invalidated.
- */
- public Key onAutoCompletionStateChanged(boolean isAutoCompletion) {
- updateSpaceBarForLocale(isAutoCompletion);
- return mSpaceKey;
- }
-
- private void updateSpaceBarForLocale(boolean isAutoCompletion) {
- final Resources res = mRes;
- // If application locales are explicitly selected.
- if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) {
- mSpaceKey.icon = new BitmapDrawable(res,
- drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion));
- } else {
- // sym_keyboard_space_led can be shared with Black and White symbol themes.
- if (isAutoCompletion) {
- mSpaceKey.icon = new BitmapDrawable(res,
- drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion));
- } else {
- mSpaceKey.icon = mSpaceIcon;
- }
- }
- }
-
- // Compute width of text with specified text size using paint.
- private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) {
- paint.setTextSize(textSize);
- paint.getTextBounds(text, 0, text.length(), bounds);
- return bounds.width();
- }
-
- // Layout local language name and left and right arrow on space bar.
- private static String layoutSpaceBar(Paint paint, Locale locale, Drawable lArrow,
- Drawable rArrow, int width, int height, float origTextSize,
- boolean allowVariableTextSize) {
- final float arrowWidth = lArrow.getIntrinsicWidth();
- final float arrowHeight = lArrow.getIntrinsicHeight();
- final float maxTextWidth = width - (arrowWidth + arrowWidth);
- final Rect bounds = new Rect();
-
- // Estimate appropriate language name text size to fit in maxTextWidth.
- String language = SubtypeSwitcher.getDisplayLanguage(locale);
- int textWidth = getTextWidth(paint, language, origTextSize, bounds);
- // Assuming text width and text size are proportional to each other.
- float textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
-
- final boolean useShortName;
- if (allowVariableTextSize) {
- textWidth = getTextWidth(paint, language, textSize, bounds);
- // If text size goes too small or text does not fit, use short name
- useShortName = textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME
- || textWidth > maxTextWidth;
- } else {
- useShortName = textWidth > maxTextWidth;
- textSize = origTextSize;
- }
- if (useShortName) {
- language = SubtypeSwitcher.getShortDisplayLanguage(locale);
- textWidth = getTextWidth(paint, language, origTextSize, bounds);
- textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
- }
- paint.setTextSize(textSize);
-
- // Place left and right arrow just before and after language text.
- final float baseline = height * SPACEBAR_LANGUAGE_BASELINE;
- final int top = (int)(baseline - arrowHeight);
- final float remains = (width - textWidth) / 2;
- lArrow.setBounds((int)(remains - arrowWidth), top, (int)remains, (int)baseline);
- rArrow.setBounds((int)(remains + textWidth), top, (int)(remains + textWidth + arrowWidth),
- (int)baseline);
-
- return language;
- }
-
- private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion) {
- final int width = mSpaceKey.width;
- final int height = mSpaceIcon.getIntrinsicHeight();
- final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(buffer);
- final Resources res = mRes;
- canvas.drawColor(res.getColor(R.color.latinkeyboard_transparent), PorterDuff.Mode.CLEAR);
-
- SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
- // If application locales are explicitly selected.
- if (subtypeSwitcher.needsToDisplayLanguage()) {
- final Paint paint = new Paint();
- paint.setAlpha(opacity);
- paint.setAntiAlias(true);
- paint.setTextAlign(Align.CENTER);
-
- final boolean allowVariableTextSize = true;
- final String language = layoutSpaceBar(paint, subtypeSwitcher.getInputLocale(),
- mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
- getTextSizeFromTheme(android.R.style.TextAppearance_Small, 14),
- allowVariableTextSize);
-
- // Draw language text with shadow
- final float baseline = height * SPACEBAR_LANGUAGE_BASELINE;
- final float descent = paint.descent();
- paint.setColor(mSpaceBarTextShadowColor);
- canvas.drawText(language, width / 2, baseline - descent - 1, paint);
- paint.setColor(res.getColor(R.color.latinkeyboard_bar_language_text));
- canvas.drawText(language, width / 2, baseline - descent, paint);
-
- // Put arrows that are already layed out on either side of the text
- if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
- && subtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) {
- mButtonArrowLeftIcon.draw(canvas);
- mButtonArrowRightIcon.draw(canvas);
- }
- }
-
- // Draw the spacebar icon at the bottom
- if (isAutoCompletion) {
- final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100;
- final int iconHeight = mSpaceAutoCompletionIndicator.getIntrinsicHeight();
- int x = (width - iconWidth) / 2;
- int y = height - iconHeight;
- mSpaceAutoCompletionIndicator.setBounds(x, y, x + iconWidth, y + iconHeight);
- mSpaceAutoCompletionIndicator.draw(canvas);
- } else {
- final int iconWidth = mSpaceIcon.getIntrinsicWidth();
- final int iconHeight = mSpaceIcon.getIntrinsicHeight();
- int x = (width - iconWidth) / 2;
- int y = height - iconHeight;
- mSpaceIcon.setBounds(x, y, x + iconWidth, y + iconHeight);
- mSpaceIcon.draw(canvas);
- }
- return buffer;
- }
-
- private void updateLocaleDrag(int diff) {
- if (mSlidingLocaleIcon == null) {
- final int width = Math.max(mSpaceKey.width,
- (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
- final int height = mSpacePreviewIcon.getIntrinsicHeight();
- mSlidingLocaleIcon = new SlidingLocaleDrawable(mSpacePreviewIcon, width, height);
- mSlidingLocaleIcon.setBounds(0, 0, width, height);
- mSpaceKey.iconPreview = mSlidingLocaleIcon;
- }
- mSlidingLocaleIcon.setDiff(diff);
- if (Math.abs(diff) == Integer.MAX_VALUE) {
- mSpaceKey.iconPreview = mSpacePreviewIcon;
- } else {
- mSpaceKey.iconPreview = mSlidingLocaleIcon;
- }
- mSpaceKey.iconPreview.invalidateSelf();
- }
-
- public int getLanguageChangeDirection() {
- if (mSpaceKey == null || SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() <= 1
- || Math.abs(mSpaceDragLastDiff) < mSpaceKey.width * SPACEBAR_DRAG_THRESHOLD) {
- return 0; // No change
- }
- return mSpaceDragLastDiff > 0 ? 1 : -1;
- }
-
- boolean isCurrentlyInSpace() {
- return mCurrentlyInSpace;
- }
-
- public void setPreferredLetters(int[] frequencies) {
- mPrefLetterFrequencies = frequencies;
- mPrefLetter = 0;
- }
-
- public void keyReleased() {
- mCurrentlyInSpace = false;
- mSpaceDragLastDiff = 0;
- mPrefLetter = 0;
- mPrefLetterX = 0;
- mPrefLetterY = 0;
- mPrefDistance = Integer.MAX_VALUE;
- if (mSpaceKey != null) {
- updateLocaleDrag(Integer.MAX_VALUE);
- }
- }
-
- /**
- * Does the magic of locking the touch gesture into the spacebar when
- * switching input languages.
- */
- public boolean isInside(LatinKey key, int x, int y) {
- final int code = key.codes[0];
- if (code == KEYCODE_SHIFT || code == KEYCODE_DELETE) {
- y -= key.height / 10;
- if (code == KEYCODE_SHIFT) x += key.width / 6;
- if (code == KEYCODE_DELETE) x -= key.width / 6;
- } else if (code == LatinIME.KEYCODE_SPACE) {
- y += LatinKeyboard.sSpacebarVerticalCorrection;
- if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
- && SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() > 1) {
- if (mCurrentlyInSpace) {
- int diff = x - mSpaceDragStartX;
- if (Math.abs(diff - mSpaceDragLastDiff) > 0) {
- updateLocaleDrag(diff);
- }
- mSpaceDragLastDiff = diff;
- return true;
- } else {
- boolean insideSpace = key.isInsideSuper(x, y);
- if (insideSpace) {
- mCurrentlyInSpace = true;
- mSpaceDragStartX = x;
- updateLocaleDrag(0);
- }
- return insideSpace;
- }
- }
- } else if (mPrefLetterFrequencies != null) {
- // New coordinate? Reset
- if (mPrefLetterX != x || mPrefLetterY != y) {
- mPrefLetter = 0;
- mPrefDistance = Integer.MAX_VALUE;
- }
- // Handle preferred next letter
- final int[] pref = mPrefLetterFrequencies;
- if (mPrefLetter > 0) {
- if (DEBUG_PREFERRED_LETTER) {
- if (mPrefLetter == code && !key.isInsideSuper(x, y)) {
- Log.d(TAG, "CORRECTED !!!!!!");
- }
- }
- return mPrefLetter == code;
- } else {
- final boolean inside = key.isInsideSuper(x, y);
- int[] nearby = getNearestKeys(x, y);
- List<Key> nearbyKeys = getKeys();
- if (inside) {
- // If it's a preferred letter
- if (inPrefList(code, pref)) {
- // Check if its frequency is much lower than a nearby key
- mPrefLetter = code;
- mPrefLetterX = x;
- mPrefLetterY = y;
- for (int i = 0; i < nearby.length; i++) {
- Key k = nearbyKeys.get(nearby[i]);
- if (k != key && inPrefList(k.codes[0], pref)) {
- final int dist = distanceFrom(k, x, y);
- if (dist < (int) (k.width * OVERLAP_PERCENTAGE_LOW_PROB) &&
- (pref[k.codes[0]] > pref[mPrefLetter] * 3)) {
- mPrefLetter = k.codes[0];
- mPrefDistance = dist;
- if (DEBUG_PREFERRED_LETTER) {
- Log.d(TAG, "CORRECTED ALTHOUGH PREFERRED !!!!!!");
- }
- break;
- }
- }
- }
-
- return mPrefLetter == code;
- }
- }
-
- // Get the surrounding keys and intersect with the preferred list
- // For all in the intersection
- // if distance from touch point is within a reasonable distance
- // make this the pref letter
- // If no pref letter
- // return inside;
- // else return thiskey == prefletter;
-
- for (int i = 0; i < nearby.length; i++) {
- Key k = nearbyKeys.get(nearby[i]);
- if (inPrefList(k.codes[0], pref)) {
- final int dist = distanceFrom(k, x, y);
- if (dist < (int) (k.width * OVERLAP_PERCENTAGE_HIGH_PROB)
- && dist < mPrefDistance) {
- mPrefLetter = k.codes[0];
- mPrefLetterX = x;
- mPrefLetterY = y;
- mPrefDistance = dist;
- }
- }
- }
- // Didn't find any
- if (mPrefLetter == 0) {
- return inside;
- } else {
- return mPrefLetter == code;
- }
- }
- }
-
- // Lock into the spacebar
- if (mCurrentlyInSpace) return false;
-
- return key.isInsideSuper(x, y);
- }
-
- private boolean inPrefList(int code, int[] pref) {
- if (code < pref.length && code >= 0) return pref[code] > 0;
- return false;
- }
-
- private int distanceFrom(Key k, int x, int y) {
- if (y > k.y && y < k.y + k.height) {
- return Math.abs(k.x + k.width / 2 - x);
- } else {
- return Integer.MAX_VALUE;
- }
- }
-
- @Override
- public int[] getNearestKeys(int x, int y) {
- if (mCurrentlyInSpace) {
- return new int[] { mSpaceKeyIndex };
- } else {
- // Avoid dead pixels at edges of the keyboard
- return super.getNearestKeys(Math.max(0, Math.min(x, getMinWidth() - 1)),
- Math.max(0, Math.min(y, getHeight() - 1)));
- }
- }
-
- private int indexOf(int code) {
- List<Key> keys = getKeys();
- int count = keys.size();
- for (int i = 0; i < count; i++) {
- if (keys.get(i).codes[0] == code) return i;
- }
- return -1;
- }
-
- private int getTextSizeFromTheme(int style, int defValue) {
- TypedArray array = mContext.getTheme().obtainStyledAttributes(
- style, new int[] { android.R.attr.textSize });
- int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
- return textSize;
- }
-
- public static class LatinKey extends BaseKeyboard.Key {
-
- // functional normal state (with properties)
- private final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
- android.R.attr.state_single
- };
-
- // functional pressed state (with properties)
- private final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
- android.R.attr.state_single,
- android.R.attr.state_pressed
- };
-
- private boolean mShiftLockEnabled;
-
- public LatinKey(Resources res, BaseKeyboard.Row parent, int x, int y,
- XmlResourceParser parser, KeyStyles keyStyles) {
- super(res, parent, x, y, parser, keyStyles);
- if (popupCharacters != null && popupCharacters.length() == 0) {
- // If there is a keyboard with no keys specified in popupCharacters
- popupResId = 0;
- }
- }
-
- private void enableShiftLock() {
- mShiftLockEnabled = true;
- }
-
- // sticky is used for shift key. If a key is not sticky and is modifier,
- // the key will be treated as functional.
- private boolean isFunctionalKey() {
- return !sticky && modifier;
- }
-
- @Override
- public void onReleased(boolean inside) {
- if (!mShiftLockEnabled) {
- super.onReleased(inside);
- } else {
- pressed = !pressed;
- }
- }
-
- /**
- * Overriding this method so that we can reduce the target area for certain keys.
- */
- @Override
- public boolean isInside(int x, int y) {
- boolean result = (keyboard instanceof LatinKeyboard)
- && ((LatinKeyboard)keyboard).isInside(this, x, y);
- return result;
- }
-
- private boolean isInsideSuper(int x, int y) {
- return super.isInside(x, y);
- }
-
- @Override
- public int[] getCurrentDrawableState() {
- if (isFunctionalKey()) {
- if (pressed) {
- return KEY_STATE_FUNCTIONAL_PRESSED;
- } else {
- return KEY_STATE_FUNCTIONAL_NORMAL;
- }
- }
- return super.getCurrentDrawableState();
- }
- }
-
- /**
- * Animation to be displayed on the spacebar preview popup when switching
- * languages by swiping the spacebar. It draws the current, previous and
- * next languages and moves them by the delta of touch movement on the spacebar.
- */
- private class SlidingLocaleDrawable extends Drawable {
-
- private final int mWidth;
- private final int mHeight;
- private final Drawable mBackground;
- private final TextPaint mTextPaint;
- private final int mMiddleX;
- private final Drawable mLeftDrawable;
- private final Drawable mRightDrawable;
- private final int mThreshold;
- private int mDiff;
- private boolean mHitThreshold;
- private String mCurrentLanguage;
- private String mNextLanguage;
- private String mPrevLanguage;
-
- public SlidingLocaleDrawable(Drawable background, int width, int height) {
- mBackground = background;
- setDefaultBounds(mBackground);
- mWidth = width;
- mHeight = height;
- final TextPaint textPaint = new TextPaint();
- textPaint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18));
- textPaint.setColor(R.color.latinkeyboard_transparent);
- textPaint.setTextAlign(Align.CENTER);
- textPaint.setAlpha(OPACITY_FULLY_OPAQUE);
- textPaint.setAntiAlias(true);
- mTextPaint = textPaint;
- mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
- final Resources res = mRes;
- mLeftDrawable = res.getDrawable(
- R.drawable.sym_keyboard_feedback_language_arrows_left);
- mRightDrawable = res.getDrawable(
- R.drawable.sym_keyboard_feedback_language_arrows_right);
- mThreshold = ViewConfiguration.get(mContext).getScaledTouchSlop();
- }
-
- private void setDiff(int diff) {
- if (diff == Integer.MAX_VALUE) {
- mHitThreshold = false;
- mCurrentLanguage = null;
- return;
- }
- mDiff = diff;
- if (mDiff > mWidth) mDiff = mWidth;
- if (mDiff < -mWidth) mDiff = -mWidth;
- if (Math.abs(mDiff) > mThreshold) mHitThreshold = true;
- invalidateSelf();
- }
-
-
- @Override
- public void draw(Canvas canvas) {
- canvas.save();
- if (mHitThreshold) {
- Paint paint = mTextPaint;
- final int width = mWidth;
- final int height = mHeight;
- final int diff = mDiff;
- final Drawable lArrow = mLeftDrawable;
- final Drawable rArrow = mRightDrawable;
- canvas.clipRect(0, 0, width, height);
- if (mCurrentLanguage == null) {
- SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
- mCurrentLanguage = subtypeSwitcher.getInputLanguageName();
- mNextLanguage = subtypeSwitcher.getNextInputLanguageName();
- mPrevLanguage = subtypeSwitcher.getPreviousInputLanguageName();
- }
- // Draw language text with shadow
- final float baseline = mHeight * SPACEBAR_LANGUAGE_BASELINE - paint.descent();
- paint.setColor(mRes.getColor(R.color.latinkeyboard_feedback_language_text));
- canvas.drawText(mCurrentLanguage, width / 2 + diff, baseline, paint);
- canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint);
- canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint);
-
- setDefaultBounds(lArrow);
- rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width,
- rArrow.getIntrinsicHeight());
- lArrow.draw(canvas);
- rArrow.draw(canvas);
- }
- if (mBackground != null) {
- canvas.translate(mMiddleX, 0);
- mBackground.draw(canvas);
- }
- canvas.restore();
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public void setAlpha(int alpha) {
- // Ignore
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- // Ignore
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mWidth;
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mHeight;
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java b/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java
deleted file mode 100644
index e916306c8..000000000
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.android.inputmethod.latin;
-
-import android.util.Log;
-
-public class LatinKeyboardShiftState {
- private static final String TAG = "LatinKeyboardShiftState";
- private static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE;
-
- private static final int NORMAL = 0;
- private static final int MANUAL_SHIFTED = 1;
- private static final int SHIFT_LOCKED = 2;
- private static final int AUTO_SHIFTED = 3;
- private static final int SHIFT_LOCK_SHIFTED = 4;
-
- private int mState = NORMAL;
-
- public boolean setShifted(boolean newShiftState) {
- final int oldState = mState;
- if (newShiftState) {
- if (oldState == NORMAL || oldState == AUTO_SHIFTED) {
- mState = MANUAL_SHIFTED;
- } else if (oldState == SHIFT_LOCKED) {
- mState = SHIFT_LOCK_SHIFTED;
- }
- } else {
- if (oldState == MANUAL_SHIFTED || oldState == AUTO_SHIFTED) {
- mState = NORMAL;
- } else if (oldState == SHIFT_LOCK_SHIFTED) {
- mState = SHIFT_LOCKED;
- }
- }
- if (DEBUG)
- Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this);
- return mState != oldState;
- }
-
- public void setShiftLocked(boolean newShiftLockState) {
- final int oldState = mState;
- if (newShiftLockState) {
- if (oldState == NORMAL || oldState == MANUAL_SHIFTED || oldState == AUTO_SHIFTED)
- mState = SHIFT_LOCKED;
- } else {
- if (oldState == SHIFT_LOCKED || oldState == SHIFT_LOCK_SHIFTED)
- mState = NORMAL;
- }
- if (DEBUG)
- Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState)
- + " > " + this);
- }
-
- public void setAutomaticTemporaryUpperCase() {
- final int oldState = mState;
- mState = AUTO_SHIFTED;
- if (DEBUG)
- Log.d(TAG, "setAutomaticTemporaryUpperCase: " + toString(oldState) + " > " + this);
- }
-
- public boolean isShiftedOrShiftLocked() {
- return mState != NORMAL;
- }
-
- public boolean isShiftLocked() {
- return mState == SHIFT_LOCKED || mState == SHIFT_LOCK_SHIFTED;
- }
-
- public boolean isAutomaticTemporaryUpperCase() {
- return mState == AUTO_SHIFTED;
- }
-
- public boolean isManualTemporaryUpperCase() {
- return mState == MANUAL_SHIFTED || mState == SHIFT_LOCK_SHIFTED;
- }
-
- @Override
- public String toString() {
- return toString(mState);
- }
-
- private static String toString(int state) {
- switch (state) {
- case NORMAL: return "NORMAL";
- case MANUAL_SHIFTED: return "MANUAL_SHIFTED";
- case SHIFT_LOCKED: return "SHIFT_LOCKED";
- case AUTO_SHIFTED: return "AUTO_SHIFTED";
- case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED";
- default: return "UKNOWN";
- }
- }
-} \ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
deleted file mode 100644
index ac68e3c39..000000000
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2008 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboard.Key;
-import com.android.inputmethod.voice.VoiceIMEConnector;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import java.util.List;
-
-public class LatinKeyboardView extends BaseKeyboardView {
-
- public static final int KEYCODE_OPTIONS = -100;
- public static final int KEYCODE_OPTIONS_LONGPRESS = -101;
- // TODO: remove this once LatinIME stops referring to this.
- public static final int KEYCODE_VOICE = -102;
- public static final int KEYCODE_NEXT_LANGUAGE = -104;
- public static final int KEYCODE_PREV_LANGUAGE = -105;
- public static final int KEYCODE_CAPSLOCK = -106;
-
- /** Whether we've started dropping move events because we found a big jump */
- private boolean mDroppingEvents;
- /**
- * Whether multi-touch disambiguation needs to be disabled if a real multi-touch event has
- * occured
- */
- private boolean mDisableDisambiguation;
- /** The distance threshold at which we start treating the touch session as a multi-touch */
- private int mJumpThresholdSquare = Integer.MAX_VALUE;
- /** The y coordinate of the last row */
- private int mLastRowY;
-
- public LatinKeyboardView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public void setPreviewEnabled(boolean previewEnabled) {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null
- && (latinKeyboard.isPhoneKeyboard() || latinKeyboard.isNumberKeyboard())) {
- // Phone and number keyboard never shows popup preview (except language switch).
- super.setPreviewEnabled(false);
- } else {
- super.setPreviewEnabled(previewEnabled);
- }
- }
-
- public void setLatinKeyboard(LatinKeyboard k) {
- super.setKeyboard(k);
- // One-seventh of the keyboard width seems like a reasonable threshold
- mJumpThresholdSquare = k.getMinWidth() / 7;
- mJumpThresholdSquare *= mJumpThresholdSquare;
- // Assuming there are 4 rows, this is the coordinate of the last row
- mLastRowY = (k.getHeight() * 3) / 4;
- setKeyboardLocal(k);
- }
-
- public LatinKeyboard getLatinKeyboard() {
- BaseKeyboard keyboard = getKeyboard();
- if (keyboard instanceof LatinKeyboard) {
- return (LatinKeyboard)keyboard;
- } else {
- return null;
- }
- }
-
- @Override
- protected boolean onLongPress(Key key) {
- int primaryCode = key.codes[0];
- if (primaryCode == KEYCODE_OPTIONS) {
- return invokeOnKey(KEYCODE_OPTIONS_LONGPRESS);
- } else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) {
- // Long pressing on 0 in phone number keypad gives you a '+'.
- return invokeOnKey('+');
- } else {
- return super.onLongPress(key);
- }
- }
-
- private boolean invokeOnKey(int primaryCode) {
- getOnKeyboardActionListener().onKey(primaryCode, null,
- BaseKeyboardView.NOT_A_TOUCH_COORDINATE,
- BaseKeyboardView.NOT_A_TOUCH_COORDINATE);
- return true;
- }
-
- @Override
- protected CharSequence adjustCase(CharSequence label) {
- LatinKeyboard keyboard = getLatinKeyboard();
- if (keyboard.isAlphaKeyboard()
- && keyboard.isShiftedOrShiftLocked()
- && !TextUtils.isEmpty(label) && label.length() < 3
- && Character.isLowerCase(label.charAt(0))) {
- label = label.toString().toUpperCase();
- }
- return label;
- }
-
- /**
- * This function checks to see if we need to handle any sudden jumps in the pointer location
- * that could be due to a multi-touch being treated as a move by the firmware or hardware.
- * Once a sudden jump is detected, all subsequent move events are discarded
- * until an UP is received.<P>
- * When a sudden jump is detected, an UP event is simulated at the last position and when
- * the sudden moves subside, a DOWN event is simulated for the second key.
- * @param me the motion event
- * @return true if the event was consumed, so that it doesn't continue to be handled by
- * KeyboardView.
- */
- private boolean handleSuddenJump(MotionEvent me) {
- final int action = me.getAction();
- final int x = (int) me.getX();
- final int y = (int) me.getY();
- boolean result = false;
-
- // Real multi-touch event? Stop looking for sudden jumps
- if (me.getPointerCount() > 1) {
- mDisableDisambiguation = true;
- }
- if (mDisableDisambiguation) {
- // If UP, reset the multi-touch flag
- if (action == MotionEvent.ACTION_UP) mDisableDisambiguation = false;
- return false;
- }
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // Reset the "session"
- mDroppingEvents = false;
- mDisableDisambiguation = false;
- break;
- case MotionEvent.ACTION_MOVE:
- // Is this a big jump?
- final int distanceSquare = (mLastX - x) * (mLastX - x) + (mLastY - y) * (mLastY - y);
- // Check the distance and also if the move is not entirely within the bottom row
- // If it's only in the bottom row, it might be an intentional slide gesture
- // for language switching
- if (distanceSquare > mJumpThresholdSquare
- && (mLastY < mLastRowY || y < mLastRowY)) {
- // If we're not yet dropping events, start dropping and send an UP event
- if (!mDroppingEvents) {
- mDroppingEvents = true;
- // Send an up event
- MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
- MotionEvent.ACTION_UP,
- mLastX, mLastY, me.getMetaState());
- super.onTouchEvent(translated);
- translated.recycle();
- }
- result = true;
- } else if (mDroppingEvents) {
- // If moves are small and we're already dropping events, continue dropping
- result = true;
- }
- break;
- case MotionEvent.ACTION_UP:
- if (mDroppingEvents) {
- // Send a down event first, as we dropped a bunch of sudden jumps and assume that
- // the user is releasing the touch on the second key.
- MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
- MotionEvent.ACTION_DOWN,
- x, y, me.getMetaState());
- super.onTouchEvent(translated);
- translated.recycle();
- mDroppingEvents = false;
- // Let the up event get processed as well, result = false
- }
- break;
- }
- // Track the previous coordinate
- mLastX = x;
- mLastY = y;
- return result;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- LatinKeyboard keyboard = getLatinKeyboard();
- if (DEBUG_LINE) {
- mLastX = (int) me.getX();
- mLastY = (int) me.getY();
- invalidate();
- }
-
- // If there was a sudden jump, return without processing the actual motion event.
- if (handleSuddenJump(me))
- return true;
-
- // Reset any bounding box controls in the keyboard
- if (me.getAction() == MotionEvent.ACTION_DOWN) {
- keyboard.keyReleased();
- }
-
- if (me.getAction() == MotionEvent.ACTION_UP) {
- int languageDirection = keyboard.getLanguageChangeDirection();
- if (languageDirection != 0) {
- getOnKeyboardActionListener().onKey(
- languageDirection == 1 ? KEYCODE_NEXT_LANGUAGE : KEYCODE_PREV_LANGUAGE,
- null, mLastX, mLastY);
- me.setAction(MotionEvent.ACTION_CANCEL);
- keyboard.keyReleased();
- return super.onTouchEvent(me);
- }
- }
-
- return super.onTouchEvent(me);
- }
-
- /**************************** INSTRUMENTATION *******************************/
-
- static final boolean DEBUG_AUTO_PLAY = false;
- static final boolean DEBUG_LINE = false;
- private static final int MSG_TOUCH_DOWN = 1;
- private static final int MSG_TOUCH_UP = 2;
-
- Handler mHandler2;
-
- private String mStringToPlay;
- private int mStringIndex;
- private boolean mDownDelivered;
- private Key[] mAsciiKeys = new Key[256];
- private boolean mPlaying;
- private int mLastX;
- private int mLastY;
- private Paint mPaint;
-
- private void setKeyboardLocal(LatinKeyboard k) {
- if (DEBUG_AUTO_PLAY) {
- findKeys();
- if (mHandler2 == null) {
- mHandler2 = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- removeMessages(MSG_TOUCH_DOWN);
- removeMessages(MSG_TOUCH_UP);
- if (mPlaying == false) return;
-
- switch (msg.what) {
- case MSG_TOUCH_DOWN:
- if (mStringIndex >= mStringToPlay.length()) {
- mPlaying = false;
- return;
- }
- char c = mStringToPlay.charAt(mStringIndex);
- while (c > 255 || mAsciiKeys[c] == null) {
- mStringIndex++;
- if (mStringIndex >= mStringToPlay.length()) {
- mPlaying = false;
- return;
- }
- c = mStringToPlay.charAt(mStringIndex);
- }
- int x = mAsciiKeys[c].x + 10;
- int y = mAsciiKeys[c].y + 26;
- MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(),
- SystemClock.uptimeMillis(),
- MotionEvent.ACTION_DOWN, x, y, 0);
- LatinKeyboardView.this.dispatchTouchEvent(me);
- me.recycle();
- sendEmptyMessageDelayed(MSG_TOUCH_UP, 500); // Deliver up in 500ms if nothing else
- // happens
- mDownDelivered = true;
- break;
- case MSG_TOUCH_UP:
- char cUp = mStringToPlay.charAt(mStringIndex);
- int x2 = mAsciiKeys[cUp].x + 10;
- int y2 = mAsciiKeys[cUp].y + 26;
- mStringIndex++;
-
- MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(),
- SystemClock.uptimeMillis(),
- MotionEvent.ACTION_UP, x2, y2, 0);
- LatinKeyboardView.this.dispatchTouchEvent(me2);
- me2.recycle();
- sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 500); // Deliver up in 500ms if nothing else
- // happens
- mDownDelivered = false;
- break;
- }
- }
- };
-
- }
- }
- }
-
- private void findKeys() {
- List<Key> keys = getLatinKeyboard().getKeys();
- // Get the keys on this keyboard
- for (int i = 0; i < keys.size(); i++) {
- int code = keys.get(i).codes[0];
- if (code >= 0 && code <= 255) {
- mAsciiKeys[code] = keys.get(i);
- }
- }
- }
-
- public void startPlaying(String s) {
- if (DEBUG_AUTO_PLAY) {
- if (s == null) return;
- mStringToPlay = s.toLowerCase();
- mPlaying = true;
- mDownDelivered = false;
- mStringIndex = 0;
- mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 10);
- }
- }
-
- @Override
- public void draw(Canvas c) {
- LatinIMEUtil.GCUtils.getInstance().reset();
- boolean tryGC = true;
- for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
- try {
- super.draw(c);
- tryGC = false;
- } catch (OutOfMemoryError e) {
- tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e);
- }
- }
- if (DEBUG_AUTO_PLAY) {
- if (mPlaying) {
- mHandler2.removeMessages(MSG_TOUCH_DOWN);
- mHandler2.removeMessages(MSG_TOUCH_UP);
- if (mDownDelivered) {
- mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_UP, 20);
- } else {
- mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 20);
- }
- }
- }
- if (DEBUG_LINE) {
- if (mPaint == null) {
- mPaint = new Paint();
- mPaint.setColor(0x80FFFFFF);
- mPaint.setAntiAlias(false);
- }
- c.drawLine(mLastX, 0, mLastX, getHeight(), mPaint);
- c.drawLine(0, mLastY, getWidth(), mLastY, mPaint);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- // Token is available from here.
- VoiceIMEConnector.getInstance().onAttachedToWindow();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
deleted file mode 100644
index 3cc43b99c..000000000
--- a/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboard.Key;
-
-class MiniKeyboardKeyDetector extends KeyDetector {
- private static final int MAX_NEARBY_KEYS = 1;
-
- private final int mSlideAllowanceSquare;
- private final int mSlideAllowanceSquareTop;
-
- public MiniKeyboardKeyDetector(float slideAllowance) {
- super();
- mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance);
- // Top slide allowance is slightly longer (sqrt(2) times) than other edges.
- mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2;
- }
-
- @Override
- protected int getMaxNearbyKeys() {
- return MAX_NEARBY_KEYS;
- }
-
- @Override
- public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) {
- final Key[] keys = getKeys();
- final int touchX = getTouchX(x);
- final int touchY = getTouchY(y);
-
- int closestKeyIndex = BaseKeyboardView.NOT_A_KEY;
- int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
- final int keyCount = keys.length;
- for (int index = 0; index < keyCount; index++) {
- final int dist = keys[index].squaredDistanceToEdge(touchX, touchY);
- if (dist < closestKeyDist) {
- closestKeyIndex = index;
- closestKeyDist = dist;
- }
- }
-
- if (allKeys != null && closestKeyIndex != BaseKeyboardView.NOT_A_KEY)
- allKeys[0] = keys[closestKeyIndex].codes[0];
- return closestKeyIndex;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java
deleted file mode 100644
index 327fef107..000000000
--- a/java/src/com/android/inputmethod/latin/PointerTracker.java
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboard.Key;
-import com.android.inputmethod.latin.BaseKeyboardView.OnKeyboardActionListener;
-import com.android.inputmethod.latin.BaseKeyboardView.UIHandler;
-
-import android.content.res.Resources;
-import android.util.Log;
-import android.view.MotionEvent;
-
-public class PointerTracker {
- private static final String TAG = "PointerTracker";
- private static final boolean DEBUG = false;
- private static final boolean DEBUG_MOVE = false;
-
- public interface UIProxy {
- public void invalidateKey(Key key);
- public void showPreview(int keyIndex, PointerTracker tracker);
- public boolean hasDistinctMultitouch();
- }
-
- public final int mPointerId;
-
- // Timing constants
- private final int mDelayBeforeKeyRepeatStart;
- private final int mLongPressKeyTimeout;
- private final int mLongPressShiftKeyTimeout;
- private final int mMultiTapKeyTimeout;
-
- // Miscellaneous constants
- private static final int NOT_A_KEY = BaseKeyboardView.NOT_A_KEY;
- private static final int[] KEY_DELETE = { BaseKeyboard.KEYCODE_DELETE };
-
- private final UIProxy mProxy;
- private final UIHandler mHandler;
- private final KeyDetector mKeyDetector;
- private OnKeyboardActionListener mListener;
- private final boolean mHasDistinctMultitouch;
-
- private BaseKeyboard mKeyboard;
- private Key[] mKeys;
- private int mKeyHysteresisDistanceSquared = -1;
-
- private final KeyState mKeyState;
-
- // true if event is already translated to a key action (long press or mini-keyboard)
- private boolean mKeyAlreadyProcessed;
-
- // true if this pointer is repeatable key
- private boolean mIsRepeatableKey;
-
- // For multi-tap
- private int mLastSentIndex;
- private int mTapCount;
- private long mLastTapTime;
- private boolean mInMultiTap;
- private final StringBuilder mPreviewLabel = new StringBuilder(1);
-
- // pressed key
- private int mPreviousKey = NOT_A_KEY;
-
- // This class keeps track of a key index and a position where this pointer is.
- private static class KeyState {
- private final KeyDetector mKeyDetector;
-
- // The position and time at which first down event occurred.
- private int mStartX;
- private int mStartY;
- private long mDownTime;
-
- // The current key index where this pointer is.
- private int mKeyIndex = NOT_A_KEY;
- // The position where mKeyIndex was recognized for the first time.
- private int mKeyX;
- private int mKeyY;
-
- // Last pointer position.
- private int mLastX;
- private int mLastY;
-
- public KeyState(KeyDetector keyDetecor) {
- mKeyDetector = keyDetecor;
- }
-
- public int getKeyIndex() {
- return mKeyIndex;
- }
-
- public int getKeyX() {
- return mKeyX;
- }
-
- public int getKeyY() {
- return mKeyY;
- }
-
- public int getStartX() {
- return mStartX;
- }
-
- public int getStartY() {
- return mStartY;
- }
-
- public long getDownTime() {
- return mDownTime;
- }
-
- public int getLastX() {
- return mLastX;
- }
-
- public int getLastY() {
- return mLastY;
- }
-
- public int onDownKey(int x, int y, long eventTime) {
- mStartX = x;
- mStartY = y;
- mDownTime = eventTime;
-
- return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
- }
-
- private int onMoveKeyInternal(int x, int y) {
- mLastX = x;
- mLastY = y;
- return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
- }
-
- public int onMoveKey(int x, int y) {
- return onMoveKeyInternal(x, y);
- }
-
- public int onMoveToNewKey(int keyIndex, int x, int y) {
- mKeyIndex = keyIndex;
- mKeyX = x;
- mKeyY = y;
- return keyIndex;
- }
-
- public int onUpKey(int x, int y) {
- return onMoveKeyInternal(x, y);
- }
-
- public void onSetKeyboard() {
- mKeyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(mKeyX, mKeyY, null);
- }
- }
-
- public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy,
- Resources res) {
- if (proxy == null || handler == null || keyDetector == null)
- throw new NullPointerException();
- mPointerId = id;
- mProxy = proxy;
- mHandler = handler;
- mKeyDetector = keyDetector;
- mKeyState = new KeyState(keyDetector);
- mHasDistinctMultitouch = proxy.hasDistinctMultitouch();
- mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
- mLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout);
- mLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout);
- mMultiTapKeyTimeout = res.getInteger(R.integer.config_multi_tap_key_timeout);
- resetMultiTap();
- }
-
- public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
- mListener = listener;
- }
-
- public void setKeyboard(BaseKeyboard keyboard, Key[] keys, float keyHysteresisDistance) {
- if (keyboard == null || keys == null || keyHysteresisDistance < 0)
- throw new IllegalArgumentException();
- mKeyboard = keyboard;
- mKeys = keys;
- mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
- // Update current key index because keyboard layout has been changed.
- mKeyState.onSetKeyboard();
- }
-
- private boolean isValidKeyIndex(int keyIndex) {
- return keyIndex >= 0 && keyIndex < mKeys.length;
- }
-
- public Key getKey(int keyIndex) {
- return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null;
- }
-
- private boolean isModifierInternal(int keyIndex) {
- Key key = getKey(keyIndex);
- if (key == null)
- return false;
- int primaryCode = key.codes[0];
- return primaryCode == BaseKeyboard.KEYCODE_SHIFT
- || primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE;
- }
-
- public boolean isModifier() {
- return isModifierInternal(mKeyState.getKeyIndex());
- }
-
- public boolean isOnModifierKey(int x, int y) {
- return isModifierInternal(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null));
- }
-
- public boolean isSpaceKey(int keyIndex) {
- Key key = getKey(keyIndex);
- return key != null && key.codes[0] == LatinIME.KEYCODE_SPACE;
- }
-
- public void releaseKey() {
- updateKeyGraphics(NOT_A_KEY);
- }
-
- private void updateKeyGraphics(int keyIndex) {
- int oldKeyIndex = mPreviousKey;
- mPreviousKey = keyIndex;
- if (keyIndex != oldKeyIndex) {
- if (isValidKeyIndex(oldKeyIndex)) {
- // if new key index is not a key, old key was just released inside of the key.
- final boolean inside = (keyIndex == NOT_A_KEY);
- mKeys[oldKeyIndex].onReleased(inside);
- mProxy.invalidateKey(mKeys[oldKeyIndex]);
- }
- if (isValidKeyIndex(keyIndex)) {
- mKeys[keyIndex].onPressed();
- mProxy.invalidateKey(mKeys[keyIndex]);
- }
- }
- }
-
- public void setAlreadyProcessed() {
- mKeyAlreadyProcessed = true;
- }
-
- public void onTouchEvent(int action, int x, int y, long eventTime) {
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- onMoveEvent(x, y, eventTime);
- break;
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- onDownEvent(x, y, eventTime);
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- onUpEvent(x, y, eventTime);
- break;
- case MotionEvent.ACTION_CANCEL:
- onCancelEvent(x, y, eventTime);
- break;
- }
- }
-
- public void onDownEvent(int x, int y, long eventTime) {
- if (DEBUG)
- debugLog("onDownEvent:", x, y);
- int keyIndex = mKeyState.onDownKey(x, y, eventTime);
- mKeyAlreadyProcessed = false;
- mIsRepeatableKey = false;
- checkMultiTap(eventTime, keyIndex);
- if (mListener != null) {
- if (isValidKeyIndex(keyIndex)) {
- mListener.onPress(mKeys[keyIndex].codes[0]);
- // This onPress call may have changed keyboard layout and have updated mKeyIndex.
- // If that's the case, mKeyIndex has been updated in setKeyboard().
- keyIndex = mKeyState.getKeyIndex();
- }
- }
- if (isValidKeyIndex(keyIndex)) {
- if (mKeys[keyIndex].repeatable) {
- repeatKey(keyIndex);
- mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this);
- mIsRepeatableKey = true;
- }
- startLongPressTimer(keyIndex);
- }
- showKeyPreviewAndUpdateKeyGraphics(keyIndex);
- }
-
- public void onMoveEvent(int x, int y, long eventTime) {
- if (DEBUG_MOVE)
- debugLog("onMoveEvent:", x, y);
- if (mKeyAlreadyProcessed)
- return;
- KeyState keyState = mKeyState;
- final int keyIndex = keyState.onMoveKey(x, y);
- final Key oldKey = getKey(keyState.getKeyIndex());
- if (isValidKeyIndex(keyIndex)) {
- if (oldKey == null) {
- keyState.onMoveToNewKey(keyIndex, x, y);
- startLongPressTimer(keyIndex);
- } else if (!isMinorMoveBounce(x, y, keyIndex)) {
- if (mListener != null)
- mListener.onRelease(oldKey.codes[0]);
- resetMultiTap();
- keyState.onMoveToNewKey(keyIndex, x, y);
- startLongPressTimer(keyIndex);
- }
- } else {
- if (oldKey != null) {
- if (mListener != null)
- mListener.onRelease(oldKey.codes[0]);
- keyState.onMoveToNewKey(keyIndex, x ,y);
- mHandler.cancelLongPressTimers();
- } else if (!isMinorMoveBounce(x, y, keyIndex)) {
- resetMultiTap();
- keyState.onMoveToNewKey(keyIndex, x ,y);
- mHandler.cancelLongPressTimers();
- }
- }
- showKeyPreviewAndUpdateKeyGraphics(mKeyState.getKeyIndex());
- }
-
- public void onUpEvent(int x, int y, long eventTime) {
- if (DEBUG)
- debugLog("onUpEvent :", x, y);
- showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
- if (mKeyAlreadyProcessed)
- return;
- mHandler.cancelKeyTimers();
- mHandler.cancelPopupPreview();
- int keyIndex = mKeyState.onUpKey(x, y);
- if (isMinorMoveBounce(x, y, keyIndex)) {
- // Use previous fixed key index and coordinates.
- keyIndex = mKeyState.getKeyIndex();
- x = mKeyState.getKeyX();
- y = mKeyState.getKeyY();
- }
- if (!mIsRepeatableKey) {
- detectAndSendKey(keyIndex, x, y, eventTime);
- }
-
- if (isValidKeyIndex(keyIndex))
- mProxy.invalidateKey(mKeys[keyIndex]);
- }
-
- public void onCancelEvent(int x, int y, long eventTime) {
- if (DEBUG)
- debugLog("onCancelEvt:", x, y);
- mHandler.cancelKeyTimers();
- mHandler.cancelPopupPreview();
- showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
- int keyIndex = mKeyState.getKeyIndex();
- if (isValidKeyIndex(keyIndex))
- mProxy.invalidateKey(mKeys[keyIndex]);
- }
-
- public void repeatKey(int keyIndex) {
- Key key = getKey(keyIndex);
- if (key != null) {
- // While key is repeating, because there is no need to handle multi-tap key, we can
- // pass -1 as eventTime argument.
- detectAndSendKey(keyIndex, key.x, key.y, -1);
- }
- }
-
- public int getLastX() {
- return mKeyState.getLastX();
- }
-
- public int getLastY() {
- return mKeyState.getLastY();
- }
-
- public long getDownTime() {
- return mKeyState.getDownTime();
- }
-
- // These package scope methods are only for debugging purpose.
- /* package */ int getStartX() {
- return mKeyState.getStartX();
- }
-
- /* package */ int getStartY() {
- return mKeyState.getStartY();
- }
-
- private boolean isMinorMoveBounce(int x, int y, int newKey) {
- if (mKeys == null || mKeyHysteresisDistanceSquared < 0)
- throw new IllegalStateException("keyboard and/or hysteresis not set");
- int curKey = mKeyState.getKeyIndex();
- if (newKey == curKey) {
- return true;
- } else if (isValidKeyIndex(curKey)) {
- return mKeys[curKey].squaredDistanceToEdge(x, y) < mKeyHysteresisDistanceSquared;
- } else {
- return false;
- }
- }
-
- private void showKeyPreviewAndUpdateKeyGraphics(int keyIndex) {
- updateKeyGraphics(keyIndex);
- // The modifier key, such as shift key, should not be shown as preview when multi-touch is
- // supported. On the other hand, if multi-touch is not supported, the modifier key should
- // be shown as preview.
- if (mHasDistinctMultitouch && isModifier()) {
- mProxy.showPreview(NOT_A_KEY, this);
- } else {
- mProxy.showPreview(keyIndex, this);
- }
- }
-
- private void startLongPressTimer(int keyIndex) {
- Key key = getKey(keyIndex);
- if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT) {
- mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
- } else {
- mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
- }
- }
-
- private boolean isManualTemporaryUpperCase() {
- return mKeyboard instanceof LatinKeyboard
- && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase();
- }
-
- private void detectAndSendKey(int index, int x, int y, long eventTime) {
- final OnKeyboardActionListener listener = mListener;
- final Key key = getKey(index);
-
- if (key == null) {
- if (listener != null)
- listener.onCancel();
- } else {
- if (key.text != null) {
- if (listener != null) {
- listener.onText(key.text);
- listener.onRelease(NOT_A_KEY);
- }
- } else {
- int code = key.codes[0];
- //TextEntryState.keyPressedAt(key, x, y);
- int[] codes = mKeyDetector.newCodeArray();
- mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
- // Multi-tap
- if (mInMultiTap) {
- if (mTapCount != -1) {
- mListener.onKey(BaseKeyboard.KEYCODE_DELETE, KEY_DELETE, x, y);
- } else {
- mTapCount = 0;
- }
- code = key.codes[mTapCount];
- }
-
- // If keyboard is in manual temporary upper case state and key has manual temporary
- // shift code, alternate character code should be sent.
- if (isManualTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) {
- code = key.manualTemporaryUpperCaseCode;
- codes[0] = code;
- }
-
- /*
- * Swap the first and second values in the codes array if the primary code is not
- * the first value but the second value in the array. This happens when key
- * debouncing is in effect.
- */
- if (codes.length >= 2 && codes[0] != code && codes[1] == code) {
- codes[1] = codes[0];
- codes[0] = code;
- }
- if (listener != null) {
- listener.onKey(code, codes, x, y);
- listener.onRelease(code);
- }
- }
- mLastSentIndex = index;
- mLastTapTime = eventTime;
- }
- }
-
- /**
- * Handle multi-tap keys by producing the key label for the current multi-tap state.
- */
- public CharSequence getPreviewText(Key key) {
- if (mInMultiTap) {
- // Multi-tap
- mPreviewLabel.setLength(0);
- mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]);
- return mPreviewLabel;
- } else {
- return key.label;
- }
- }
-
- private void resetMultiTap() {
- mLastSentIndex = NOT_A_KEY;
- mTapCount = 0;
- mLastTapTime = -1;
- mInMultiTap = false;
- }
-
- private void checkMultiTap(long eventTime, int keyIndex) {
- Key key = getKey(keyIndex);
- if (key == null)
- return;
-
- final boolean isMultiTap =
- (eventTime < mLastTapTime + mMultiTapKeyTimeout && keyIndex == mLastSentIndex);
- if (key.codes.length > 1) {
- mInMultiTap = true;
- if (isMultiTap) {
- mTapCount = (mTapCount + 1) % key.codes.length;
- return;
- } else {
- mTapCount = -1;
- return;
- }
- }
- if (!isMultiTap) {
- resetMultiTap();
- }
- }
-
- private void debugLog(String title, int x, int y) {
- int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
- Key key = getKey(keyIndex);
- final String code;
- if (key == null) {
- code = "----";
- } else {
- int primaryCode = key.codes[0];
- code = String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode);
- }
- Log.d(TAG, String.format("%s%s[%d] %3d,%3d %3d(%s) %s", title,
- (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, keyIndex, code,
- (isModifier() ? "modifier" : "")));
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
deleted file mode 100644
index 35bdc6728..000000000
--- a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import com.android.inputmethod.latin.BaseKeyboard.Key;
-
-import java.util.Arrays;
-
-class ProximityKeyDetector extends KeyDetector {
- private static final int MAX_NEARBY_KEYS = 12;
-
- // working area
- private int[] mDistances = new int[MAX_NEARBY_KEYS];
-
- @Override
- protected int getMaxNearbyKeys() {
- return MAX_NEARBY_KEYS;
- }
-
- @Override
- public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) {
- final Key[] keys = getKeys();
- final int touchX = getTouchX(x);
- final int touchY = getTouchY(y);
-
- int primaryIndex = BaseKeyboardView.NOT_A_KEY;
- int closestKeyIndex = BaseKeyboardView.NOT_A_KEY;
- int closestKeyDist = mProximityThresholdSquare + 1;
- final int[] distances = mDistances;
- Arrays.fill(distances, Integer.MAX_VALUE);
- for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
- final Key key = keys[index];
- final boolean isInside = key.isInside(touchX, touchY);
- if (isInside)
- primaryIndex = index;
- final int dist = key.squaredDistanceToEdge(touchX, touchY);
- if (isInside || (mProximityCorrectOn && dist < mProximityThresholdSquare)) {
- if (dist < closestKeyDist) {
- closestKeyDist = dist;
- closestKeyIndex = index;
- }
-
- if (allKeys == null) continue;
- final int nCodes = key.codes.length;
- // Find insertion point
- for (int j = 0; j < distances.length; j++) {
- if (distances[j] > dist) {
- // Make space for nCodes codes
- System.arraycopy(distances, j, distances, j + nCodes,
- distances.length - (j + nCodes));
- System.arraycopy(allKeys, j, allKeys, j + nCodes,
- allKeys.length - (j + nCodes));
- System.arraycopy(key.codes, 0, allKeys, j, nCodes);
- Arrays.fill(distances, j, j + nCodes, dist);
- break;
- }
- }
- }
- }
-
- return primaryIndex == BaseKeyboardView.NOT_A_KEY ? closestKeyIndex : primaryIndex;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 103443e6d..a98917689 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.voice.SettingsUtil;
import com.android.inputmethod.voice.VoiceIMEConnector;
import com.android.inputmethod.voice.VoiceInput;
@@ -197,7 +198,7 @@ public class SubtypeSwitcher {
|| VoiceIMEConnector.getInstance().needsToShowWarningDialog()) {
if (mVoiceInput != null) {
// TODO: Call proper function to trigger VoiceIME
- mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
+ mService.onKey(LatinKeyboard.KEYCODE_VOICE, null, 0, 0);
}
}
} else {
@@ -350,7 +351,7 @@ public class SubtypeSwitcher {
if (DBG) {
Log.d(TAG, "Set and call voice input.");
}
- mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
+ mService.onKey(LatinKeyboard.KEYCODE_VOICE, null, 0, 0);
return true;
}
}
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index ca2ffe13a..4c9b7509a 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -423,6 +423,7 @@ public class Suggest implements Dictionary.WordCallback {
return false;
}
+ @Override
public boolean addWord(final char[] word, final int offset, final int length, int freq,
final int dicTypeId, final Dictionary.DataType dataType) {
Dictionary.DataType dataTypeForLog = dataType;
diff --git a/java/src/com/android/inputmethod/latin/SwipeTracker.java b/java/src/com/android/inputmethod/latin/SwipeTracker.java
deleted file mode 100644
index 970e91965..000000000
--- a/java/src/com/android/inputmethod/latin/SwipeTracker.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.latin;
-
-import android.view.MotionEvent;
-
-class SwipeTracker {
- private static final int NUM_PAST = 4;
- private static final int LONGEST_PAST_TIME = 200;
-
- final EventRingBuffer mBuffer = new EventRingBuffer(NUM_PAST);
-
- private float mYVelocity;
- private float mXVelocity;
-
- public void addMovement(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mBuffer.clear();
- return;
- }
- long time = ev.getEventTime();
- final int count = ev.getHistorySize();
- for (int i = 0; i < count; i++) {
- addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i), ev.getHistoricalEventTime(i));
- }
- addPoint(ev.getX(), ev.getY(), time);
- }
-
- private void addPoint(float x, float y, long time) {
- final EventRingBuffer buffer = mBuffer;
- while (buffer.size() > 0) {
- long lastT = buffer.getTime(0);
- if (lastT >= time - LONGEST_PAST_TIME)
- break;
- buffer.dropOldest();
- }
- buffer.add(x, y, time);
- }
-
- public void computeCurrentVelocity(int units) {
- computeCurrentVelocity(units, Float.MAX_VALUE);
- }
-
- public void computeCurrentVelocity(int units, float maxVelocity) {
- final EventRingBuffer buffer = mBuffer;
- final float oldestX = buffer.getX(0);
- final float oldestY = buffer.getY(0);
- final long oldestTime = buffer.getTime(0);
-
- float accumX = 0;
- float accumY = 0;
- final int count = buffer.size();
- for (int pos = 1; pos < count; pos++) {
- final int dur = (int)(buffer.getTime(pos) - oldestTime);
- if (dur == 0) continue;
- float dist = buffer.getX(pos) - oldestX;
- float vel = (dist / dur) * units; // pixels/frame.
- if (accumX == 0) accumX = vel;
- else accumX = (accumX + vel) * .5f;
-
- dist = buffer.getY(pos) - oldestY;
- vel = (dist / dur) * units; // pixels/frame.
- if (accumY == 0) accumY = vel;
- else accumY = (accumY + vel) * .5f;
- }
- mXVelocity = accumX < 0.0f ? Math.max(accumX, -maxVelocity)
- : Math.min(accumX, maxVelocity);
- mYVelocity = accumY < 0.0f ? Math.max(accumY, -maxVelocity)
- : Math.min(accumY, maxVelocity);
- }
-
- public float getXVelocity() {
- return mXVelocity;
- }
-
- public float getYVelocity() {
- return mYVelocity;
- }
-
- static class EventRingBuffer {
- private final int bufSize;
- private final float xBuf[];
- private final float yBuf[];
- private final long timeBuf[];
- private int top; // points new event
- private int end; // points oldest event
- private int count; // the number of valid data
-
- public EventRingBuffer(int max) {
- this.bufSize = max;
- xBuf = new float[max];
- yBuf = new float[max];
- timeBuf = new long[max];
- clear();
- }
-
- public void clear() {
- top = end = count = 0;
- }
-
- public int size() {
- return count;
- }
-
- // Position 0 points oldest event
- private int index(int pos) {
- return (end + pos) % bufSize;
- }
-
- private int advance(int index) {
- return (index + 1) % bufSize;
- }
-
- public void add(float x, float y, long time) {
- xBuf[top] = x;
- yBuf[top] = y;
- timeBuf[top] = time;
- top = advance(top);
- if (count < bufSize) {
- count++;
- } else {
- end = advance(end);
- }
- }
-
- public float getX(int pos) {
- return xBuf[index(pos)];
- }
-
- public float getY(int pos) {
- return yBuf[index(pos)];
- }
-
- public long getTime(int pos) {
- return timeBuf[index(pos)];
- }
-
- public void dropOldest() {
- count--;
- end = advance(end);
- }
- }
-} \ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
index 56347af5d..31a192bfe 100644
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ b/java/src/com/android/inputmethod/latin/TextEntryState.java
@@ -16,7 +16,7 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.latin.BaseKeyboard.Key;
+import com.android.inputmethod.keyboard.Key;
import android.content.Context;
import android.text.format.DateFormat;
diff --git a/java/src/com/android/inputmethod/latin/Tutorial.java b/java/src/com/android/inputmethod/latin/Tutorial.java
index cd7636f3c..bd069bd0d 100644
--- a/java/src/com/android/inputmethod/latin/Tutorial.java
+++ b/java/src/com/android/inputmethod/latin/Tutorial.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.LatinKeyboardView;
+
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -133,6 +135,7 @@ public class Tutorial implements OnTouchListener {
if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) offy -= window.getHeight();
if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) offx -= window.getWidth();
textView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
public boolean onTouch(View view, MotionEvent me) {
Tutorial.this.next();
return true;
@@ -237,6 +240,7 @@ public class Tutorial implements OnTouchListener {
return true;
}
+ @Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
next();
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
index 49b95e9aa..a522303e6 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -97,6 +97,7 @@ public class UserDictionary extends ExpandableDictionary {
final ContentResolver contentResolver = getContext().getContentResolver();
new Thread("addWord") {
+ @Override
public void run() {
contentResolver.insert(Words.CONTENT_URI, values);
}