aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java62
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java14
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java31
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboard.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java24
-rw-r--r--java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java151
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java41
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java82
-rw-r--r--java/src/com/android/inputmethod/latin/MoreSuggestions.java7
-rw-r--r--java/src/com/android/inputmethod/latin/MoreSuggestionsView.java10
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java3
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestionsView.java149
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java37
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java9
17 files changed, 381 insertions, 253 deletions
diff --git a/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java b/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java
index a6304d877..2fb8b8710 100644
--- a/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java
@@ -44,4 +44,8 @@ public class VibratorCompatWrapper {
return false;
return (Boolean) CompatUtils.invoke(mVibrator, true, METHOD_hasVibrator);
}
+
+ public void vibrate(long milliseconds) {
+ mVibrator.vibrate(milliseconds);
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 7ae3467f9..b1cc7cafb 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -120,11 +120,6 @@ public class Key {
/** Whether this key needs to show the "..." popup hint for special purposes */
private boolean mNeedsSpecialPopupHint;
- // keyWidth enum constants
- private static final int KEYWIDTH_NOT_ENUM = 0;
- private static final int KEYWIDTH_FILL_RIGHT = -1;
- private static final int KEYWIDTH_FILL_BOTH = -2;
-
// RTL parenthesis character swapping map.
private static final Map<Integer, Integer> sRtlParenthesisMap = new HashMap<Integer, Integer>();
@@ -216,20 +211,9 @@ public class Key {
*/
public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
XmlResourceParser parser, KeyStyles keyStyles) {
- final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- mHeight = (int)KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_rowHeight, params.mHeight, row.mRowHeight)
- - params.mVerticalGap;
- final float horizontalGap = isSpacer() ? 0
- : KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_horizontalGap, params.mWidth, params.mHorizontalGap);
+ final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
mVerticalGap = params.mVerticalGap;
- final int widthType = KeyboardBuilder.getEnumValue(keyboardAttr,
- R.styleable.Keyboard_keyWidth, KEYWIDTH_NOT_ENUM);
- float keyWidth = KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyWidth, params.mWidth, row.mDefaultKeyWidth);
- keyboardAttr.recycle();
+ mHeight = row.mRowHeight - mVerticalGap;
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_Key);
@@ -244,38 +228,16 @@ public class Key {
style = keyStyles.getEmptyKeyStyle();
}
- final int keyboardWidth = params.mOccupiedWidth;
- final float x = row.mCurrentX;
- float keyXPos = KeyboardBuilder.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyXPos, keyboardWidth, x);
- if (keyXPos < 0) {
- // If keyXPos is negative, the actual x-coordinate will be keyboardWidth + keyXPos.
- keyXPos += keyboardWidth;
- if (keyXPos < x) {
- // keyXPos shouldn't be less than x because drawable area for this key starts
- // at x. Or, this key will overlaps the adjacent key on its left hand side.
- keyXPos = x;
- }
- }
- if (widthType == KEYWIDTH_FILL_RIGHT) {
- // If keyWidth is zero, the actual key width will be determined to fill out the
- // area up to the right edge of the keyboard.
- keyWidth = keyboardWidth - keyXPos;
- } else if (widthType == KEYWIDTH_FILL_BOTH) {
- // If keyWidth is negative, the actual key width will be determined to fill out the
- // area between the nearest key on the left hand side and the right edge of the
- // keyboard.
- keyXPos = x;
- keyWidth = keyboardWidth - keyXPos;
- }
+ final float keyXPos = row.getKeyX(keyAttr);
+ final float keyWidth = row.getKeyWidth(keyAttr, keyXPos);
// Horizontal gap is divided equally to both sides of the key.
mX = (int) (keyXPos + horizontalGap / 2);
- mY = row.mCurrentY;
+ mY = row.getKeyY();
mWidth = (int) (keyWidth - horizontalGap);
mHorizontalGap = (int) horizontalGap;
// Update row to have current x coordinate.
- row.mCurrentX = keyXPos + keyWidth;
+ row.setXPos(keyXPos + keyWidth);
final CharSequence[] moreKeys = style.getTextArray(keyAttr,
R.styleable.Keyboard_Key_moreKeys);
@@ -287,20 +249,20 @@ public class Key {
} else {
mMoreKeys = moreKeys;
}
- mMaxMoreKeysColumn = style.getInt(keyboardAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn,
- params.mMaxMiniKeyboardColumn);
+ mMaxMoreKeysColumn = style.getInt(keyAttr,
+ R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMiniKeyboardColumn);
- mBackgroundType = style.getInt(
- keyAttr, R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL);
+ mBackgroundType = style.getInt(keyAttr,
+ R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL);
mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
mEdgeFlags = 0;
final KeyboardIconsSet iconsSet = params.mIconsSet;
mVisualInsetsLeft = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_visualInsetsLeft, keyboardWidth, 0);
+ R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0);
mVisualInsetsRight = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_visualInsetsRight, keyboardWidth, 0);
+ R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0);
mPreviewIcon = iconsSet.getIcon(style.getInt(keyAttr,
R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED));
mIcon = iconsSet.getIcon(style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIcon,
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 3a8a1d4b8..2f11164f9 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -90,15 +90,12 @@ public class Keyboard {
/** Total width of the keyboard, including the padding and keys */
public final int mOccupiedWidth;
- public final int mHeight;
- public final int mWidth;
-
- /** Default row height */
- public final int mDefaultRowHeight;
-
+ /** The padding above the keyboard */
+ public final int mTopPadding;
/** Default gap between rows */
public final int mVerticalGap;
+ public final int mMostCommonKeyHeight;
public final int mMostCommonKeyWidth;
/** More keys keyboard template */
@@ -126,14 +123,13 @@ public class Keyboard {
mId = params.mId;
mOccupiedHeight = params.mOccupiedHeight;
mOccupiedWidth = params.mOccupiedWidth;
- mHeight = params.mHeight;
- mWidth = params.mWidth;
+ mMostCommonKeyHeight = params.mMostCommonKeyHeight;
mMostCommonKeyWidth = params.mMostCommonKeyWidth;
mIsRtlKeyboard = params.mIsRtlKeyboard;
mMoreKeysTemplate = params.mMoreKeysTemplate;
mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn;
- mDefaultRowHeight = params.mDefaultRowHeight;
+ mTopPadding = params.mTopPadding;
mVerticalGap = params.mVerticalGap;
mKeys = Collections.unmodifiableList(params.mKeys);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index e43ae55a8..2d123699e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -48,7 +49,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
public static final boolean DEBUG_STATE = false;
- public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
+ public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916";
private static final int[] KEYBOARD_THEMES = {
R.style.KeyboardTheme,
R.style.KeyboardTheme_HighContrast,
@@ -97,6 +98,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final int SWITCH_STATE_CHORDING_SYMBOL = 6;
private int mSwitchState = SWITCH_STATE_ALPHA;
+ private static String mLayoutSwitchBackSymbols;
+
private int mThemeIndex = -1;
private Context mThemeContext;
@@ -204,6 +207,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
+ mLayoutSwitchBackSymbols = mResources.getString(R.string.layout_switch_back_symbols);
setKeyboard(getKeyboard(mSavedKeyboardState.getKeyboardId()));
} catch (RuntimeException e) {
Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
@@ -661,24 +665,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER;
}
- private static boolean isQuoteCharacter(int c) {
- // Apostrophe, quotation mark.
- if (c == Keyboard.CODE_SINGLE_QUOTE || c == Keyboard.CODE_DOUBLE_QUOTE)
- return true;
- // \u2018: Left single quotation mark
- // \u2019: Right single quotation mark
- // \u201a: Single low-9 quotation mark
- // \u201b: Single high-reversed-9 quotation mark
- // \u201c: Left double quotation mark
- // \u201d: Right double quotation mark
- // \u201e: Double low-9 quotation mark
- // \u201f: Double high-reversed-9 quotation mark
- if (c >= '\u2018' && c <= '\u201f')
- return true;
- // \u00ab: Left-pointing double angle quotation mark
- // \u00bb: Right-pointing double angle quotation mark
- if (c == '\u00ab' || c == '\u00bb')
- return true;
+ private static boolean isLayoutSwitchBackCharacter(int c) {
+ if (TextUtils.isEmpty(mLayoutSwitchBackSymbols)) return false;
+ if (mLayoutSwitchBackSymbols.indexOf(c) >= 0) return true;
return false;
}
@@ -736,7 +725,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mSwitchState = SWITCH_STATE_SYMBOL;
}
// Snap back to alpha keyboard mode immediately if user types a quote character.
- if (isQuoteCharacter(code)) {
+ if (isLayoutSwitchBackCharacter(code)) {
changeKeyboardMode();
}
break;
@@ -744,7 +733,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
case SWITCH_STATE_CHORDING_SYMBOL:
// Snap back to alpha keyboard mode if user types one or more non-space/enter
// characters followed by a space/enter or a quote character.
- if (isSpaceCharacter(code) || isQuoteCharacter(code)) {
+ if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) {
changeKeyboardMode();
}
break;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 5a44460a1..c94ffd940 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -391,7 +391,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
mDirtyRect.set(0, 0, getWidth(), getHeight());
mBufferNeedsUpdate = true;
invalidateAllKeys();
- final int keyHeight = keyboard.mDefaultRowHeight - keyboard.mVerticalGap;
+ final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
mKeyDrawParams.updateKeyHeight(keyHeight);
mKeyPreviewDrawParams.updateKeyHeight(keyHeight);
}
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index ad8056cc0..c90439474 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -122,9 +122,9 @@ public class MiniKeyboard extends Keyboard {
mTopRowAdjustment = -1;
}
- mWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth;
+ mBaseWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth;
// Need to subtract the bottom row's gutter only.
- mHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap
+ mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap
+ mTopPadding + mBottomPadding;
}
@@ -219,7 +219,7 @@ public class MiniKeyboard extends Keyboard {
final int keyWidth = getMaxKeyWidth(view, mMoreKeys, mParams.mDefaultKeyWidth);
mParams.setParameters(mMoreKeys.length, parentKey.mMaxMoreKeysColumn,
- keyWidth, parentKeyboard.mDefaultRowHeight, parentKey.mX
+ keyWidth, parentKeyboard.mMostCommonKeyHeight, parentKey.mX
+ (mParams.mDefaultKeyWidth - keyWidth) / 2, view.getMeasuredWidth());
}
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index a82bcbed0..0e2d28024 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -65,7 +65,8 @@ public class ProximityInfo {
spellCheckerProximityInfo.mNativeProximityInfo =
spellCheckerProximityInfo.setProximityInfoNative(
SpellCheckerProximityInfo.ROW_SIZE,
- 480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY);
+ 480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY,
+ 0, null, null, null, null, null);
return spellCheckerProximityInfo;
}
@@ -74,7 +75,9 @@ public class ProximityInfo {
Utils.loadNativeLibrary();
}
private native int setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
- int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray);
+ int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray,
+ int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
+ int[] keyWidths, int[] keyHeights, int[] keyCharCodes);
private native void releaseProximityInfoNative(int nativeProximityInfo);
private final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
@@ -88,8 +91,23 @@ public class ProximityInfo {
keys.get(gridNeighborKeyIndexes[i][j]).mCode;
}
}
+ final int keyCount = keys.size();
+ int[] keyXCoordinates = new int[keyCount];
+ int[] keyYCoordinates = new int[keyCount];
+ int[] keyWidths = new int[keyCount];
+ int[] keyHeights = new int[keyCount];
+ int[] keyCharCodes = new int[keyCount];
+ for (int i = 0; i < keyCount; ++i) {
+ final Key key = keys.get(i);
+ keyXCoordinates[i] = key.mX;
+ keyYCoordinates[i] = key.mY;
+ keyWidths[i] = key.mWidth;
+ keyHeights[i] = key.mHeight;
+ keyCharCodes[i] = key.mCode;
+ }
mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE,
- keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray);
+ keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray,
+ keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes);
}
public int getNativeProximityInfo() {
diff --git a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java
index c4251ccfc..62a9259f9 100644
--- a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java
+++ b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java
@@ -51,7 +51,7 @@ public class SuddenJumpingTouchEventHandler {
mView = view;
final String[] deviceList = context.getResources().getStringArray(
R.array.sudden_jumping_touch_event_device_list);
- mNeedsSuddenJumpingHack = needsSuddenJumpingHack(Build.DEVICE, deviceList);
+ mNeedsSuddenJumpingHack = needsSuddenJumpingHack(Build.HARDWARE, deviceList);
}
private static boolean needsSuddenJumpingHack(String deviceName, String[] deviceList) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index e39548e9c..99b917c86 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -123,6 +123,9 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
private static final String TAG_DEFAULT = "default";
public static final String TAG_KEY_STYLE = "key-style";
+ private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
+ private static final int DEFAULT_KEYBOARD_ROWS = 4;
+
protected final KP mParams;
protected final Context mContext;
protected final Resources mResources;
@@ -141,29 +144,96 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
* defines.
*/
public static class Row {
+ // keyWidth enum constants
+ private static final int KEYWIDTH_NOT_ENUM = 0;
+ private static final int KEYWIDTH_FILL_RIGHT = -1;
+ private static final int KEYWIDTH_FILL_BOTH = -2;
+
+ private final KeyboardParams mParams;
/** Default width of a key in this row. */
public final float mDefaultKeyWidth;
/** Default height of a key in this row. */
public final int mRowHeight;
- public final int mCurrentY;
+ private final int mCurrentY;
// Will be updated by {@link Key}'s constructor.
- public float mCurrentX;
+ private float mCurrentX;
public Row(Resources res, KeyboardParams params, XmlResourceParser parser, int y) {
- final int keyboardWidth = params.mWidth;
- final int keyboardHeight = params.mHeight;
- TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
+ mParams = params;
+ TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard);
- mDefaultKeyWidth = KeyboardBuilder.getDimensionOrFraction(a,
- R.styleable.Keyboard_keyWidth, keyboardWidth, params.mDefaultKeyWidth);
- mRowHeight = (int)KeyboardBuilder.getDimensionOrFraction(a,
- R.styleable.Keyboard_rowHeight, keyboardHeight, params.mDefaultRowHeight);
- a.recycle();
+ mRowHeight = (int)KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_rowHeight, params.mBaseHeight, params.mDefaultRowHeight);
+ keyboardAttr.recycle();
+ TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ mDefaultKeyWidth = KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth, params.mDefaultKeyWidth);
+ keyAttr.recycle();
mCurrentY = y;
mCurrentX = 0.0f;
}
+
+ public void setXPos(float keyXPos) {
+ mCurrentX = keyXPos;
+ }
+
+ public void advanceXPos(float width) {
+ mCurrentX += width;
+ }
+
+ public int getKeyY() {
+ return mCurrentY;
+ }
+
+ public float getKeyX(TypedArray keyAttr) {
+ final int widthType = KeyboardBuilder.getEnumValue(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
+ if (widthType == KEYWIDTH_FILL_BOTH) {
+ // If keyWidth is fillBoth, the key width should start right after the nearest key
+ // on the left hand side.
+ return mCurrentX;
+ }
+
+ final int keyboardRightEdge = mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding;
+ if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) {
+ final float keyXPos = KeyboardBuilder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyXPos, mParams.mBaseWidth, 0);
+ if (keyXPos < 0) {
+ // If keyXPos is negative, the actual x-coordinate will be
+ // keyboardWidth + keyXPos.
+ // keyXPos shouldn't be less than mCurrentX because drawable area for this key
+ // starts at mCurrentX. Or, this key will overlaps the adjacent key on its left
+ // hand side.
+ return Math.max(keyXPos + keyboardRightEdge, mCurrentX);
+ } else {
+ return keyXPos + mParams.mHorizontalEdgesPadding;
+ }
+ }
+ return mCurrentX;
+ }
+
+ public float getKeyWidth(TypedArray keyAttr, float keyXPos) {
+ final int widthType = KeyboardBuilder.getEnumValue(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
+ switch (widthType) {
+ case KEYWIDTH_FILL_RIGHT:
+ case KEYWIDTH_FILL_BOTH:
+ final int keyboardRightEdge =
+ mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding;
+ // If keyWidth is fillRight, the actual key width will be determined to fill out the
+ // area up to the right edge of the keyboard.
+ // If keyWidth is fillBoth, the actual key width will be determined to fill out the
+ // area between the nearest key on the left hand side and the right edge of the
+ // keyboard.
+ return keyboardRightEdge - keyXPos;
+ default: // KEYWIDTH_NOT_ENUM
+ return KeyboardBuilder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, mParams.mBaseWidth, mDefaultKeyWidth);
+ }
+ }
}
public KeyboardBuilder(Context context, KP params) {
@@ -173,8 +243,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
mDisplayMetrics = res.getDisplayMetrics();
mParams = params;
- mParams.mHorizontalEdgesPadding = (int)res.getDimension(
- R.dimen.keyboard_horizontal_edges_padding);
mParams.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
mParams.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
@@ -259,38 +327,42 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2);
}
+ final KeyboardParams params = mParams;
// Keyboard height will not exceed maxKeyboardHeight and will not be less than
// minKeyboardHeight.
- mParams.mOccupiedHeight = Math.max(
+ params.mOccupiedHeight = Math.max(
Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight);
- mParams.mOccupiedWidth = mParams.mId.mWidth;
- mParams.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyboardTopPadding, mParams.mOccupiedHeight, 0);
- mParams.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyboardBottomPadding, mParams.mOccupiedHeight, 0);
-
- final int height = mParams.mOccupiedHeight;
- final int width = mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding * 2
- - mParams.mHorizontalCenterPadding;
- mParams.mHeight = height;
- mParams.mWidth = width;
- mParams.mDefaultKeyWidth = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyWidth, width, width / 10);
- mParams.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_rowHeight, height, height / 4);
- mParams.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_horizontalGap, width, 0);
- mParams.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_verticalGap, height, 0);
-
- mParams.mIsRtlKeyboard = keyboardAttr.getBoolean(
+ params.mOccupiedWidth = params.mId.mWidth;
+ params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardTopPadding, params.mOccupiedHeight, 0);
+ params.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardBottomPadding, params.mOccupiedHeight, 0);
+ params.mHorizontalEdgesPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardHorizontalEdgesPadding, mParams.mOccupiedWidth, 0);
+
+ params.mBaseWidth = params.mOccupiedWidth - params.mHorizontalEdgesPadding * 2
+ - params.mHorizontalCenterPadding;
+ params.mDefaultKeyWidth = (int)getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth,
+ params.mBaseWidth / DEFAULT_KEYBOARD_COLUMNS);
+ params.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_horizontalGap, params.mBaseWidth, 0);
+ params.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_verticalGap, params.mOccupiedHeight, 0);
+ params.mBaseHeight = params.mOccupiedHeight - params.mTopPadding
+ - params.mBottomPadding + params.mVerticalGap;
+ params.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_rowHeight, params.mBaseHeight,
+ params.mBaseHeight / DEFAULT_KEYBOARD_ROWS);
+
+ params.mIsRtlKeyboard = keyboardAttr.getBoolean(
R.styleable.Keyboard_isRtlKeyboard, false);
- mParams.mMoreKeysTemplate = keyboardAttr.getResourceId(
+ params.mMoreKeysTemplate = keyboardAttr.getResourceId(
R.styleable.Keyboard_moreKeysTemplate, 0);
- mParams.mMaxMiniKeyboardColumn = keyAttr.getInt(
+ params.mMaxMiniKeyboardColumn = keyAttr.getInt(
R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
- mParams.mIconsSet.loadIcons(keyboardAttr);
+ params.mIconsSet.loadIcons(keyboardAttr);
} finally {
keyAttr.recycle();
keyboardAttr.recycle();
@@ -667,7 +739,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
private void startRow(Row row) {
- row.mCurrentX = 0;
addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
mCurrentRow = row;
mLeftEdge = true;
@@ -682,7 +753,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
mRightEdgeKey = null;
}
addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
- mCurrentY += mCurrentRow.mRowHeight;
+ mCurrentY += row.mRowHeight;
mCurrentRow = null;
mTopEdge = false;
}
@@ -703,7 +774,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
private void addEdgeSpace(float width, Row row) {
- row.mCurrentX += width;
+ row.advanceXPos(width);
mLeftEdge = false;
mRightEdgeKey = null;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
index 593c3dc5b..01f9d3bb1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
@@ -32,11 +32,13 @@ import java.util.Set;
public class KeyboardParams {
public KeyboardId mId;
+ /** Total height and width of the keyboard, including the paddings and keys */
public int mOccupiedHeight;
public int mOccupiedWidth;
- public int mHeight;
- public int mWidth;
+ /** Base height and width of the keyboard used to calculate rows' or keys' heights and widths */
+ public int mBaseHeight;
+ public int mBaseWidth;
public int mTopPadding;
public int mBottomPadding;
@@ -62,6 +64,7 @@ public class KeyboardParams {
public final Map<Key, Drawable> mUnshiftedIcons = new HashMap<Key, Drawable>();
public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
+ public int mMostCommonKeyHeight = 0;
public int mMostCommonKeyWidth = 0;
protected void clearKeys() {
@@ -89,21 +92,39 @@ public class KeyboardParams {
mShiftedIcons.put(key, icon);
}
- private int mMaxCount = 0;
- private final Map<Integer, Integer> mHistogram = new HashMap<Integer, Integer>();
+ private int mMaxHeightCount = 0;
+ private int mMaxWidthCount = 0;
+ private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
+ private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
private void clearHistogram() {
+ mMostCommonKeyHeight = 0;
+ mMaxHeightCount = 0;
+ mHeightHistogram.clear();
+
+ mMaxWidthCount = 0;
mMostCommonKeyWidth = 0;
- mMaxCount = 0;
- mHistogram.clear();
+ mWidthHistogram.clear();
+ }
+
+ private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) {
+ final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
+ histogram.put(key, count);
+ return count;
}
private void updateHistogram(Key key) {
+ final Integer height = key.mHeight + key.mVerticalGap;
+ final int heightCount = updateHistogramCounter(mHeightHistogram, height);
+ if (heightCount > mMaxHeightCount) {
+ mMaxHeightCount = heightCount;
+ mMostCommonKeyHeight = height;
+ }
+
final Integer width = key.mWidth + key.mHorizontalGap;
- final int count = (mHistogram.containsKey(width) ? mHistogram.get(width) : 0) + 1;
- mHistogram.put(width, count);
- if (count > mMaxCount) {
- mMaxCount = count;
+ final int widthCount = updateHistogramCounter(mWidthHistogram, width);
+ if (widthCount > mMaxWidthCount) {
+ mMaxWidthCount = widthCount;
mMostCommonKeyWidth = width;
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index ff0226684..ddda184aa 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -28,6 +28,7 @@ import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.net.ConnectivityManager;
+import android.os.Build;
import android.os.Debug;
import android.os.Message;
import android.os.SystemClock;
@@ -56,6 +57,7 @@ import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
import com.android.inputmethod.compat.InputTypeCompatUtils;
import com.android.inputmethod.compat.SuggestionSpanUtils;
+import com.android.inputmethod.compat.VibratorCompatWrapper;
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.deprecated.recorrection.Recorrection;
@@ -207,9 +209,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private long mLastKeyTime;
private AudioManager mAudioManager;
- private static float mFxVolume = -1.0f; // just a default value to be updated runtime
+ private float mFxVolume = -1.0f; // default volume
private boolean mSilentModeOn; // System-wide current configuration
+ private VibratorCompatWrapper mVibrator;
+ private long mKeypressVibrationDuration = -1;
+
// TODO: Move this flag to VoiceProxy
private boolean mConfigurationChanging;
@@ -433,13 +438,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
mRecorrection = Recorrection.getInstance();
+ mVibrator = VibratorCompatWrapper.getInstance(this);
DEBUG = LatinImeLogger.sDBG;
- loadSettings();
-
final Resources res = getResources();
mResources = res;
+ loadSettings();
+
Utils.GCUtils.getInstance().reset();
boolean tryGC = true;
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
@@ -480,6 +486,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr());
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
updateSoundEffectVolume();
+ updateKeypressVibrationDuration();
}
private void initSuggest() {
@@ -611,6 +618,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view);
if (mSuggestionsView != null)
mSuggestionsView.setListener(this, view);
+ if (LatinImeLogger.sVISUALDEBUG) {
+ mKeyPreviewBackingView.setBackgroundColor(0x10FF0000);
+ }
}
@Override
@@ -1496,8 +1506,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) {
InputConnectionCompatUtils.commitCorrection(
ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord);
- if (mSuggestionsView != null)
- mSuggestionsView.onAutoCorrectionInverted(mBestWord);
}
}
if (Keyboard.CODE_SPACE == primaryCode) {
@@ -2052,13 +2060,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// update sound effect volume
private void updateSoundEffectVolume() {
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- if (mAudioManager == null) return;
+ final String[] volumePerHardwareList = mResources.getStringArray(R.array.keypress_volumes);
+ final String hardwarePrefix = Build.HARDWARE + ",";
+ for (final String element : volumePerHardwareList) {
+ if (element.startsWith(hardwarePrefix)) {
+ mFxVolume = Float.parseFloat(element.substring(element.lastIndexOf(',') + 1));
+ break;
+ }
}
- // This aligns with the current media volume minus 6dB
- mFxVolume = (float) mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
- / (float) mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) / 4.0f;
}
// update flags for silent mode
@@ -2070,6 +2079,19 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL);
}
+ private void updateKeypressVibrationDuration() {
+ final String[] durationPerHardwareList = mResources.getStringArray(
+ R.array.keypress_vibration_durations);
+ final String hardwarePrefix = Build.HARDWARE + ",";
+ for (final String element : durationPerHardwareList) {
+ if (element.startsWith(hardwarePrefix)) {
+ mKeypressVibrationDuration =
+ Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
+ break;
+ }
+ }
+ }
+
private void playKeyClick(int primaryCode) {
// if mAudioManager is null, we don't have the ringer state yet
// mAudioManager will be set by updateRingerMode
@@ -2079,17 +2101,20 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
if (isSoundOn()) {
- int sound = AudioManager.FX_KEYPRESS_STANDARD;
+ final int sound;
switch (primaryCode) {
- case Keyboard.CODE_DELETE:
- sound = AudioManager.FX_KEYPRESS_DELETE;
- break;
- case Keyboard.CODE_ENTER:
- sound = AudioManager.FX_KEYPRESS_RETURN;
- break;
- case Keyboard.CODE_SPACE:
- sound = AudioManager.FX_KEYPRESS_SPACEBAR;
- break;
+ case Keyboard.CODE_DELETE:
+ sound = AudioManager.FX_KEYPRESS_DELETE;
+ break;
+ case Keyboard.CODE_ENTER:
+ sound = AudioManager.FX_KEYPRESS_RETURN;
+ break;
+ case Keyboard.CODE_SPACE:
+ sound = AudioManager.FX_KEYPRESS_SPACEBAR;
+ break;
+ default:
+ sound = AudioManager.FX_KEYPRESS_STANDARD;
+ break;
}
mAudioManager.playSoundEffect(sound, mFxVolume);
}
@@ -2099,11 +2124,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (!mSettingsValues.mVibrateOn) {
return;
}
- LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
- if (inputView != null) {
- inputView.performHapticFeedback(
- HapticFeedbackConstants.KEYBOARD_TAP,
- HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
+ if (mKeypressVibrationDuration < 0) {
+ // Go ahead with the system default
+ LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
+ if (inputView != null) {
+ inputView.performHapticFeedback(
+ HapticFeedbackConstants.KEYBOARD_TAP,
+ HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
+ }
+ } else if (mVibrator != null) {
+ mVibrator.vibrate(mKeypressVibrationDuration);
}
}
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
index 24011c41e..1afa07214 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
@@ -92,8 +92,9 @@ public class MoreSuggestions extends Keyboard {
}
mNumColumnsInRow[row] = pos - rowStartPos;
mNumRows = row + 1;
- mWidth = mOccupiedWidth = Math.max(minWidth, calcurateMaxRowWidth(fromPos, pos));
- mHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap;
+ mBaseWidth = mOccupiedWidth = Math.max(
+ minWidth, calcurateMaxRowWidth(fromPos, pos));
+ mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap;
return pos - fromPos;
}
@@ -149,7 +150,7 @@ public class MoreSuggestions extends Keyboard {
public int getWidth(int pos) {
final int numColumnInRow = getNumColumnInRow(pos);
- return (mWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
+ return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
}
public int getFlags(int pos) {
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java
index 15a0cec2e..5a2eb1632 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java
@@ -145,13 +145,6 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
// Nothing to do with.
}
- private final View.OnTouchListener mMotionEventDelegate = new View.OnTouchListener() {
- @Override
- public boolean onTouch(View view, MotionEvent me) {
- return MoreSuggestionsView.this.dispatchTouchEvent(me);
- }
- };
-
@Override
public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
PopupWindow window, KeyboardActionListener listener) {
@@ -170,9 +163,7 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
- (container.getMeasuredHeight() - container.getPaddingBottom())
+ parentView.getPaddingTop() + mCoordinates[1];
- container.setOnTouchListener(mMotionEventDelegate);
window.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
- window.setFocusable(true);
window.setOutsideTouchable(true);
window.setContentView(container);
window.setWidth(container.getMeasuredWidth());
@@ -193,6 +184,7 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
@Override
public boolean dismissMoreKeysPanel() {
+ if (mController == null) return false;
return mController.dismissMoreKeysPanel();
}
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index c97f56712..d706cd0a4 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -171,7 +171,8 @@ public class Settings extends InputMethodSettingsActivity
// Get the settings preferences
final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator();
- mVibrateOn = hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON, false);
+ mVibrateOn = hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
+ res.getBoolean(R.bool.config_default_vibration_enabled));
mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
res.getBoolean(R.bool.config_default_sound_enabled));
mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
diff --git a/java/src/com/android/inputmethod/latin/SuggestionsView.java b/java/src/com/android/inputmethod/latin/SuggestionsView.java
index 13beb4479..196148731 100644
--- a/java/src/com/android/inputmethod/latin/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/SuggestionsView.java
@@ -19,8 +19,14 @@ package com.android.inputmethod.latin;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Rect;
import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Message;
import android.os.SystemClock;
@@ -29,12 +35,11 @@ import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
-import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle;
-import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
+import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -86,7 +91,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private Listener mListener;
private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
- private boolean mShowingAutoCorrectionInverted;
private final SuggestionsViewParams mParams;
private static final float MIN_TEXT_XSCALE = 0.70f;
@@ -95,10 +99,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private static class UiHandler extends StaticInnerHandlerWrapper<SuggestionsView> {
private static final int MSG_HIDE_PREVIEW = 0;
- private static final int MSG_UPDATE_SUGGESTION = 1;
private static final long DELAY_HIDE_PREVIEW = 1300;
- private static final long DELAY_UPDATE_SUGGESTION = 300;
public UiHandler(SuggestionsView outerInstance) {
super(outerInstance);
@@ -111,9 +113,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
case MSG_HIDE_PREVIEW:
suggestionsView.hidePreview();
break;
- case MSG_UPDATE_SUGGESTION:
- suggestionsView.updateSuggestions();
- break;
}
}
@@ -126,19 +125,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
removeMessages(MSG_HIDE_PREVIEW);
}
- public void postUpdateSuggestions() {
- cancelUpdateSuggestions();
- sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION),
- DELAY_UPDATE_SUGGESTION);
- }
-
- public void cancelUpdateSuggestions() {
- removeMessages(MSG_UPDATE_SUGGESTION);
- }
-
public void cancelAllMessages() {
cancelHidePreview();
- cancelUpdateSuggestions();
}
}
@@ -167,15 +155,13 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private final float mCenterSuggestionWeight;
private final int mCenterSuggestionIndex;
private final Drawable mMoreSuggestionsHint;
+ private static final String MORE_SUGGESTIONS_HINT = "\u2026";
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
- private final CharacterStyle mInvertedForegroundColorSpan;
- private final CharacterStyle mInvertedBackgroundColorSpan;
private static final int AUTO_CORRECT_BOLD = 0x01;
private static final int AUTO_CORRECT_UNDERLINE = 0x02;
- private static final int AUTO_CORRECT_INVERT = 0x04;
- private static final int VALID_TYPED_WORD_BOLD = 0x08;
+ private static final int VALID_TYPED_WORD_BOLD = 0x04;
private final int mSuggestionStripOption;
@@ -225,7 +211,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
mCenterSuggestionWeight = getPercent(a,
R.styleable.SuggestionsView_centerSuggestionPercentile,
DEFAULT_CENTER_SUGGESTION_PERCENTILE);
- mMoreSuggestionsHint = a.getDrawable(R.styleable.SuggestionsView_moreSuggestionsHint);
mMaxMoreSuggestionsRow = a.getInt(
R.styleable.SuggestionsView_maxMoreSuggestionsRow,
DEFAULT_MAX_MORE_SUGGESTIONS_ROW);
@@ -233,19 +218,35 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
R.styleable.SuggestionsView_minMoreSuggestionsWidth);
a.recycle();
+ mMoreSuggestionsHint = getMoreSuggestionsHint(res,
+ res.getDimension(R.dimen.more_suggestions_hint_text_size), mColorAutoCorrect);
mCenterSuggestionIndex = mSuggestionsCountInStrip / 2;
mMoreSuggestionsBottomGap = res.getDimensionPixelOffset(
R.dimen.more_suggestions_bottom_gap);
- mInvertedForegroundColorSpan = new ForegroundColorSpan(mColorTypedWord ^ 0x00ffffff);
- mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord);
-
final LayoutInflater inflater = LayoutInflater.from(context);
mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
mHintToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
}
+ private static Drawable getMoreSuggestionsHint(Resources res, float textSize, int color) {
+ final Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setTextAlign(Align.CENTER);
+ paint.setTextSize(textSize);
+ paint.setColor(color);
+ final Rect bounds = new Rect();
+ paint.getTextBounds(MORE_SUGGESTIONS_HINT, 0, MORE_SUGGESTIONS_HINT.length(), bounds);
+ final int width = Math.round(bounds.width() + 0.5f);
+ final int height = Math.round(bounds.height() + 0.5f);
+ final Bitmap buffer = Bitmap.createBitmap(
+ width, (height * 3 / 2), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(buffer);
+ canvas.drawText(MORE_SUGGESTIONS_HINT, width / 2, height, paint);
+ return new BitmapDrawable(res, buffer);
+ }
+
// Read integer value in TypedArray as percent.
private static float getPercent(TypedArray a, int index, int defValue) {
return a.getInt(index, defValue) / 100.0f;
@@ -320,16 +321,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
}
- public CharSequence getInvertedText(CharSequence text) {
- if ((mSuggestionStripOption & AUTO_CORRECT_INVERT) == 0)
- return null;
- final int len = text.length();
- final Spannable word = new SpannableString(text);
- word.setSpan(mInvertedBackgroundColorSpan, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- word.setSpan(mInvertedForegroundColorSpan, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- return word;
- }
-
public void layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer,
int stripWidth) {
if (suggestions.isPunctuationSuggestions()) {
@@ -522,8 +513,25 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final Resources res = context.getResources();
mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
R.dimen.more_suggestions_modal_tolerance);
+ mMoreSuggestionsSlidingDetector = new GestureDetector(
+ context, mMoreSuggestionsSlidingListener);
}
+ private final View.OnTouchListener mMoreSuggestionsCanceller = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent me) {
+ if (!mMoreSuggestionsWindow.isShowing()) return false;
+
+ switch (me.getAction()) {
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ return mMoreSuggestionsView.dismissMoreKeysPanel();
+ default:
+ return true;
+ }
+ }
+ };
+
/**
* A connection back to the input method.
* @param listener
@@ -534,21 +542,11 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
}
public void setSuggestions(SuggestedWords suggestions) {
- if (suggestions == null)
+ if (suggestions == null || suggestions.size() == 0)
return;
- mSuggestions = suggestions;
- if (mShowingAutoCorrectionInverted) {
- mHandler.postUpdateSuggestions();
- } else {
- updateSuggestions();
- }
- }
- private void updateSuggestions() {
clear();
- if (mSuggestions.size() == 0)
- return;
-
+ mSuggestions = suggestions;
mParams.layout(mSuggestions, mSuggestionsStrip, this, getWidth());
}
@@ -637,15 +635,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
}
}
- public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) {
- final CharSequence inverted = mParams.getInvertedText(autoCorrectedWord);
- if (inverted == null)
- return;
- final TextView tv = mWords.get(1);
- tv.setText(inverted);
- mShowingAutoCorrectionInverted = true;
- }
-
public boolean isShowingAddToDictionaryHint() {
return mSuggestionsStrip.getChildCount() > 0
&& mSuggestionsStrip.getChildAt(0) == mParams.mWordToSaveView;
@@ -669,7 +658,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
}
public void clear() {
- mShowingAutoCorrectionInverted = false;
mSuggestionsStrip.removeAllViews();
removeAllViews();
addView(mSuggestionsStrip);
@@ -739,6 +727,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
if (mMoreSuggestionsWindow.isShowing()) {
mMoreSuggestionsWindow.dismiss();
mKeyboardView.dimEntireKeyboard(false);
+ mKeyboardView.setOnTouchListener(null);
return true;
}
return false;
@@ -750,6 +739,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
@Override
public boolean onLongClick(View view) {
+ return showMoreSuggestions();
+ }
+
+ private boolean showMoreSuggestions() {
final SuggestionsViewParams params = mParams;
if (params.mMoreSuggestionsAvailable) {
final int stripWidth = getWidth();
@@ -770,29 +763,51 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
moreKeysPanel.showMoreKeysPanel(
this, mMoreSuggestionsController, pointX, pointY,
mMoreSuggestionsWindow, mMoreSuggestionsListener);
- mCheckingIfModalOrSlidingMode = true;
+ mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING;
mOriginX = mLastX;
mOriginY = mLastY;
- view.setPressed(false);
mKeyboardView.dimEntireKeyboard(true);
+ mKeyboardView.setOnTouchListener(mMoreSuggestionsCanceller);
+ for (int i = 0; i < params.mSuggestionsCountInStrip; i++) {
+ mWords.get(i).setPressed(false);
+ }
return true;
}
return false;
}
// Working variables for onLongClick and dispatchTouchEvent.
- private boolean mCheckingIfModalOrSlidingMode;
+ private int mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE;
+ private static final int MORE_SUGGESTIONS_IN_MODAL_MODE = 0;
+ private static final int MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING = 1;
+ private static final int MORE_SUGGESTIONS_IN_SLIDING_MODE = 2;
private int mLastX;
private int mLastY;
private int mOriginX;
private int mOriginY;
private final int mMoreSuggestionsModalTolerance;
+ private final GestureDetector mMoreSuggestionsSlidingDetector;
+ private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
+ new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onScroll(MotionEvent down, MotionEvent me, float deltaX, float deltaY) {
+ final float dy = me.getY() - down.getY();
+ if (deltaY > 0 && dy < 0) {
+ return showMoreSuggestions();
+ }
+ return false;
+ }
+ };
@Override
public boolean dispatchTouchEvent(MotionEvent me) {
- if (!mMoreSuggestionsWindow.isShowing()) {
+ if (!mMoreSuggestionsWindow.isShowing()
+ || mMoreSuggestionsMode == MORE_SUGGESTIONS_IN_MODAL_MODE) {
mLastX = (int)me.getX();
mLastY = (int)me.getY();
+ if (mMoreSuggestionsSlidingDetector.onTouchEvent(me)) {
+ return true;
+ }
return super.dispatchTouchEvent(me);
}
@@ -807,22 +822,22 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final int translatedX = moreKeysPanel.translateX(x);
final int translatedY = moreKeysPanel.translateY(y);
- if (mCheckingIfModalOrSlidingMode) {
+ if (mMoreSuggestionsMode == MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING) {
if (Math.abs(x - mOriginX) >= mMoreSuggestionsModalTolerance
|| mOriginY - y >= mMoreSuggestionsModalTolerance) {
// Decided to be in the sliding input mode only when the touch point has been moved
// upward.
- mCheckingIfModalOrSlidingMode = false;
+ mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_SLIDING_MODE;
tracker.onShowMoreKeysPanel(
translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel);
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
// Decided to be in the modal input mode
- mCheckingIfModalOrSlidingMode = false;
+ mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE;
}
return true;
}
- // Process sliding motion events
+ // MORE_SUGGESTIONS_IN_SLIDING_MODE
tracker.processMotionEvent(action, translatedX, translatedY, eventTime, moreKeysPanel);
return true;
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 1e5b87763..77fbe3ec6 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -60,8 +60,11 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private static final int CAPITALIZE_ALL = 2; // All caps
private final static String[] EMPTY_STRING_ARRAY = new String[0];
- private final static SuggestionsInfo EMPTY_SUGGESTIONS_INFO =
+ private final static SuggestionsInfo NOT_IN_DICT_EMPTY_SUGGESTIONS =
new SuggestionsInfo(0, EMPTY_STRING_ARRAY);
+ private final static SuggestionsInfo IN_DICT_EMPTY_SUGGESTIONS =
+ new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY,
+ EMPTY_STRING_ARRAY);
private Map<String, DictionaryPool> mDictionaryPools =
Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
private Map<String, Dictionary> mUserDictionaries =
@@ -330,7 +333,21 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
try {
final String text = textInfo.getText();
- if (shouldFilterOut(text)) return EMPTY_SUGGESTIONS_INFO;
+ if (shouldFilterOut(text)) {
+ DictAndProximity dictInfo = null;
+ try {
+ dictInfo = mDictionaryPool.takeOrGetNull();
+ if (null == dictInfo) return NOT_IN_DICT_EMPTY_SUGGESTIONS;
+ return dictInfo.mDictionary.isValidWord(text) ? IN_DICT_EMPTY_SUGGESTIONS
+ : NOT_IN_DICT_EMPTY_SUGGESTIONS;
+ } finally {
+ if (null != dictInfo) {
+ if (!mDictionaryPool.offer(dictInfo)) {
+ Log.e(TAG, "Can't re-insert a dictionary into its pool");
+ }
+ }
+ }
+ }
final SuggestionsGatherer suggestionsGatherer =
new SuggestionsGatherer(suggestionsLimit);
@@ -353,8 +370,10 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
final int capitalizeType = getCapitalizationType(text);
boolean isInDict = true;
+ DictAndProximity dictInfo = null;
try {
- final DictAndProximity dictInfo = mDictionaryPool.take();
+ dictInfo = mDictionaryPool.takeOrGetNull();
+ if (null == dictInfo) return NOT_IN_DICT_EMPTY_SUGGESTIONS;
dictInfo.mDictionary.getWords(composer, suggestionsGatherer,
dictInfo.mProximityInfo);
isInDict = dictInfo.mDictionary.isValidWord(text);
@@ -364,12 +383,12 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// want to test a lowercase version of it.
isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
}
- if (!mDictionaryPool.offer(dictInfo)) {
- Log.e(TAG, "Can't re-insert a dictionary into its pool");
+ } finally {
+ if (null != dictInfo) {
+ if (!mDictionaryPool.offer(dictInfo)) {
+ Log.e(TAG, "Can't re-insert a dictionary into its pool");
+ }
}
- } catch (InterruptedException e) {
- // I don't think this can happen.
- return EMPTY_SUGGESTIONS_INFO;
}
final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(text,
@@ -396,7 +415,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
throw e;
} else {
Log.e(TAG, "Exception while spellcheking: " + e);
- return EMPTY_SUGGESTIONS_INFO;
+ return NOT_IN_DICT_EMPTY_SUGGESTIONS;
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
index ee294f6b0..dec18c1d5 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -56,6 +56,15 @@ public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
}
}
+ // Convenience method
+ public DictAndProximity takeOrGetNull() {
+ try {
+ return take();
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
+
public void close() {
synchronized(this) {
mClosed = true;