diff options
Diffstat (limited to 'java/src')
18 files changed, 517 insertions, 710 deletions
diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java index 7aab66d05..8e2ee0f7a 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java @@ -73,16 +73,17 @@ public class InputMethodServiceCompatWrapper extends InputMethodService { // This call is required to let LatinIME itself know a subtype changed // event when the API level is 10 or previous. @SuppressWarnings("unused") - public void notifyOnCurrentInputMethodSubtypeChanged(InputMethodSubtypeCompatWrapper subtype) { + public void notifyOnCurrentInputMethodSubtypeChanged( + InputMethodSubtypeCompatWrapper newSubtype) { // Do nothing when the API level is 11 or later // and FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES is not true if (CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED && !InputMethodManagerCompatWrapper. FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) { return; } - if (subtype == null) { - subtype = mImm.getCurrentInputMethodSubtype(); - } + final InputMethodSubtypeCompatWrapper subtype = (newSubtype == null) + ? mImm.getCurrentInputMethodSubtype() + : newSubtype; if (subtype != null) { if (!InputMethodManagerCompatWrapper.FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES && !subtype.isDummy()) return; diff --git a/java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java b/java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java index bf2512d7b..75efa52f2 100644 --- a/java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java +++ b/java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java @@ -16,28 +16,28 @@ package com.android.inputmethod.deprecated.recorrection; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.text.TextUtils; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; + import com.android.inputmethod.compat.InputConnectionCompatUtils; import com.android.inputmethod.compat.SuggestionSpanUtils; import com.android.inputmethod.deprecated.VoiceProxy; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.latin.AutoCorrection; -import com.android.inputmethod.latin.CandidateView; import com.android.inputmethod.latin.EditingUtils; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.Settings; import com.android.inputmethod.latin.Suggest; import com.android.inputmethod.latin.SuggestedWords; +import com.android.inputmethod.latin.SuggestionsView; import com.android.inputmethod.latin.TextEntryState; import com.android.inputmethod.latin.WordComposer; -import android.content.SharedPreferences; -import android.content.res.Resources; -import android.text.TextUtils; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; - import java.util.ArrayList; /** @@ -107,7 +107,7 @@ public class Recorrection implements SharedPreferences.OnSharedPreferenceChangeL } public void updateRecorrectionSelection(KeyboardSwitcher keyboardSwitcher, - CandidateView candidateView, int candidatesStart, int candidatesEnd, + SuggestionsView suggestionsView, int candidatesStart, int candidatesEnd, int newSelStart, int newSelEnd, int oldSelStart, int lastSelectionStart, int lastSelectionEnd, boolean hasUncommittedTypedChars) { if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED || !mRecorrectionEnabled) return; @@ -127,7 +127,7 @@ public class Recorrection implements SharedPreferences.OnSharedPreferenceChangeL // If showing the "touch again to save" hint, do not replace it. Else, // show the bigrams if we are at the end of the text, punctuation // otherwise. - if (candidateView != null && !candidateView.isShowingAddToDictionaryHint()) { + if (suggestionsView != null && !suggestionsView.isShowingAddToDictionaryHint()) { InputConnection ic = mService.getCurrentInputConnection(); if (null == ic || !TextUtils.isEmpty(ic.getTextAfterCursor(1, 0))) { if (!mService.isShowingPunctuationList()) { @@ -219,13 +219,13 @@ public class Recorrection implements SharedPreferences.OnSharedPreferenceChangeL } public void fetchAndDisplayRecorrectionSuggestions(VoiceProxy voiceProxy, - CandidateView candidateView, Suggest suggest, KeyboardSwitcher keyboardSwitcher, + SuggestionsView suggestionsView, Suggest suggest, KeyboardSwitcher keyboardSwitcher, WordComposer word, boolean hasUncommittedTypedChars, int lastSelectionStart, int lastSelectionEnd, String wordSeparators) { if (!InputConnectionCompatUtils.RECORRECTION_SUPPORTED) return; if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED || !mRecorrectionEnabled) return; voiceProxy.setShowingVoiceSuggestions(false); - if (candidateView != null && candidateView.isShowingAddToDictionaryHint()) { + if (suggestionsView != null && suggestionsView.isShowingAddToDictionaryHint()) { return; } InputConnection ic = mService.getCurrentInputConnection(); @@ -260,7 +260,7 @@ public class Recorrection implements SharedPreferences.OnSharedPreferenceChangeL if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED) return; if (force || TextEntryState.isRecorrecting()) { TextEntryState.onAbortRecorrection(); - mService.setCandidatesViewShown(mService.isCandidateStripVisible()); + mService.setCandidatesViewShown(mService.isSuggestionsStripVisible()); mService.getCurrentInputConnection().finishComposingText(); mService.clearSuggestions(); } diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index b919bcfc4..15ec80b6e 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -31,7 +31,6 @@ import com.android.inputmethod.keyboard.internal.KeyboardBuilder.ParseException; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.keyboard.internal.MoreKeySpecParser; -import com.android.inputmethod.keyboard.internal.Row; import com.android.inputmethod.latin.R; import java.util.HashMap; @@ -243,133 +242,125 @@ public class Key { * parser. * @param res resources associated with the caller's context * @param params the keyboard building parameters. - * @param row the row that this key belongs to. - * @param x the x coordinate of the top-left - * @param y the y coordinate of the top-left + * @param row the row that this key belongs to. row's x-coordinate will be the right edge of + * this key. * @param parser the XML parser containing the attributes for this key * @param keyStyles active key styles set */ - public Key(Resources res, KeyboardParams params, Row row, int x, int y, + public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row, XmlResourceParser parser, KeyStyles keyStyles) { final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard); - int keyWidth; - try { - mHeight = KeyboardBuilder.getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_rowHeight, - params.mHeight, row.mRowHeight) - params.mVerticalGap; - mHorizontalGap = KeyboardBuilder.getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_horizontalGap, - params.mWidth, params.mHorizontalGap); - mVerticalGap = params.mVerticalGap; - keyWidth = KeyboardBuilder.getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_keyWidth, - params.mWidth, row.mDefaultKeyWidth); - } finally { - keyboardAttr.recycle(); - } + mHeight = (int)KeyboardBuilder.getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_rowHeight, params.mHeight, row.mRowHeight) + - params.mVerticalGap; + final float horizontalGap = KeyboardBuilder.getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_horizontalGap, params.mWidth, params.mHorizontalGap); + mVerticalGap = params.mVerticalGap; + float keyWidth = KeyboardBuilder.getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_keyWidth, params.mWidth, row.mDefaultKeyWidth); + keyboardAttr.recycle(); final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard_Key); - try { - final KeyStyle style; - if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) { - String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle); - style = keyStyles.getKeyStyle(styleName); - if (style == null) - throw new ParseException("Unknown key style: " + styleName, parser); - } else { - style = keyStyles.getEmptyKeyStyle(); - } - final int keyboardWidth = params.mOccupiedWidth; - int keyXPos = KeyboardBuilder.getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_keyXPos, keyboardWidth, x); - if (keyXPos < 0) { - // If keyXPos is negative, the actual x-coordinate will be k + keyXPos. - keyXPos += keyboardWidth; - if (keyXPos < x) { - // keyXPos shouldn't be less than x because drawable area for this key starts - // at x. Or, this key will overlaps the adjacent key on its left hand side. - keyXPos = x; - } - } - if (keyWidth == KEYWIDTH_FILL_RIGHT) { - // If keyWidth is zero, the actual key width will be determined to fill out the - // area up to the right edge of the keyboard. - keyWidth = keyboardWidth - keyXPos; - } else if (keyWidth <= KEYWIDTH_FILL_BOTH) { - // If keyWidth is negative, the actual key width will be determined to fill out the - // area between the nearest key on the left hand side and the right edge of the - // keyboard. + final KeyStyle style; + if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) { + String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle); + style = keyStyles.getKeyStyle(styleName); + if (style == null) + throw new ParseException("Unknown key style: " + styleName, parser); + } else { + style = keyStyles.getEmptyKeyStyle(); + } + + final int keyboardWidth = 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; - keyWidth = keyboardWidth - keyXPos; } + } + if (keyWidth == KEYWIDTH_FILL_RIGHT) { + // If keyWidth is zero, the actual key width will be determined to fill out the + // area up to the right edge of the keyboard. + keyWidth = keyboardWidth - keyXPos; + } else if (keyWidth <= KEYWIDTH_FILL_BOTH) { + // If keyWidth is negative, the actual key width will be determined to fill out the + // area between the nearest key on the left hand side and the right edge of the + // keyboard. + keyXPos = x; + keyWidth = keyboardWidth - keyXPos; + } - // Horizontal gap is divided equally to both sides of the key. - mX = keyXPos + mHorizontalGap / 2; - mY = y; - mWidth = keyWidth - mHorizontalGap; - - final CharSequence[] moreKeys = style.getTextArray( - keyAttr, R.styleable.Keyboard_Key_moreKeys); - // In Arabic symbol layouts, we'd like to keep digits in more keys regardless of - // config_digit_more_keys_enabled. - if (params.mId.isAlphabetKeyboard() && !res.getBoolean( - R.bool.config_digit_more_keys_enabled)) { - mMoreKeys = MoreKeySpecParser.filterOut( - res, moreKeys, MoreKeySpecParser.DIGIT_FILTER); - } else { - mMoreKeys = moreKeys; - } - mMaxMoreKeysColumn = style.getInt(keyboardAttr, - R.styleable.Keyboard_Key_maxMoreKeysColumn, - params.mMaxMiniKeyboardColumn); - - mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false); - mFunctional = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isFunctional, false); - mSticky = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isSticky, false); - mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true); - mEdgeFlags = 0; - - final KeyboardIconsSet iconsSet = params.mIconsSet; - mVisualInsetsLeft = KeyboardBuilder.getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_visualInsetsLeft, keyboardWidth, 0); - mVisualInsetsRight = KeyboardBuilder.getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_visualInsetsRight, keyboardWidth, 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, - KeyboardIconsSet.ICON_UNDEFINED)); - final int shiftedIconId = style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIconShifted, - KeyboardIconsSet.ICON_UNDEFINED); - if (shiftedIconId != KeyboardIconsSet.ICON_UNDEFINED) { - final Drawable shiftedIcon = iconsSet.getIcon(shiftedIconId); - params.addShiftedIcon(this, shiftedIcon); - } - mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel); - - mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel); - mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0); - mOutputText = style.getText(keyAttr, R.styleable.Keyboard_Key_keyOutputText); - // Choose the first letter of the label as primary code if not - // specified. - final int code = style.getInt(keyAttr, R.styleable.Keyboard_Key_code, - Keyboard.CODE_UNSPECIFIED); - if (code == Keyboard.CODE_UNSPECIFIED && !TextUtils.isEmpty(mLabel)) { - final int firstChar = mLabel.charAt(0); - mCode = getRtlParenthesisCode(firstChar, params.mIsRtlKeyboard); - } else if (code != Keyboard.CODE_UNSPECIFIED) { - mCode = code; - } else { - mCode = Keyboard.CODE_DUMMY; - } - } finally { - keyAttr.recycle(); + // Horizontal gap is divided equally to both sides of the key. + mX = (int) (keyXPos + horizontalGap / 2); + mY = row.mCurrentY; + mWidth = (int) (keyWidth - horizontalGap); + mHorizontalGap = (int) horizontalGap; + // Update row to have current x coordinate. + row.mCurrentX = keyXPos + keyWidth; + + final CharSequence[] moreKeys = style.getTextArray(keyAttr, + R.styleable.Keyboard_Key_moreKeys); + // In Arabic symbol layouts, we'd like to keep digits in more keys regardless of + // config_digit_more_keys_enabled. + if (params.mId.isAlphabetKeyboard() + && !res.getBoolean(R.bool.config_digit_more_keys_enabled)) { + mMoreKeys = MoreKeySpecParser.filterOut(res, moreKeys, MoreKeySpecParser.DIGIT_FILTER); + } else { + mMoreKeys = moreKeys; + } + mMaxMoreKeysColumn = style.getInt(keyboardAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn, + params.mMaxMiniKeyboardColumn); + + mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false); + mFunctional = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isFunctional, false); + mSticky = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isSticky, false); + mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true); + mEdgeFlags = 0; + + final KeyboardIconsSet iconsSet = params.mIconsSet; + mVisualInsetsLeft = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr, + R.styleable.Keyboard_Key_visualInsetsLeft, keyboardWidth, 0); + mVisualInsetsRight = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr, + R.styleable.Keyboard_Key_visualInsetsRight, keyboardWidth, 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, + KeyboardIconsSet.ICON_UNDEFINED)); + final int shiftedIconId = style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIconShifted, + KeyboardIconsSet.ICON_UNDEFINED); + if (shiftedIconId != KeyboardIconsSet.ICON_UNDEFINED) { + final Drawable shiftedIcon = iconsSet.getIcon(shiftedIconId); + params.addShiftedIcon(this, shiftedIcon); } + mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel); + + mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel); + mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0); + mOutputText = style.getText(keyAttr, R.styleable.Keyboard_Key_keyOutputText); + // Choose the first letter of the label as primary code if not + // specified. + final int code = style.getInt(keyAttr, R.styleable.Keyboard_Key_code, + Keyboard.CODE_UNSPECIFIED); + if (code == Keyboard.CODE_UNSPECIFIED && !TextUtils.isEmpty(mLabel)) { + final int firstChar = mLabel.charAt(0); + mCode = getRtlParenthesisCode(firstChar, params.mIsRtlKeyboard); + } else if (code != Keyboard.CODE_UNSPECIFIED) { + mCode = code; + } else { + mCode = Keyboard.CODE_DUMMY; + } + + keyAttr.recycle(); } public void addEdgeFlags(int flags) { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index ceadc919c..96eb69407 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -103,6 +103,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private ViewGroup mPreviewPlacer; // Drawing + /** True if the entire keyboard needs to be dimmed. */ + private boolean mNeedsToDimBackground; /** Whether the keyboard bitmap buffer needs to be redrawn before it's blitted. **/ private boolean mBufferNeedsUpdate; /** The dirty region in the keyboard bitmap */ @@ -481,8 +483,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } } - // Overlay a dark rectangle to dim the keyboard - if (needsToDimKeyboard()) { + // Overlay a dark rectangle to dim the entire keyboard + if (mNeedsToDimBackground) { mPaint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24); canvas.drawRect(0, 0, width, height, mPaint); } @@ -491,8 +493,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mDirtyRect.setEmpty(); } - protected boolean needsToDimKeyboard() { - return false; + public void dimEntireKeyboard(boolean dimmed) { + final boolean needsRedrawing = mNeedsToDimBackground != dimmed; + mNeedsToDimBackground = dimmed; + if (needsRedrawing) { + invalidateAllKeys(); + } } private static void onBufferDrawKey(final Key key, final Keyboard keyboard, final Canvas canvas, diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 777bae3b0..d9089e199 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -373,11 +373,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke return miniKeyboardView; } - @Override - protected boolean needsToDimKeyboard() { - return mMoreKeysPanel != null; - } - public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboard oldKeyboard) { final Keyboard keyboard = getKeyboard(); // We should not set text fade factor to the keyboard which does not display the language on @@ -460,8 +455,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final int translatedY = moreKeysPanel.translateY(tracker.getLastY()); tracker.onShowMoreKeysPanel( translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel); - - invalidateAllKeys(); + dimEntireKeyboard(true); return true; } @@ -620,7 +614,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mMoreKeysWindow.dismiss(); mMoreKeysPanel = null; mMoreKeysPanelPointerTrackerId = -1; - invalidateAllKeys(); + dimEntireKeyboard(false); return true; } return false; diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java index f331662d7..29861fe4a 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java @@ -27,7 +27,6 @@ import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.latin.R; -import java.util.List; /** * A view that renders a virtual {@link MiniKeyboard}. It handles rendering of keys and detecting @@ -43,51 +42,6 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { private int mOriginX; private int mOriginY; - private static class MiniKeyboardKeyDetector extends KeyDetector { - private final int mSlideAllowanceSquare; - private final int mSlideAllowanceSquareTop; - - public MiniKeyboardKeyDetector(float slideAllowance) { - super(/* keyHysteresisDistance */0); - mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance); - // Top slide allowance is slightly longer (sqrt(2) times) than other edges. - mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2; - } - - @Override - public boolean alwaysAllowsSlidingInput() { - return true; - } - - @Override - protected int getMaxNearbyKeys() { - // No nearby key will be returned. - return 1; - } - - @Override - public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; - final int touchX = getTouchX(x); - final int touchY = getTouchY(y); - - int nearestIndex = NOT_A_KEY; - int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; - final int keyCount = keys.size(); - for (int index = 0; index < keyCount; index++) { - final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY); - if (dist < nearestDist) { - nearestIndex = index; - nearestDist = dist; - } - } - - if (allCodes != null && nearestIndex != NOT_A_KEY) - allCodes[0] = keys.get(nearestIndex).mCode; - return nearestIndex; - } - } - private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter(); private final KeyboardActionListener mMiniKeyboardListener = @@ -126,7 +80,7 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { final Resources res = context.getResources(); // Override default ProximityKeyDetector. - mKeyDetector = new MiniKeyboardKeyDetector(res.getDimension( + mKeyDetector = new MoreKeysDetector(res.getDimension( R.dimen.mini_keyboard_slide_allowance)); // Remove gesture detector on mini-keyboard setKeyPreviewPopupEnabled(false, 0); diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java new file mode 100644 index 000000000..d20204611 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard; + +import java.util.List; + +public class MoreKeysDetector extends KeyDetector { + private final int mSlideAllowanceSquare; + private final int mSlideAllowanceSquareTop; + + public MoreKeysDetector(float slideAllowance) { + super(/* keyHysteresisDistance */0); + mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance); + // Top slide allowance is slightly longer (sqrt(2) times) than other edges. + mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2; + } + + @Override + public boolean alwaysAllowsSlidingInput() { + return true; + } + + @Override + protected int getMaxNearbyKeys() { + // No nearby key will be returned. + return 1; + } + + @Override + public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { + final List<Key> keys = getKeyboard().mKeys; + final int touchX = getTouchX(x); + final int touchY = getTouchY(y); + + int nearestIndex = NOT_A_KEY; + int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; + final int keyCount = keys.size(); + for (int index = 0; index < keyCount; index++) { + final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY); + if (dist < nearestDist) { + nearestIndex = index; + nearestDist = dist; + } + } + + if (allCodes != null && nearestIndex != NOT_A_KEY) + allCodes[0] = keys.get(nearestIndex).mCode; + return nearestIndex; + } +}
\ No newline at end of file diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java index c605debab..fb1c06175 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java @@ -128,7 +128,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> { protected final Resources mResources; private final DisplayMetrics mDisplayMetrics; - private int mCurrentX = 0; private int mCurrentY = 0; private Row mCurrentRow = null; private boolean mLeftEdge; @@ -136,6 +135,37 @@ public class KeyboardBuilder<KP extends KeyboardParams> { private Key mRightEdgeKey = null; private final KeyStyles mKeyStyles = new KeyStyles(); + /** + * 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 Keyboard} + * defines. + */ + public static class Row { + /** 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; + // Will be updated by {@link Key}'s constructor. + public 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), + 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(); + + mCurrentY = y; + mCurrentX = 0.0f; + } + } + public KeyboardBuilder(Context context, KP params) { mContext = context; final Resources res = context.getResources(); @@ -219,14 +249,14 @@ public class KeyboardBuilder<KP extends KeyboardParams> { final int displayHeight = mDisplayMetrics.heightPixels; final int keyboardHeight = (int)keyboardAttr.getDimension( R.styleable.Keyboard_keyboardHeight, displayHeight / 2); - final int maxKeyboardHeight = getDimensionOrFraction(keyboardAttr, + final int maxKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2); - int minKeyboardHeight = getDimensionOrFraction(keyboardAttr, + int minKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2); if (minKeyboardHeight < 0) { // Specified fraction was negative, so it should be calculated against display // width. - minKeyboardHeight = -getDimensionOrFraction(keyboardAttr, + minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2); } // Keyboard height will not exceed maxKeyboardHeight and will not be less than @@ -234,9 +264,9 @@ public class KeyboardBuilder<KP extends KeyboardParams> { mParams.mOccupiedHeight = Math.max( Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight); mParams.mOccupiedWidth = mParams.mId.mWidth; - mParams.mTopPadding = getDimensionOrFraction(keyboardAttr, + mParams.mTopPadding = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_keyboardTopPadding, mParams.mOccupiedHeight, 0); - mParams.mBottomPadding = getDimensionOrFraction(keyboardAttr, + mParams.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_keyboardBottomPadding, mParams.mOccupiedHeight, 0); final int height = mParams.mOccupiedHeight; @@ -244,13 +274,13 @@ public class KeyboardBuilder<KP extends KeyboardParams> { - mParams.mHorizontalCenterPadding; mParams.mHeight = height; mParams.mWidth = width; - mParams.mDefaultKeyWidth = getDimensionOrFraction(keyboardAttr, + mParams.mDefaultKeyWidth = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_keyWidth, width, width / 10); - mParams.mDefaultRowHeight = getDimensionOrFraction(keyboardAttr, + mParams.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_rowHeight, height, height / 4); - mParams.mHorizontalGap = getDimensionOrFraction(keyboardAttr, + mParams.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_horizontalGap, width, 0); - mParams.mVerticalGap = getDimensionOrFraction(keyboardAttr, + mParams.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_verticalGap, height, 0); mParams.mIsRtlKeyboard = keyboardAttr.getBoolean( @@ -314,7 +344,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> { throw new IllegalAttribute(parser, "horizontalGap"); if (a.hasValue(R.styleable.Keyboard_verticalGap)) throw new IllegalAttribute(parser, "verticalGap"); - return new Row(mResources, mParams, parser); + return new Row(mResources, mParams, parser, mCurrentY); } finally { a.recycle(); } @@ -344,7 +374,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> { if (TAG_ROW.equals(tag)) { if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_ROW)); if (!skip) - endRow(); + endRow(row); break; } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag) || TAG_MERGE.equals(tag)) { @@ -364,7 +394,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> { if (skip) { checkEndTag(TAG_KEY, parser); } else { - Key key = new Key(mResources, mParams, row, mCurrentX, mCurrentY, parser, mKeyStyles); + Key key = new Key(mResources, mParams, row, parser, mKeyStyles); if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d moreKeys=%s />", TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode, Arrays.toString(key.mMoreKeys))); @@ -385,21 +415,21 @@ public class KeyboardBuilder<KP extends KeyboardParams> { if (keyboardAttr.hasValue(R.styleable.Keyboard_horizontalGap)) throw new IllegalAttribute(parser, "horizontalGap"); final int keyboardWidth = mParams.mWidth; - final int keyWidth = getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_keyWidth, - keyboardWidth, row.mDefaultKeyWidth); + final float keyWidth = getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_keyWidth, keyboardWidth, row.mDefaultKeyWidth); keyboardAttr.recycle(); final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard_Key); - int keyXPos = KeyboardBuilder.getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_keyXPos, keyboardWidth, mCurrentX); + float keyXPos = getDimensionOrFraction(keyAttr, + R.styleable.Keyboard_Key_keyXPos, keyboardWidth, row.mCurrentX); if (keyXPos < 0) { // If keyXPos is negative, the actual x-coordinate will be display_width + keyXPos. keyXPos += keyboardWidth; } checkEndTag(TAG_SPACER, parser); - setSpacer(keyXPos, keyWidth); + setSpacer(keyXPos, keyWidth, row); } } @@ -655,28 +685,27 @@ public class KeyboardBuilder<KP extends KeyboardParams> { } private void startRow(Row row) { - mCurrentX = 0; - setSpacer(mCurrentX, mParams.mHorizontalEdgesPadding); + row.mCurrentX = 0; + setSpacer(row.mCurrentX, mParams.mHorizontalEdgesPadding, row); mCurrentRow = row; mLeftEdge = true; mRightEdgeKey = null; } - private void endRow() { + private void endRow(Row row) { if (mCurrentRow == null) throw new InflateException("orphant end row tag"); if (mRightEdgeKey != null) { mRightEdgeKey.addEdgeFlags(Keyboard.EDGE_RIGHT); mRightEdgeKey = null; } - setSpacer(mCurrentX, mParams.mHorizontalEdgesPadding); + setSpacer(row.mCurrentX, mParams.mHorizontalEdgesPadding, row); mCurrentY += mCurrentRow.mRowHeight; mCurrentRow = null; mTopEdge = false; } private void endKey(Key key) { - mCurrentX = key.mX - key.mHorizontalGap / 2 + key.mWidth + key.mHorizontalGap; if (mLeftEdge) { key.addEdgeFlags(Keyboard.EDGE_LEFT); mLeftEdge = false; @@ -690,24 +719,23 @@ public class KeyboardBuilder<KP extends KeyboardParams> { private void endKeyboard() { } - private void setSpacer(int keyXPos, int width) { - mCurrentX = keyXPos + width; + private void setSpacer(float keyXPos, float width, Row row) { + row.mCurrentX = keyXPos + width; mLeftEdge = false; mRightEdgeKey = null; } - public static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) { + public static float getDimensionOrFraction(TypedArray a, int index, int base, float defValue) { final TypedValue value = a.peekValue(index); if (value == null) return defValue; if (isFractionValue(value)) { - // Round it to avoid values like 47.9999 from getting truncated - return Math.round(a.getFraction(index, base, base, defValue)); + return a.getFraction(index, base, base, defValue); } else if (isDimensionValue(value)) { - return a.getDimensionPixelOffset(index, defValue); + return a.getDimension(index, defValue); } else if (isIntegerValue(value)) { // For enum value. - return a.getInt(index, defValue); + return a.getInt(index, 0); } return defValue; } diff --git a/java/src/com/android/inputmethod/keyboard/internal/Row.java b/java/src/com/android/inputmethod/keyboard/internal/Row.java deleted file mode 100644 index d53fe12e2..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/Row.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.Xml; - -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.latin.R; - -/** - * 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 Keyboard} - * defines. - */ -public class Row { - /** Default width of a key in this row. */ - public final int mDefaultKeyWidth; - /** Default height of a key in this row. */ - public final int mRowHeight; - - public Row(Resources res, KeyboardParams params, XmlResourceParser parser) { - final int keyboardWidth = params.mWidth; - final int keyboardHeight = params.mHeight; - TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard); - mDefaultKeyWidth = KeyboardBuilder.getDimensionOrFraction(a, - R.styleable.Keyboard_keyWidth, keyboardWidth, params.mDefaultKeyWidth); - mRowHeight = KeyboardBuilder.getDimensionOrFraction(a, - R.styleable.Keyboard_rowHeight, keyboardHeight, params.mDefaultRowHeight); - a.recycle(); - } -} diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index d3119792c..e6ae2c5c7 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -119,15 +119,15 @@ public class AutoCorrection { if (wordComposer.size() > 1 && (correctionMode == Suggest.CORRECTION_FULL || correctionMode == Suggest.CORRECTION_FULL_BIGRAM) && typedWord != null && suggestions.size() > 0 && sortedScores.length > 0) { - final CharSequence autoCorrectionCandidate = suggestions.get(0); - final int autoCorrectionCandidateScore = sortedScores[0]; + final CharSequence autoCorrectionSuggestion = suggestions.get(0); + final int autoCorrectionSuggestionScore = sortedScores[0]; // TODO: when the normalized score of the first suggestion is nearly equals to // the normalized score of the second suggestion, behave less aggressive. mNormalizedScore = Utils.calcNormalizedScore( - typedWord,autoCorrectionCandidate, autoCorrectionCandidateScore); + typedWord,autoCorrectionSuggestion, autoCorrectionSuggestionScore); if (DBG) { - Log.d(TAG, "Normalized " + typedWord + "," + autoCorrectionCandidate + "," - + autoCorrectionCandidateScore + ", " + mNormalizedScore + Log.d(TAG, "Normalized " + typedWord + "," + autoCorrectionSuggestion + "," + + autoCorrectionSuggestionScore + ", " + mNormalizedScore + "(" + autoCorrectionThreshold + ")"); } if (mNormalizedScore >= autoCorrectionThreshold) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7559108f3..cea59fe0a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -77,7 +77,7 @@ import java.util.Locale; * Input method implementation for Qwerty'ish keyboard. */ public class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, - CandidateView.Listener { + SuggestionsView.Listener { private static final String TAG = LatinIME.class.getSimpleName(); private static final boolean PERF_DEBUG = false; private static final boolean TRACE = false; @@ -118,6 +118,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar */ public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; + /** + * The subtype extra value used to indicate that the subtype keyboard layout should be loaded + * from the specified locale. + */ + public static final String SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE = "KeyboardLocale"; + private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; // How many continuous deletes at which to start deleting at a higher speed. @@ -151,9 +157,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private Settings.Values mSettingsValues; - private View mCandidateViewContainer; - private int mCandidateStripHeight; - private CandidateView mCandidateView; + private View mSuggestionsContainer; + private int mSuggestionsStripHeight; + private SuggestionsView mSuggestionsView; private Suggest mSuggest; private CompletionInfo[] mApplicationSpecifiedCompletions; @@ -248,7 +254,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar break; case MSG_UPDATE_OLD_SUGGESTIONS: latinIme.mRecorrection.fetchAndDisplayRecorrectionSuggestions( - latinIme.mVoiceProxy, latinIme.mCandidateView, + latinIme.mVoiceProxy, latinIme.mSuggestionsView, latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWordComposer, latinIme.mHasUncommittedTypedChars, latinIme.mLastSelectionStart, latinIme.mLastSelectionEnd, latinIme.mSettingsValues.mWordSeparators); @@ -601,11 +607,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public void setInputView(View view) { super.setInputView(view); - mCandidateViewContainer = view.findViewById(R.id.candidates_container); - mCandidateView = (CandidateView) view.findViewById(R.id.candidates); - if (mCandidateView != null) - mCandidateView.setListener(this, view); - mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height); + mSuggestionsContainer = view.findViewById(R.id.suggestions_container); + mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view); + if (mSuggestionsView != null) + mSuggestionsView.setListener(this, view); + mSuggestionsStripHeight = (int)mResources.getDimension(R.dimen.suggestions_strip_height); } @Override @@ -672,9 +678,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar switcher.loadKeyboard(attribute, mSettingsValues); } - if (mCandidateView != null) - mCandidateView.clear(); - setSuggestionStripShownInternal(isCandidateStripVisible(), /* needsInputViewShown */ false); + if (mSuggestionsView != null) + mSuggestionsView.clear(); + setSuggestionStripShownInternal( + isSuggestionsStripVisible(), /* needsInputViewShown */ false); // Delay updating suggestions because keyboard input view may not be shown at this point. mHandler.postUpdateSuggestions(); @@ -702,7 +709,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { mIsSettingsSuggestionStripOn = true; - // Make sure that passwords are not displayed in candidate view + // Make sure that passwords are not displayed in {@link SuggestionsView}. if (InputTypeCompatUtils.isPasswordInputType(inputType) || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) { mIsSettingsSuggestionStripOn = false; @@ -813,7 +820,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar && (selectionChanged || candidatesCleared)) { if (candidatesCleared) { // If the composing span has been cleared, save the typed word in the history for - // recorrection before we reset the candidate strip. Then, we'll be able to show + // recorrection before we reset the suggestions strip. Then, we'll be able to show // suggestions for recorrection right away. mRecorrection.saveRecorrectionSuggestion(mWordComposer, mComposingStringBuilder); } @@ -847,7 +854,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mLastSelectionEnd = newSelEnd; mRecorrection.updateRecorrectionSelection(mKeyboardSwitcher, - mCandidateView, candidatesStart, candidatesEnd, newSelStart, + mSuggestionsView, candidatesStart, candidatesEnd, newSelStart, newSelEnd, oldSelStart, mLastSelectionStart, mLastSelectionEnd, mHasUncommittedTypedChars); } @@ -860,10 +867,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar /** * This is called when the user has clicked on the extracted text view, * when running in fullscreen mode. The default implementation hides - * the candidates view when this happens, but only if the extracted text + * the suggestions view when this happens, but only if the extracted text * editor has a vertical scroll bar because its text doesn't fit. * Here we override the behavior due to the possibility that a re-correction could - * cause the candidate strip to disappear and re-appear. + * cause the suggestions strip to disappear and re-appear. */ @Override public void onExtractedTextClicked() { @@ -875,11 +882,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar /** * This is called when the user has performed a cursor movement in the * extracted text view, when it is running in fullscreen mode. The default - * implementation hides the candidates view when a vertical movement + * implementation hides the suggestions view when a vertical movement * happens, but only if the extracted text editor has a vertical scroll bar * because its text doesn't fit. * Here we override the behavior due to the possibility that a re-correction could - * cause the candidate strip to disappear and re-appear. + * cause the suggestions strip to disappear and re-appear. */ @Override public void onExtractedCursorMovement(int dx, int dy) { @@ -932,20 +939,20 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { - // TODO: Modify this if we support candidates with hard keyboard - if (onEvaluateInputViewShown() && mCandidateViewContainer != null) { - final boolean shouldShowCandidates = shown + // TODO: Modify this if we support suggestions with hard keyboard + if (onEvaluateInputViewShown() && mSuggestionsContainer != null) { + final boolean shouldShowSuggestions = shown && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true); if (isFullscreenMode()) { // No need to have extra space to show the key preview. - mCandidateViewContainer.setMinimumHeight(0); - mCandidateViewContainer.setVisibility( - shouldShowCandidates ? View.VISIBLE : View.GONE); + mSuggestionsContainer.setMinimumHeight(0); + mSuggestionsContainer.setVisibility( + shouldShowSuggestions ? View.VISIBLE : View.GONE); } else { // We must control the visibility of the suggestion strip in order to avoid clipped // key previews, even when we don't show the suggestion strip. - mCandidateViewContainer.setVisibility( - shouldShowCandidates ? View.VISIBLE : View.INVISIBLE); + mSuggestionsContainer.setVisibility( + shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE); } } } @@ -958,14 +965,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public void onComputeInsets(InputMethodService.Insets outInsets) { super.onComputeInsets(outInsets); final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); - if (inputView == null || mCandidateViewContainer == null) + if (inputView == null || mSuggestionsContainer == null) return; - final int containerHeight = mCandidateViewContainer.getHeight(); + final int containerHeight = mSuggestionsContainer.getHeight(); int touchY = containerHeight; // Need to set touchable region only if input view is being shown if (mKeyboardSwitcher.isInputViewShown()) { - if (mCandidateViewContainer.getVisibility() == View.VISIBLE) { - touchY -= mCandidateStripHeight; + if (mSuggestionsContainer.getVisibility() == View.VISIBLE) { + touchY -= mSuggestionsStripHeight; } final int touchWidth = inputView.getWidth(); final int touchHeight = inputView.getHeight() + containerHeight @@ -1315,7 +1322,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { ic.deleteSurroundingText(mEnteredText.length(), 0); } else if (deleteChar) { - if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { + if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { // Go back to the suggestion mode if the user canceled the // "Touch again to save". // NOTE: In gerenal, we don't revert the word when backspacing @@ -1434,7 +1441,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mVoiceProxy.handleSeparator(); // Should dismiss the "Touch again to save" message when handling separator - if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { + if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); } @@ -1485,8 +1492,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { InputConnectionCompatUtils.commitCorrection( ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); - if (mCandidateView != null) - mCandidateView.onAutoCorrectionInverted(mBestWord); + if (mSuggestionsView != null) + mSuggestionsView.onAutoCorrectionInverted(mBestWord); } } if (Keyboard.CODE_SPACE == primaryCode) { @@ -1521,7 +1528,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } public boolean isShowingPunctuationList() { - return mSettingsValues.mSuggestPuncList == mCandidateView.getSuggestions(); + return mSettingsValues.mSuggestPuncList == mSuggestionsView.getSuggestions(); } public boolean isShowingSuggestionsStrip() { @@ -1530,10 +1537,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT); } - public boolean isCandidateStripVisible() { - if (mCandidateView == null) + public boolean isSuggestionsStripVisible() { + if (mSuggestionsView == null) return false; - if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) + if (mSuggestionsView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) return true; if (!isShowingSuggestionsStrip()) return false; @@ -1555,7 +1562,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } setInputView(v); } - setSuggestionStripShown(isCandidateStripVisible()); + setSuggestionStripShown(isSuggestionsStripVisible()); updateInputViewShown(); mHandler.postUpdateSuggestions(); } @@ -1565,8 +1572,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } public void setSuggestions(SuggestedWords words) { - if (mCandidateView != null) { - mCandidateView.setSuggestions(words); + if (mSuggestionsView != null) { + mSuggestionsView.setSuggestions(words); mKeyboardSwitcher.onAutoCorrectionStateChanged( words.hasWordAboveAutoCorrectionScoreThreshold()); } @@ -1619,11 +1626,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // length == 1). if (typedWord != null) { if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid - || mCandidateView.isShowingAddToDictionaryHint()) { + || mSuggestionsView.isShowingAddToDictionaryHint()) { builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion( autoCorrectionAvailable); } else { - final SuggestedWords previousSuggestions = mCandidateView.getSuggestions(); + final SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); if (previousSuggestions == mSettingsValues.mSuggestPuncList) return; builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); @@ -1645,11 +1652,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { mBestWord = null; } - setSuggestionStripShown(isCandidateStripVisible()); + setSuggestionStripShown(isSuggestionsStripVisible()); } private boolean pickDefaultSuggestion(int separatorCode) { - // Complete any pending candidate query first + // Complete any pending suggestions query first if (mHandler.hasPendingUpdateSuggestions()) { mHandler.cancelUpdateSuggestions(); updateSuggestions(); @@ -1668,7 +1675,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public void pickSuggestionManually(int index, CharSequence suggestion) { - SuggestedWords suggestions = mCandidateView.getSuggestions(); + SuggestedWords suggestions = mSuggestionsView.getSuggestions(); mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, mSettingsValues.mWordSeparators); @@ -1684,8 +1691,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.commitCompletion(completionInfo); } mCommittedLength = suggestion.length(); - if (mCandidateView != null) { - mCandidateView.clear(); + if (mSuggestionsView != null) { + mSuggestionsView.clear(); } mKeyboardSwitcher.updateShiftState(); if (ic != null) { @@ -1780,7 +1787,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } if (showingAddToDictionaryHint) { if (mIsUserDictionaryAvaliable) { - mCandidateView.showAddToDictionaryHint(suggestion); + mSuggestionsView.showAddToDictionaryHint(suggestion); } else { mHandler.postUpdateSuggestions(); } @@ -1800,9 +1807,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final InputConnection ic = getCurrentInputConnection(); if (ic != null) { mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); - SuggestedWords suggestedWords = mCandidateView.getSuggestions(); - ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( - this, bestWord, suggestedWords), 1); + if (mSettingsValues.mEnableSuggestionSpanInsertion) { + final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); + ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( + this, bestWord, suggestedWords), 1); + } else { + ic.commitText(bestWord, 1); + } } mRecorrection.saveRecorrectionSuggestion(mWordComposer, bestWord); mHasUncommittedTypedChars = false; @@ -1836,7 +1847,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public void setPunctuationSuggestions() { setSuggestions(mSettingsValues.mSuggestPuncList); - setSuggestionStripShown(isCandidateStripVisible()); + setSuggestionStripShown(isSuggestionsStripVisible()); } private void addToUserUnigramAndBigramDictionaries(CharSequence suggestion, diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/MoreSuggestions.java index 0446fb2a8..a9e75b7b3 100644 --- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/MoreSuggestions.java @@ -43,10 +43,10 @@ public class MoreSuggestions extends Keyboard { private int mToPos; public static class MoreSuggestionsParam extends KeyboardParams { - private final int[] mWidths = new int[CandidateView.MAX_SUGGESTIONS]; - private final int[] mRowNumbers = new int[CandidateView.MAX_SUGGESTIONS]; - private final int[] mColumnOrders = new int[CandidateView.MAX_SUGGESTIONS]; - private final int[] mNumColumnsInRow = new int[CandidateView.MAX_SUGGESTIONS]; + private final int[] mWidths = new int[SuggestionsView.MAX_SUGGESTIONS]; + private final int[] mRowNumbers = new int[SuggestionsView.MAX_SUGGESTIONS]; + private final int[] mColumnOrders = new int[SuggestionsView.MAX_SUGGESTIONS]; + private final int[] mNumColumnsInRow = new int[SuggestionsView.MAX_SUGGESTIONS]; private static final int MAX_COLUMNS_IN_ROW = 3; private int mNumRows; @@ -60,7 +60,7 @@ public class MoreSuggestions extends Keyboard { int row = 0; int pos = fromPos, rowStartPos = fromPos; - final int size = Math.min(suggestions.size(), CandidateView.MAX_SUGGESTIONS); + final int size = Math.min(suggestions.size(), SuggestionsView.MAX_SUGGESTIONS); while (pos < size) { final CharSequence word = suggestions.getWord(pos); // TODO: Should take care of text x-scaling. diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java index 828490112..9fd90241b 100644 --- a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java @@ -23,17 +23,15 @@ import android.view.Gravity; import android.view.View; import android.widget.PopupWindow; -import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardView; +import com.android.inputmethod.keyboard.MoreKeysDetector; import com.android.inputmethod.keyboard.MoreKeysPanel; -import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; -import java.util.List; /** * A view that renders a virtual {@link MoreSuggestions}. It handles rendering of keys and detecting @@ -49,51 +47,6 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { private int mOriginX; private int mOriginY; - private static class SuggestionsPaneKeyDetector extends KeyDetector { - private final int mSlideAllowanceSquare; - private final int mSlideAllowanceSquareTop; - - public SuggestionsPaneKeyDetector(float slideAllowance) { - super(/* keyHysteresisDistance */0); - mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance); - // Top slide allowance is slightly longer (sqrt(2) times) than other edges. - mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2; - } - - @Override - public boolean alwaysAllowsSlidingInput() { - return true; - } - - @Override - protected int getMaxNearbyKeys() { - // No nearby key will be returned. - return 1; - } - - @Override - public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; - final int touchX = getTouchX(x); - final int touchY = getTouchY(y); - - int nearestIndex = NOT_A_KEY; - int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; - final int keyCount = keys.size(); - for (int index = 0; index < keyCount; index++) { - final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY); - if (dist < nearestDist) { - nearestIndex = index; - nearestDist = dist; - } - } - - if (allCodes != null && nearestIndex != NOT_A_KEY) - allCodes[0] = keys.get(nearestIndex).mCode; - return nearestIndex; - } - } - private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter(); private final KeyboardActionListener mSuggestionsPaneListener = @@ -128,7 +81,7 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { final Resources res = context.getResources(); // Override default ProximityKeyDetector. - mKeyDetector = new SuggestionsPaneKeyDetector(res.getDimension( + mKeyDetector = new MoreKeysDetector(res.getDimension( R.dimen.more_suggestions_slide_allowance)); // Remove gesture detector on suggestions pane setKeyPreviewPopupEnabled(false, 0); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 1e2ef4824..e99bb7016 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -82,6 +82,8 @@ public class Settings extends InputMethodSettingsActivity "pref_key_preview_popup_dismiss_delay"; public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict"; + public static final String PREF_KEY_ENABLE_SPAN_INSERT = + "enable_span_insert"; public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; @@ -117,6 +119,7 @@ public class Settings extends InputMethodSettingsActivity // Prediction: use bigrams to predict the next word when there is no input for it yet public final boolean mBigramPredictionEnabled; public final boolean mUseContactsDict; + public final boolean mEnableSuggestionSpanInsertion; private final boolean mShowSettingsKey; private final boolean mVoiceKeyEnabled; @@ -179,6 +182,8 @@ public class Settings extends InputMethodSettingsActivity && isBigramPredictionEnabled(prefs, res); mAutoCorrectionThreshold = getAutoCorrectionThreshold(prefs, res); mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true); + mEnableSuggestionSpanInsertion = + prefs.getBoolean(Settings.PREF_KEY_ENABLE_SPAN_INSERT, true); final boolean defaultShowSettingsKey = res.getBoolean( R.bool.config_default_show_settings_key); mShowSettingsKey = isShowSettingsKeyOption(res) @@ -426,8 +431,10 @@ public class Settings extends InputMethodSettingsActivity final boolean showBigramSuggestionsOption = res.getBoolean( R.bool.config_enable_bigram_suggestions_option); if (!showBigramSuggestionsOption) { - textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_SUGGESTIONS)); - textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_PREDICTIONS)); + textCorrectionGroup.removePreference(mBigramSuggestion); + if (null != mBigramPrediction) { + textCorrectionGroup.removePreference(mBigramPrediction); + } } final boolean showUsabilityModeStudyOption = res.getBoolean( diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 87d854940..56f14de57 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; @@ -138,7 +139,7 @@ public class SubtypeSwitcher { mEnabledLanguagesOfCurrentInputMethod.clear(); mEnabledKeyboardSubtypesOfCurrentInputMethod.clear(); for (InputMethodSubtypeCompatWrapper ims : mAllEnabledSubtypesOfCurrentInputMethod) { - final String locale = ims.getLocale(); + final String locale = getSubtypeLocale(ims); final String mode = ims.getMode(); mLocaleSplitter.setString(locale); if (mLocaleSplitter.hasNext()) { @@ -167,7 +168,7 @@ public class SubtypeSwitcher { Log.d(TAG, "Update shortcut IME from : " + (mShortcutInputMethodInfo == null ? "<null>" : mShortcutInputMethodInfo.getId()) + ", " - + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale() + + (mShortcutSubtype == null ? "<null>" : (getSubtypeLocale(mShortcutSubtype) + ", " + mShortcutSubtype.getMode()))); } // TODO: Update an icon for shortcut IME @@ -189,11 +190,17 @@ public class SubtypeSwitcher { Log.d(TAG, "Update shortcut IME to : " + (mShortcutInputMethodInfo == null ? "<null>" : mShortcutInputMethodInfo.getId()) + ", " - + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale() + + (mShortcutSubtype == null ? "<null>" : (getSubtypeLocale(mShortcutSubtype) + ", " + mShortcutSubtype.getMode()))); } } + private static String getSubtypeLocale(InputMethodSubtypeCompatWrapper subtype) { + final String keyboardLocale = subtype.getExtraValueOf( + LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE); + return keyboardLocale != null ? keyboardLocale : subtype.getLocale(); + } + // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. public void updateSubtype(InputMethodSubtypeCompatWrapper newSubtype) { final String newLocale; @@ -206,7 +213,7 @@ public class SubtypeSwitcher { newLocale = "en_US"; newMode = KEYBOARD_MODE; } else { - newLocale = newSubtype.getLocale(); + newLocale = getSubtypeLocale(newSubtype); newMode = newSubtype.getMode(); } if (DBG) { @@ -257,6 +264,15 @@ public class SubtypeSwitcher { // as it is not the current input mode. mVoiceInputWrapper.reset(); } + final String packageName = mService.getPackageName(); + int version = -1; + try { + version = mService.getPackageManager().getPackageInfo( + packageName, 0).versionCode; + } catch (NameNotFoundException e) { + } + throw new RuntimeException("Unknown subtype mode: " + version + ", " + packageName + + ", " + mVoiceInputWrapper); } } @@ -332,7 +348,7 @@ public class SubtypeSwitcher { final String imiPackageName = imi.getPackageName(); if (DBG) { Log.d(TAG, "Update icons of IME: " + imiPackageName + "," - + subtype.getLocale() + "," + subtype.getMode()); + + getSubtypeLocale(subtype) + "," + subtype.getMode()); } if (subtype != null) { return pm.getDrawable(imiPackageName, subtype.getIconResId(), diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 29b629576..93933f1bc 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -371,24 +371,14 @@ public class Suggest implements Dictionary.WordCallback { // Apply quick fix only for the typed word. if (mQuickFixesEnabled) { final String lowerCaseTypedWord = typedWordString.toLowerCase(); - CharSequence tempAutoText = capitalizeWord( - mIsAllUpperCase, mIsFirstCharCapitalized, AutoText.get( - lowerCaseTypedWord, 0, lowerCaseTypedWord.length(), view)); - // TODO: cleanup canAdd // Is there an AutoText (also known as Quick Fixes) correction? // Capitalize as needed - boolean canAdd = tempAutoText != null; - // Is that correction already the current prediction (or original word)? - canAdd &= !TextUtils.equals(tempAutoText, typedWord); - // Is that correction already the next predicted word? - if (canAdd && mSuggestions.size() > 0 && mCorrectionMode != CORRECTION_BASIC) { - canAdd &= !TextUtils.equals(tempAutoText, mSuggestions.get(0)); - } - if (canAdd) { - if (DBG) { - Log.d(TAG, "Auto corrected by AUTOTEXT."); + autoText = capitalizeWord(mIsAllUpperCase, mIsFirstCharCapitalized, AutoText.get( + lowerCaseTypedWord, 0, lowerCaseTypedWord.length(), view)); + if (DBG) { + if (autoText != null) { + Log.d(TAG, "Auto corrected by AUTOTEXT: " + typedWord + " -> " + autoText); } - autoText = tempAutoText; } } } diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/SuggestionsView.java index 0d355d01e..10cd73dd3 100644 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/SuggestionsView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of @@ -50,6 +50,7 @@ import android.widget.TextView; import com.android.inputmethod.compat.FrameLayoutCompatUtils; import com.android.inputmethod.compat.LinearLayoutCompatUtils; import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.MoreKeysPanel; import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; @@ -57,7 +58,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; import java.util.List; -public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener { +public class SuggestionsView extends LinearLayout implements OnClickListener, OnLongClickListener { public interface Listener { public boolean addWordToDictionary(String word); public void pickSuggestionManually(int index, CharSequence word); @@ -68,12 +69,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private static final boolean DBG = LatinImeLogger.sDBG; - private final ViewGroup mCandidatesPlacer; - private final ViewGroup mCandidatesStrip; - // TODO: Remove these pane related fields and stuffs. - private ViewGroup mCandidatesPane; - private ViewGroup mCandidatesPaneContainer; - private View mKeyboardView; + private final ViewGroup mSuggestionsPlacer; + private final ViewGroup mSuggestionsStrip; + private KeyboardView mKeyboardView; private final View mMoreSuggestionsContainer; private final MoreSuggestionsView mMoreSuggestionsView; @@ -91,32 +89,31 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private SuggestedWords mSuggestions = SuggestedWords.EMPTY; private boolean mShowingAutoCorrectionInverted; - private final SuggestionsStripParams mStripParams; - private final SuggestionsPaneParams mPaneParams; + private final SuggestionsViewParams mParams; private static final float MIN_TEXT_XSCALE = 0.70f; private final UiHandler mHandler = new UiHandler(this); - private static class UiHandler extends StaticInnerHandlerWrapper<CandidateView> { + 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(CandidateView outerInstance) { + public UiHandler(SuggestionsView outerInstance) { super(outerInstance); } @Override public void dispatchMessage(Message msg) { - final CandidateView candidateView = getOuterInstance(); + final SuggestionsView suggestionsView = getOuterInstance(); switch (msg.what) { case MSG_HIDE_PREVIEW: - candidateView.hidePreview(); + suggestionsView.hidePreview(); break; case MSG_UPDATE_SUGGESTION: - candidateView.updateSuggestions(); + suggestionsView.updateSuggestions(); break; } } @@ -146,133 +143,26 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } - private static class CandidateViewParams { + private static class SuggestionsViewParams { + private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3; + private static final int DEFAULT_CENTER_SUGGESTION_PERCENTILE = 40; + private static final int PUNCTUATIONS_IN_STRIP = 6; + public final int mPadding; public final int mDividerWidth; - public final int mDividerHeight; - public final int mCandidateStripHeight; - - protected final List<TextView> mWords; - protected final List<View> mDividers; - protected final List<TextView> mInfos; + public final int mSuggestionsStripHeight; + public final int mSuggestionsCountInStrip; - protected CandidateViewParams(List<TextView> words, List<View> dividers, - List<TextView> infos) { - mWords = words; - mDividers = dividers; - mInfos = infos; - - final TextView word = words.get(0); - final View divider = dividers.get(0); - mPadding = word.getCompoundPaddingLeft() + word.getCompoundPaddingRight(); - divider.measure( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - mDividerWidth = divider.getMeasuredWidth(); - mDividerHeight = divider.getMeasuredHeight(); - - final Resources res = word.getResources(); - mCandidateStripHeight = res.getDimensionPixelSize(R.dimen.candidate_strip_height); - } - } - - private static class SuggestionsPaneParams extends CandidateViewParams { - public SuggestionsPaneParams(List<TextView> words, List<View> dividers, - List<TextView> infos) { - super(words, dividers, infos); - } - - public int layout(SuggestedWords suggestions, ViewGroup paneView, int from, int textColor, - int paneWidth) { - final int count = Math.min(mWords.size(), suggestions.size()); - View centeringFrom = null, lastView = null; - int x = 0, y = 0; - for (int index = from; index < count; index++) { - final int pos = index; - final TextView word = mWords.get(pos); - final View divider = mDividers.get(pos); - final TextPaint paint = word.getPaint(); - word.setTextColor(textColor); - final CharSequence styled = suggestions.getWord(pos); - - final TextView info; - if (DBG) { - final CharSequence debugInfo = getDebugInfo(suggestions, index); - if (debugInfo != null) { - info = mInfos.get(index); - info.setText(debugInfo); - } else { - info = null; - } - } else { - info = null; - } - - final CharSequence text; - final float scaleX; - paint.setTextScaleX(1.0f); - final int textWidth = getTextWidth(styled, paint); - int available = paneWidth - x - mPadding; - if (textWidth >= available) { - // Needs new row, centering previous row. - centeringCandidates(paneView, centeringFrom, lastView, x, paneWidth); - x = 0; - y += mCandidateStripHeight; - } - if (x != 0) { - // Add divider if this isn't the left most suggestion in current row. - paneView.addView(divider); - FrameLayoutCompatUtils.placeViewAt(divider, x, y - + (mCandidateStripHeight - mDividerHeight) / 2, mDividerWidth, - mDividerHeight); - x += mDividerWidth; - } - available = paneWidth - x - mPadding; - text = getEllipsizedText(styled, available, paint); - scaleX = paint.getTextScaleX(); - word.setText(text); - word.setTextScaleX(scaleX); - paneView.addView(word); - lastView = word; - if (x == 0) - centeringFrom = word; - word.measure(ViewGroup.LayoutParams.WRAP_CONTENT, - MeasureSpec.makeMeasureSpec(mCandidateStripHeight, MeasureSpec.EXACTLY)); - final int width = word.getMeasuredWidth(); - final int height = word.getMeasuredHeight(); - FrameLayoutCompatUtils.placeViewAt(word, x, y + (mCandidateStripHeight - height) - / 2, width, height); - x += width; - if (info != null) { - paneView.addView(info); - lastView = info; - info.measure(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - final int infoWidth = info.getMeasuredWidth(); - FrameLayoutCompatUtils.placeViewAt( - info, x - infoWidth, y, infoWidth, info.getMeasuredHeight()); - } - } - if (x != 0) { - // Centering last candidates row. - centeringCandidates(paneView, centeringFrom, lastView, x, paneWidth); - } - - return count - from; - } - } - - private static class SuggestionsStripParams extends CandidateViewParams { - private static final int DEFAULT_CANDIDATE_COUNT_IN_STRIP = 3; - private static final int DEFAULT_CENTER_CANDIDATE_PERCENTILE = 40; - private static final int PUNCTUATIONS_IN_STRIP = 6; + private final List<TextView> mWords; + private final List<View> mDividers; + private final List<TextView> mInfos; private final int mColorTypedWord; private final int mColorAutoCorrect; - private final int mColorSuggestedCandidate; - public final int mCandidateCountInStrip; - private final float mCenterCandidateWeight; - private final int mCenterCandidateIndex; - private final Drawable mMoreCandidateHint; + private final int mColorSuggested; + private final float mCenterSuggestionWeight; + private final int mCenterSuggestionIndex; + private final Drawable mMoreSuggestionsHint; private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); @@ -293,41 +183,49 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private final TextView mHintToSaveView; private final CharSequence mHintToSaveText; - public SuggestionsStripParams(Context context, AttributeSet attrs, int defStyle, + public SuggestionsViewParams(Context context, AttributeSet attrs, int defStyle, List<TextView> words, List<View> dividers, List<TextView> infos) { - super(words, dividers, infos); + mWords = words; + mDividers = dividers; + mInfos = infos; + + final TextView word = words.get(0); + final View divider = dividers.get(0); + mPadding = word.getCompoundPaddingLeft() + word.getCompoundPaddingRight(); + divider.measure( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + mDividerWidth = divider.getMeasuredWidth(); + + final Resources res = word.getResources(); + mSuggestionsStripHeight = res.getDimensionPixelSize(R.dimen.suggestions_strip_height); + final TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.CandidateView, defStyle, R.style.CandidateViewStyle); - mSuggestionStripOption = a.getInt(R.styleable.CandidateView_suggestionStripOption, 0); - mColorTypedWord = a.getColor(R.styleable.CandidateView_colorTypedWord, 0); - mColorAutoCorrect = a.getColor(R.styleable.CandidateView_colorAutoCorrect, 0); - mColorSuggestedCandidate = a.getColor(R.styleable.CandidateView_colorSuggested, 0); - mCandidateCountInStrip = a.getInt( - R.styleable.CandidateView_candidateCountInStrip, - DEFAULT_CANDIDATE_COUNT_IN_STRIP); - mCenterCandidateWeight = a.getInt( - R.styleable.CandidateView_centerCandidatePercentile, - DEFAULT_CENTER_CANDIDATE_PERCENTILE) / 100.0f; + attrs, R.styleable.SuggestionsView, defStyle, R.style.SuggestionsViewStyle); + mSuggestionStripOption = a.getInt(R.styleable.SuggestionsView_suggestionStripOption, 0); + mColorTypedWord = a.getColor(R.styleable.SuggestionsView_colorTypedWord, 0); + mColorAutoCorrect = a.getColor(R.styleable.SuggestionsView_colorAutoCorrect, 0); + mColorSuggested = a.getColor(R.styleable.SuggestionsView_colorSuggested, 0); + mSuggestionsCountInStrip = a.getInt( + R.styleable.SuggestionsView_suggestionsCountInStrip, + DEFAULT_SUGGESTIONS_COUNT_IN_STRIP); + mCenterSuggestionWeight = a.getInt( + R.styleable.SuggestionsView_centerSuggestionPercentile, + DEFAULT_CENTER_SUGGESTION_PERCENTILE) / 100.0f; a.recycle(); - mCenterCandidateIndex = mCandidateCountInStrip / 2; - final Resources res = context.getResources(); - mMoreCandidateHint = res.getDrawable(R.drawable.more_suggestions_hint); + mCenterSuggestionIndex = mSuggestionsCountInStrip / 2; + mMoreSuggestionsHint = res.getDrawable(R.drawable.more_suggestions_hint); mInvertedForegroundColorSpan = new ForegroundColorSpan(mColorTypedWord ^ 0x00ffffff); mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord); final LayoutInflater inflater = LayoutInflater.from(context); - mWordToSaveView = (TextView)inflater.inflate(R.layout.candidate_word, null); - mHintToSaveView = (TextView)inflater.inflate(R.layout.candidate_word, null); + 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); } - public int getTextColor() { - return mColorTypedWord; - } - - private CharSequence getStyledCandidateWord(SuggestedWords suggestions, int pos) { + private CharSequence getStyledSuggestionWord(SuggestedWords suggestions, int pos) { final CharSequence word = suggestions.getWord(pos); final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions); final boolean isTypedWordValid = pos == 0 && suggestions.mTypedWordValid; @@ -355,24 +253,24 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more // suggestions. final int centerPos = willAutoCorrect(suggestions) ? 1 : 0; - if (index == mCenterCandidateIndex) { + if (index == mCenterSuggestionIndex) { return centerPos; } else if (index == centerPos) { - return mCenterCandidateIndex; + return mCenterSuggestionIndex; } else { return index; } } - private int getCandidateTextColor(int index, SuggestedWords suggestions, int pos) { + private int getSuggestionTextColor(int index, SuggestedWords suggestions, int pos) { // TODO: Need to revisit this logic with bigram suggestions - final boolean isSuggestedCandidate = (pos != 0); + final boolean isSuggested = (pos != 0); final int color; - if (index == mCenterCandidateIndex && willAutoCorrect(suggestions)) { + if (index == mCenterSuggestionIndex && willAutoCorrect(suggestions)) { color = mColorAutoCorrect; - } else if (isSuggestedCandidate) { - color = mColorSuggestedCandidate; + } else if (isSuggested) { + color = mColorSuggested; } else { color = mColorTypedWord; } @@ -401,13 +299,14 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo return word; } - public int layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer, + public void layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer, int stripWidth) { if (suggestions.isPunctuationSuggestions()) { - return layoutPunctuationSuggestions(suggestions, stripView); + layoutPunctuationSuggestions(suggestions, stripView); + return; } - final int countInStrip = mCandidateCountInStrip; + final int countInStrip = mSuggestionsCountInStrip; setupTexts(suggestions, countInStrip); mMoreSuggestionsAvailable = (suggestions.size() > countInStrip); int x = 0; @@ -416,34 +315,34 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo if (index != 0) { final View divider = mDividers.get(pos); - // Add divider if this isn't the left most suggestion in candidate strip. + // Add divider if this isn't the left most suggestion in suggestions strip. stripView.addView(divider); x += divider.getMeasuredWidth(); } final CharSequence styled = mTexts.get(pos); final TextView word = mWords.get(pos); - if (index == mCenterCandidateIndex && mMoreSuggestionsAvailable) { + if (index == mCenterSuggestionIndex && mMoreSuggestionsAvailable) { // TODO: This "more suggestions hint" should have nicely designed icon. word.setCompoundDrawablesWithIntrinsicBounds( - null, null, null, mMoreCandidateHint); + null, null, null, mMoreSuggestionsHint); // HACK: To align with other TextView that has no compound drawables. - word.setCompoundDrawablePadding(-mMoreCandidateHint.getIntrinsicHeight()); + word.setCompoundDrawablePadding(-mMoreSuggestionsHint.getIntrinsicHeight()); } else { word.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); } - // Disable this candidate if the suggestion is null or empty. + // Disable this suggestion if the suggestion is null or empty. word.setEnabled(!TextUtils.isEmpty(styled)); - word.setTextColor(getCandidateTextColor(index, suggestions, pos)); - final int width = getCandidateWidth(index, stripWidth); + word.setTextColor(getSuggestionTextColor(index, suggestions, pos)); + final int width = getSuggestionWidth(index, stripWidth); final CharSequence text = getEllipsizedText(styled, width, word.getPaint()); final float scaleX = word.getTextScaleX(); word.setText(text); // TextView.setText() resets text scale x to 1.0. word.setTextScaleX(scaleX); stripView.addView(word); setLayoutWeight( - word, getCandidateWeight(index), ViewGroup.LayoutParams.MATCH_PARENT); + word, getSuggestionWeight(index), ViewGroup.LayoutParams.MATCH_PARENT); x += word.getMeasuredWidth(); if (DBG) { @@ -461,22 +360,21 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } } - return countInStrip; } - private int getCandidateWidth(int index, int maxWidth) { - final int paddings = mPadding * mCandidateCountInStrip; - final int dividers = mDividerWidth * (mCandidateCountInStrip - 1); + private int getSuggestionWidth(int index, int maxWidth) { + final int paddings = mPadding * mSuggestionsCountInStrip; + final int dividers = mDividerWidth * (mSuggestionsCountInStrip - 1); final int availableWidth = maxWidth - paddings - dividers; - return (int)(availableWidth * getCandidateWeight(index)); + return (int)(availableWidth * getSuggestionWeight(index)); } - private float getCandidateWeight(int index) { - if (index == mCenterCandidateIndex) { - return mCenterCandidateWeight; + private float getSuggestionWeight(int index) { + if (index == mCenterSuggestionIndex) { + return mCenterSuggestionWeight; } else { // TODO: Revisit this for cases of 5 or more suggestions - return (1.0f - mCenterCandidateWeight) / (mCandidateCountInStrip - 1); + return (1.0f - mCenterSuggestionWeight) / (mSuggestionsCountInStrip - 1); } } @@ -484,7 +382,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo mTexts.clear(); final int count = Math.min(suggestions.size(), countInStrip); for (int pos = 0; pos < count; pos++) { - final CharSequence styled = getStyledCandidateWord(suggestions, pos); + final CharSequence styled = getStyledSuggestionWord(suggestions, pos); mTexts.add(styled); } for (int pos = count; pos < countInStrip; pos++) { @@ -493,11 +391,11 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } - private int layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) { + private void layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) { final int countInStrip = Math.min(suggestions.size(), PUNCTUATIONS_IN_STRIP); for (int index = 0; index < countInStrip; index++) { if (index != 0) { - // Add divider if this isn't the left most suggestion in candidate strip. + // Add divider if this isn't the left most suggestion in suggestions strip. stripView.addView(mDividers.get(index)); } @@ -509,10 +407,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo word.setTextScaleX(1.0f); word.setCompoundDrawables(null, null, null, null); stripView.addView(word); - setLayoutWeight(word, 1.0f, mCandidateStripHeight); + setLayoutWeight(word, 1.0f, mSuggestionsStripHeight); } mMoreSuggestionsAvailable = false; - return countInStrip; } public void layoutAddToDictionaryHint(CharSequence word, ViewGroup stripView, @@ -521,14 +418,14 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final TextView wordView = mWordToSaveView; wordView.setTextColor(mColorTypedWord); - final int wordWidth = (int)(width * mCenterCandidateWeight); + final int wordWidth = (int)(width * mCenterSuggestionWeight); final CharSequence text = getEllipsizedText(word, wordWidth, wordView.getPaint()); final float wordScaleX = wordView.getTextScaleX(); wordView.setTag(word); wordView.setText(text); wordView.setTextScaleX(wordScaleX); stripView.addView(wordView); - setLayoutWeight(wordView, mCenterCandidateWeight, ViewGroup.LayoutParams.MATCH_PARENT); + setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT); stripView.addView(mDividers.get(0)); @@ -540,62 +437,60 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo hintView.setTextScaleX(hintScaleX); stripView.addView(hintView); setLayoutWeight( - hintView, 1.0f - mCenterCandidateWeight, ViewGroup.LayoutParams.MATCH_PARENT); + hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT); } } /** - * Construct a CandidateView for showing suggested words for completion. + * Construct a {@link SuggestionsView} for showing suggested words for completion. * @param context * @param attrs */ - public CandidateView(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.candidateViewStyle); + public SuggestionsView(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.suggestionsViewStyle); } - public CandidateView(Context context, AttributeSet attrs, int defStyle) { + public SuggestionsView(Context context, AttributeSet attrs, int defStyle) { // Note: Up to version 10 (Gingerbread) of the API, LinearLayout doesn't have 3-argument // constructor. // TODO: Call 3-argument constructor, super(context, attrs, defStyle), when we abandon // backward compatibility with the version 10 or earlier of the API. super(context, attrs); - if (defStyle != R.attr.candidateViewStyle) { + if (defStyle != R.attr.suggestionsViewStyle) { throw new IllegalArgumentException( - "can't accept defStyle other than R.attr.candidateViewStyle: defStyle=" + "can't accept defStyle other than R.attr.suggestionsViewStyle: defStyle=" + defStyle); } setBackgroundDrawable(LinearLayoutCompatUtils.getBackgroundDrawable( - context, attrs, defStyle, R.style.CandidateViewStyle)); + context, attrs, defStyle, R.style.SuggestionsViewStyle)); final LayoutInflater inflater = LayoutInflater.from(context); - inflater.inflate(R.layout.candidates_strip, this); + inflater.inflate(R.layout.suggestions_strip, this); mPreviewPopup = new PopupWindow(context); - mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null); + mPreviewText = (TextView) inflater.inflate(R.layout.suggestion_preview, null); mPreviewPopup.setWindowLayoutMode( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); mPreviewPopup.setContentView(mPreviewText); mPreviewPopup.setBackgroundDrawable(null); - mCandidatesPlacer = (ViewGroup)findViewById(R.id.candidates_placer); - mCandidatesStrip = (ViewGroup)findViewById(R.id.candidates_strip); + mSuggestionsPlacer = (ViewGroup)findViewById(R.id.suggestions_placer); + mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip); for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) { - final TextView word = (TextView)inflater.inflate(R.layout.candidate_word, null); + final TextView word = (TextView)inflater.inflate(R.layout.suggestion_word, null); word.setTag(pos); word.setOnClickListener(this); word.setOnLongClickListener(this); mWords.add(word); - final View divider = inflater.inflate(R.layout.candidate_divider, null); + final View divider = inflater.inflate(R.layout.suggestion_divider, null); divider.setTag(pos); divider.setOnClickListener(this); mDividers.add(divider); - mInfos.add((TextView)inflater.inflate(R.layout.candidate_info, null)); + mInfos.add((TextView)inflater.inflate(R.layout.suggestion_info, null)); } - mStripParams = new SuggestionsStripParams(context, attrs, defStyle, mWords, mDividers, - mInfos); - mPaneParams = new SuggestionsPaneParams(mWords, mDividers, mInfos); - mStripParams.mWordToSaveView.setOnClickListener(this); + mParams = new SuggestionsViewParams(context, attrs, defStyle, mWords, mDividers, mInfos); + mParams.mWordToSaveView.setOnClickListener(this); mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null); mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer @@ -613,12 +508,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo */ public void setListener(Listener listener, View inputView) { mListener = listener; - mKeyboardView = inputView.findViewById(R.id.keyboard_view); - mCandidatesPane = FrameLayoutCompatUtils.getPlacer( - (ViewGroup)inputView.findViewById(R.id.candidates_pane)); - mCandidatesPane.setOnClickListener(this); - mCandidatesPaneContainer = (ViewGroup)inputView.findViewById( - R.id.candidates_pane_container); + mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view); } public void setSuggestions(SuggestedWords suggestions) { @@ -634,13 +524,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private void updateSuggestions() { clear(); - closeCandidatesPane(); if (mSuggestions.size() == 0) return; - final int width = getWidth(); - final int countInStrip = mStripParams.layout( - mSuggestions, mCandidatesStrip, mCandidatesPlacer, width); + mParams.layout(mSuggestions, mSuggestionsStrip, mSuggestionsPlacer, getWidth()); } private static CharSequence getDebugInfo(SuggestedWords suggestions, int pos) { @@ -666,26 +553,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } - private static void centeringCandidates(ViewGroup parent, View from, View to, int width, - int parentWidth) { - final int fromIndex = parent.indexOfChild(from); - final int toIndex = parent.indexOfChild(to); - final int offset = (parentWidth - width) / 2; - for (int index = fromIndex; index <= toIndex; index++) { - offsetMargin(parent.getChildAt(index), offset, 0); - } - } - - private static void offsetMargin(View v, int dx, int dy) { - if (v == null) - return; - final ViewGroup.LayoutParams lp = v.getLayoutParams(); - if (lp instanceof ViewGroup.MarginLayoutParams) { - final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp; - mlp.setMargins(mlp.leftMargin + dx, mlp.topMargin + dy, 0, 0); - } - } - private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) { paint.setTextScaleX(1.0f); final int width = getTextWidth(text, paint); @@ -748,27 +615,8 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } - private void expandCandidatesPane() { - mCandidatesPaneContainer.setMinimumHeight(mKeyboardView.getMeasuredHeight()); - mCandidatesPaneContainer.setVisibility(VISIBLE); - mKeyboardView.setVisibility(GONE); - } - - private void closeCandidatesPane() { - mCandidatesPaneContainer.setVisibility(GONE); - mKeyboardView.setVisibility(VISIBLE); - } - - private void toggleCandidatesPane() { - if (mCandidatesPaneContainer.getVisibility() == VISIBLE) { - closeCandidatesPane(); - } else { - expandCandidatesPane(); - } - } - public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) { - final CharSequence inverted = mStripParams.getInvertedText(autoCorrectedWord); + final CharSequence inverted = mParams.getInvertedText(autoCorrectedWord); if (inverted == null) return; final TextView tv = mWords.get(1); @@ -777,13 +625,13 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } public boolean isShowingAddToDictionaryHint() { - return mCandidatesStrip.getChildCount() > 0 - && mCandidatesStrip.getChildAt(0) == mStripParams.mWordToSaveView; + return mSuggestionsStrip.getChildCount() > 0 + && mSuggestionsStrip.getChildAt(0) == mParams.mWordToSaveView; } public void showAddToDictionaryHint(CharSequence word) { clear(); - mStripParams.layoutAddToDictionaryHint(word, mCandidatesStrip, getWidth()); + mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth()); } public boolean dismissAddToDictionaryHint() { @@ -800,12 +648,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo public void clear() { mShowingAutoCorrectionInverted = false; - mCandidatesPlacer.removeAllViews(); - mCandidatesPlacer.addView(mCandidatesStrip); - mCandidatesStrip.removeAllViews(); - mCandidatesPane.removeAllViews(); - closeCandidatesPane(); - mMoreSuggestionsWindow.dismiss(); + mSuggestionsPlacer.removeAllViews(); + mSuggestionsPlacer.addView(mSuggestionsStrip); + mSuggestionsStrip.removeAllViews(); + dismissMoreSuggestions(); } private void hidePreview() { @@ -817,7 +663,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo return; final TextView previewText = mPreviewText; - previewText.setTextColor(mStripParams.mColorTypedWord); + previewText.setTextColor(mParams.mColorTypedWord); previewText.setText(word); previewText.measure( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -838,7 +684,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private void addToDictionary(CharSequence word) { if (mListener.addWordToDictionary(word.toString())) { final CharSequence message = getContext().getString(R.string.added_word, word); - showPreview(mStripParams.mWordToSaveView, message); + showPreview(mParams.mWordToSaveView, message); } } @@ -849,13 +695,13 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final int index = requestCode; final CharSequence word = mSuggestions.getWord(index); mListener.pickSuggestionManually(index, word); - mMoreSuggestionsView.dismissMoreKeysPanel(); + dismissMoreSuggestions(); return true; } @Override public void onCancelInput() { - mMoreSuggestionsView.dismissMoreKeysPanel(); + dismissMoreSuggestions(); } }; @@ -863,17 +709,22 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo new MoreKeysPanel.Controller() { @Override public boolean dismissMoreKeysPanel() { - if (mMoreSuggestionsWindow.isShowing()) { - mMoreSuggestionsWindow.dismiss(); - return true; - } - return false; + return dismissMoreSuggestions(); } }; + private boolean dismissMoreSuggestions() { + if (mMoreSuggestionsWindow.isShowing()) { + mMoreSuggestionsWindow.dismiss(); + mKeyboardView.dimEntireKeyboard(false); + return true; + } + return false; + } + @Override public boolean onLongClick(View view) { - final SuggestionsStripParams params = mStripParams; + final SuggestionsViewParams params = mParams; if (params.mMoreSuggestionsAvailable) { final int stripWidth = getWidth(); final View container = mMoreSuggestionsContainer; @@ -883,7 +734,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo // TODO: Revise how we determine the height final int maxHeight = dm.heightPixels - mKeyboardView.getHeight() - getHeight() * 3; final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; - builder.layout(mSuggestions, params.mCandidateCountInStrip, maxWidth, maxHeight); + builder.layout(mSuggestions, params.mSuggestionsCountInStrip, maxWidth, maxHeight); mMoreSuggestionsView.setKeyboard(builder.build()); container.measure( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -901,7 +752,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo tracker.onShowMoreKeysPanel( translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel); view.setPressed(false); - // TODO: Should gray out the keyboard here as well? + mKeyboardView.dimEntireKeyboard(true); return true; } return false; @@ -940,17 +791,12 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo @Override public void onClick(View view) { - if (view == mStripParams.mWordToSaveView) { + if (view == mParams.mWordToSaveView) { addToDictionary((CharSequence)view.getTag()); clear(); return; } - if (view == mCandidatesPane) { - closeCandidatesPane(); - return; - } - final Object tag = view.getTag(); if (!(tag instanceof Integer)) return; @@ -960,9 +806,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final CharSequence word = mSuggestions.getWord(index); mListener.pickSuggestionManually(index, word); - // Because some punctuation letters are not treated as word separator depending on locale, - // {@link #setSuggestions} might not be called and candidates pane left opened. - closeCandidatesPane(); } @Override diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index 60a4cfb38..6263ebefa 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -16,15 +16,7 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; -import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; -import com.android.inputmethod.compat.InputTypeCompatUtils; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardId; - import android.content.Context; -import android.content.res.Configuration; import android.content.res.Resources; import android.inputmethodservice.InputMethodService; import android.os.AsyncTask; @@ -37,6 +29,13 @@ import android.text.format.DateUtils; import android.util.Log; import android.view.inputmethod.EditorInfo; +import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; +import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; +import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; +import com.android.inputmethod.compat.InputTypeCompatUtils; +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardId; + import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -47,7 +46,6 @@ import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -175,21 +173,21 @@ public class Utils { // If user selected aggressive auto correction mode, there is no need to use the safety // net. if (suggest.isAggressiveAutoCorrectionMode()) return false; - CharSequence typedWord = suggestions.getWord(0); + final CharSequence typedWord = suggestions.getWord(0); // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH, // we should not use net because relatively edit distance can be big. if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) return false; - CharSequence candidateWord = suggestions.getWord(1); + final CharSequence suggestionWord = suggestions.getWord(1); final int typedWordLength = typedWord.length(); final int maxEditDistanceOfNativeDictionary = typedWordLength < 5 ? 2 : typedWordLength / 2; - final int distance = Utils.editDistance(typedWord, candidateWord); + final int distance = Utils.editDistance(typedWord, suggestionWord); if (DBG) { Log.d(TAG, "Autocorrected edit distance = " + distance + ", " + maxEditDistanceOfNativeDictionary); } if (distance > maxEditDistanceOfNativeDictionary) { if (DBG) { - Log.d(TAG, "Safety net: before = " + typedWord + ", after = " + candidateWord); + Log.d(TAG, "Safety net: before = " + typedWord + ", after = " + suggestionWord); Log.w(TAG, "(Error) The edit distance of this correction exceeds limit. " + "Turning off auto-correction."); } @@ -717,7 +715,7 @@ public class Utils { // Don't cache suggestions.size(), since we may be removing items while (i < suggestions.size()) { final CharSequence cur = suggestions.get(i); - // Compare each candidate with each previous candidate + // Compare each suggestion with each previous suggestion for (int j = 0; j < i; j++) { CharSequence previous = suggestions.get(j); if (TextUtils.equals(cur, previous)) { |