diff options
Diffstat (limited to 'java/src')
9 files changed, 317 insertions, 239 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 19795e764..cdf07ed70 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -41,6 +41,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -225,7 +226,7 @@ public class Keyboard { public int GRID_WIDTH; public int GRID_HEIGHT; - public final ArrayList<Key> mKeys = new ArrayList<Key>(); + public final HashSet<Key> mKeys = new HashSet<Key>(); public final ArrayList<Key> mShiftKeys = new ArrayList<Key>(); public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>(); public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); @@ -316,8 +317,8 @@ public class Keyboard { private int mMaxHeightCount = 0; private int mMaxWidthCount = 0; - private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); - private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); + private final HashMap<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); + private final HashMap<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); private void clearHistogram() { mMostCommonKeyHeight = 0; @@ -329,7 +330,8 @@ public class Keyboard { mWidthHistogram.clear(); } - private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) { + private static int updateHistogramCounter(HashMap<Integer, Integer> histogram, + Integer key) { final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1; histogram.put(key, count); return count; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 4c65522ec..847174c0a 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -95,6 +95,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // The maximum key label width in the proportion to the key width. private static final float MAX_LABEL_RATIO = 0.90f; + private final static int ALPHA_OPAQUE = 255; + // Main keyboard private Keyboard mKeyboard; private final KeyDrawParams mKeyDrawParams; @@ -201,6 +203,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { public int mKeyHintLetterSize; public int mKeyShiftedLetterHintSize; public int mKeyHintLabelSize; + public int mAnimAlpha; public KeyDrawParams(TypedArray a) { mKeyBackground = a.getDrawable(R.styleable.KeyboardView_keyBackground); @@ -256,6 +259,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mKeyShiftedLetterHintSize = (int)(keyHeight * mKeyShiftedLetterHintRatio); mKeyHintLabelSize = (int)(keyHeight * mKeyHintLabelRatio); } + + public void brendAlpha(Paint paint) { + final int color = paint.getColor(); + paint.setARGB((paint.getAlpha() * mAnimAlpha) / ALPHA_OPAQUE, + Color.red(color), Color.green(color), Color.blue(color)); + } } /* package */ static class KeyPreviewDrawParams { @@ -343,7 +352,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mPaint.setAntiAlias(true); mPaint.setTextAlign(Align.CENTER); - mPaint.setAlpha(255); } // Read fraction value in TypedArray as float. @@ -492,6 +500,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { final int keyDrawY = key.mY + getPaddingTop(); canvas.translate(keyDrawX, keyDrawY); + params.mAnimAlpha = ALPHA_OPAQUE; if (!key.isSpacer()) { onDrawKeyBackground(key, canvas, params); } @@ -535,6 +544,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // Draw key label. final Drawable icon = key.getIcon(mKeyboard.mIconsSet); + if (icon != null) { + icon.setAlpha(params.mAnimAlpha); + } float positionX = centerX; if (key.mLabel != null) { final String label = key.mLabel; @@ -589,6 +601,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // Make label invisible paint.setColor(Color.TRANSPARENT); } + params.brendAlpha(paint); canvas.drawText(label, 0, label.length(), positionX, baseline, paint); // Turn off drop shadow and reset x-scale. paint.setShadowLayer(0, 0, 0, 0); @@ -633,6 +646,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { hintSize = params.mKeyHintLetterSize; } paint.setColor(hintColor); + params.brendAlpha(paint); paint.setTextSize(hintSize); final float hintX, hintY; if (key.hasHintLabel()) { @@ -701,6 +715,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { paint.setTextSize(params.mKeyHintLetterSize); paint.setColor(params.mKeyHintLabelColor); + params.brendAlpha(paint); paint.setTextAlign(Align.CENTER); final float hintX = keyWidth - params.mKeyHintLetterPadding - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2; diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index f4e766cb0..97f4d07d9 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -16,7 +16,11 @@ package com.android.inputmethod.keyboard; +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.TypedArray; @@ -75,12 +79,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke private Key mSpaceKey; private Drawable mSpaceIcon; // Stuff to draw language name on spacebar. - private ValueAnimator mLanguageOnSpacebarAnimator; + private ValueAnimator mLanguageOnSpacebarFadeoutAnimator; private int mFinalAlphaOfLanguageOnSpacebar; - private int mDurationOfFadeoutLanguageOnSpacebar; private static final int ALPHA_OPAQUE = 255; - private static final int LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY = 0; - private static final int LANGUAGE_ON_SPACEBAR_ALWAYS_DISPLAY = -1; private boolean mNeedsToDisplayLanguage; private Locale mSpacebarLocale; private int mSpacebarTextAlpha; @@ -97,6 +98,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke private final Drawable mAutoCorrectionSpacebarLedIcon; private static final int SPACE_LED_LENGTH_PERCENT = 80; + // Stuff to draw altCodeWhileTyping keys. + private ValueAnimator mAltCodeKeyWhileTypingFadeoutAnimator; + private ValueAnimator mAltCodeKeyWhileTypingFadeinAnimator; + private int mAltCodeKeyWhileTypingAnimAlpha; + // More keys keyboard private PopupWindow mMoreKeysWindow; private MoreKeysPanel mMoreKeysPanel; @@ -121,7 +127,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke private static final int MSG_REPEAT_KEY = 1; private static final int MSG_LONGPRESS_KEY = 2; private static final int MSG_DOUBLE_TAP = 3; - private static final int MSG_KEY_TYPED = 4; + private static final int MSG_TYPING_STATE_EXPIRED = 4; private final KeyTimerParams mParams; private boolean mInKeyRepeat; @@ -147,6 +153,18 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke KeyboardSwitcher.getInstance().onLongPressTimeout(msg.arg1); } break; + case MSG_TYPING_STATE_EXPIRED: + final ValueAnimator fadeout = keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator; + if (fadeout != null && fadeout.isStarted()) { + fadeout.cancel(); + } + // TODO: Start the fade in animation with an initial value that is the same as the + // final value when the above fade out animation gets cancelled. + final ValueAnimator fadein = keyboardView.mAltCodeKeyWhileTypingFadeinAnimator; + if (fadein != null && !fadein.isStarted()) { + fadein.start(); + } + break; } } @@ -221,14 +239,30 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } @Override - public void startKeyTypedTimer() { - removeMessages(MSG_KEY_TYPED); - sendMessageDelayed(obtainMessage(MSG_KEY_TYPED), mParams.mIgnoreSpecialKeyTimeout); + public void startTypingStateTimer() { + final boolean isTyping = isTypingState(); + removeMessages(MSG_TYPING_STATE_EXPIRED); + sendMessageDelayed( + obtainMessage(MSG_TYPING_STATE_EXPIRED), mParams.mIgnoreAltCodeKeyTimeout); + final LatinKeyboardView keyboardView = getOuterInstance(); + if (isTyping) { + return; + } + final ValueAnimator fadein = keyboardView.mAltCodeKeyWhileTypingFadeinAnimator; + if (fadein != null && fadein.isStarted()) { + fadein.cancel(); + } + // TODO: Start the fade out animation with an initial value that is the same as the + // final value when the above fade in animation gets cancelled. + final ValueAnimator fadeout = keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator; + if (fadeout != null && !fadeout.isStarted()) { + fadeout.start(); + } } @Override - public boolean isTyping() { - return hasMessages(MSG_KEY_TYPED); + public boolean isTypingState() { + return hasMessages(MSG_TYPING_STATE_EXPIRED); } @Override @@ -287,7 +321,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke public final int mLongPressKeyTimeout; public final int mLongPressShiftKeyTimeout; public final int mLongPressSpaceKeyTimeout; - public final int mIgnoreSpecialKeyTimeout; + public final int mIgnoreAltCodeKeyTimeout; KeyTimerParams() { mKeyRepeatStartTimeout = 0; @@ -295,7 +329,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mLongPressKeyTimeout = 0; mLongPressShiftKeyTimeout = 0; mLongPressSpaceKeyTimeout = 0; - mIgnoreSpecialKeyTimeout = 0; + mIgnoreAltCodeKeyTimeout = 0; } public KeyTimerParams(TypedArray latinKeyboardViewAttr) { @@ -309,8 +343,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke R.styleable.LatinKeyboardView_longPressShiftKeyTimeout, 0); mLongPressSpaceKeyTimeout = latinKeyboardViewAttr.getInt( R.styleable.LatinKeyboardView_longPressSpaceKeyTimeout, 0); - mIgnoreSpecialKeyTimeout = latinKeyboardViewAttr.getInt( - R.styleable.LatinKeyboardView_ignoreSpecialKeyTimeout, 0); + mIgnoreAltCodeKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_ignoreAltCodeKeyTimeout, 0); } } @@ -339,13 +373,12 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboardView_spacebarTextColor, 0); mSpacebarTextShadowColor = a.getColor( R.styleable.LatinKeyboardView_spacebarTextShadowColor, 0); - mDurationOfFadeoutLanguageOnSpacebar = a.getInt( - R.styleable.LatinKeyboardView_durationOfFadeoutLanguageOnSpacebar, - LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY); - final int delayBeforeFadeoutLanguageOnSpacebar = a.getInt( - R.styleable.LatinKeyboardView_delayBeforeFadeoutLangageOnSpacebar, 0); - mFinalAlphaOfLanguageOnSpacebar = a.getInt( - R.styleable.LatinKeyboardView_finalAlphaOfLanguageOnSpacebar, 0); + final int languageOnSpacebarFadeoutAnimatorResId = a.getResourceId( + R.styleable.LatinKeyboardView_languageOnSpacebarFadeoutAnimator, 0); + final int altCodeKeyWhileTypingFadeoutAnimatorResId = a.getResourceId( + R.styleable.LatinKeyboardView_altCodeKeyWhileTypingFadeoutAnimator, 0); + final int altCodeKeyWhileTypingFadeinAnimatorResId = a.getResourceId( + R.styleable.LatinKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0); final KeyTimerParams keyTimerParams = new KeyTimerParams(a); mPointerTrackerParams = new PointerTrackerParams(a); @@ -361,19 +394,67 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke PointerTracker.setParameters(mPointerTrackerParams); - mLanguageOnSpacebarAnimator = ValueAnimator.ofInt( - ALPHA_OPAQUE, mFinalAlphaOfLanguageOnSpacebar); - mLanguageOnSpacebarAnimator.setStartDelay(delayBeforeFadeoutLanguageOnSpacebar); - if (mDurationOfFadeoutLanguageOnSpacebar > 0) { - mLanguageOnSpacebarAnimator.setDuration(mDurationOfFadeoutLanguageOnSpacebar); - } - mLanguageOnSpacebarAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mSpacebarTextAlpha = (Integer)animation.getAnimatedValue(); - invalidateKey(mSpaceKey); - } - }); + final ValueAnimator animator = loadValueAnimator(languageOnSpacebarFadeoutAnimatorResId); + if (animator != null) { + animator.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mSpacebarTextAlpha = (Integer)animation.getAnimatedValue(); + invalidateKey(mSpaceKey); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator a) { + final ValueAnimator valueAnimator = (ValueAnimator)a; + mFinalAlphaOfLanguageOnSpacebar = (Integer)valueAnimator.getAnimatedValue(); + } + }); + // In order to get the final value of animator. + animator.end(); + } + mLanguageOnSpacebarFadeoutAnimator = animator; + + final ValueAnimator fadeout = loadValueAnimator(altCodeKeyWhileTypingFadeoutAnimatorResId); + if (fadeout != null) { + fadeout.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mAltCodeKeyWhileTypingAnimAlpha = (Integer)animation.getAnimatedValue(); + updateAltCodeKeyWhileTyping(); + } + }); + fadeout.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator a) { + final ValueAnimator valueAnimator = (ValueAnimator)a; + } + }); + } + mAltCodeKeyWhileTypingFadeoutAnimator = fadeout; + + final ValueAnimator fadein = loadValueAnimator(altCodeKeyWhileTypingFadeinAnimatorResId); + if (fadein != null) { + fadein.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mAltCodeKeyWhileTypingAnimAlpha = (Integer)animation.getAnimatedValue(); + updateAltCodeKeyWhileTyping(); + } + }); + fadein.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator a) { + final ValueAnimator valueAnimator = (ValueAnimator)a; + } + }); + } + mAltCodeKeyWhileTypingFadeinAnimator = fadein; + } + + private ValueAnimator loadValueAnimator(int resId) { + if (resId == 0) return null; + return (ValueAnimator)AnimatorInflater.loadAnimator(getContext(), resId); } public void setKeyboardActionListener(KeyboardActionListener listener) { @@ -429,6 +510,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; mSpacebarTextSize = keyHeight * mSpacebarTextRatio; mSpacebarLocale = keyboard.mId.mLocale; + mSpacebarTextAlpha = ALPHA_OPAQUE; + mAltCodeKeyWhileTypingAnimAlpha = ALPHA_OPAQUE; } /** @@ -789,18 +872,27 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke invalidateKey(shortcutKey); } + private void updateAltCodeKeyWhileTyping() { + final Keyboard keyboard = getKeyboard(); + if (keyboard == null) return; + for (final Key key : keyboard.mAltCodeKeysWhileTyping) { + invalidateKey(key); + } + } + public void startDisplayLanguageOnSpacebar(boolean subtypeChanged, boolean needsToDisplayLanguage) { - mLanguageOnSpacebarAnimator.cancel(); + final ValueAnimator animator = mLanguageOnSpacebarFadeoutAnimator; + if (animator != null) { + animator.cancel(); + } mNeedsToDisplayLanguage = needsToDisplayLanguage; - if (mDurationOfFadeoutLanguageOnSpacebar == LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY) { + if (animator == null) { mNeedsToDisplayLanguage = false; - } else if (mDurationOfFadeoutLanguageOnSpacebar == LANGUAGE_ON_SPACEBAR_ALWAYS_DISPLAY) { - mSpacebarTextAlpha = ALPHA_OPAQUE; } else { if (subtypeChanged && needsToDisplayLanguage) { mSpacebarTextAlpha = ALPHA_OPAQUE; - mLanguageOnSpacebarAnimator.start(); + animator.start(); } else { mSpacebarTextAlpha = mFinalAlphaOfLanguageOnSpacebar; } @@ -816,6 +908,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke @Override protected void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint, KeyDrawParams params) { + if (key.altCodeWhileTyping() && key.isEnabled()) { + params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha; + } if (key.mCode == Keyboard.CODE_SPACE) { drawSpacebar(key, canvas, paint); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 607b33bb4..ed889712a 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -68,8 +68,8 @@ public class PointerTracker { } public interface TimerProxy { - public void startKeyTypedTimer(); - public boolean isTyping(); + public void startTypingStateTimer(); + public boolean isTypingState(); public void startKeyRepeatTimer(PointerTracker tracker); public void startLongPressTimer(PointerTracker tracker); public void startLongPressTimer(int code); @@ -81,9 +81,9 @@ public class PointerTracker { public static class Adapter implements TimerProxy { @Override - public void startKeyTypedTimer() {} + public void startTypingStateTimer() {} @Override - public boolean isTyping() { return false; } + public boolean isTypingState() { return false; } @Override public void startKeyRepeatTimer(PointerTracker tracker) {} @Override @@ -251,25 +251,26 @@ public class PointerTracker { // primaryCode is different from {@link Key#mCode}. private void callListenerOnCodeInput(Key key, int primaryCode, int x, int y) { final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); - final boolean alterCode = key.altCodeWhileTyping() && mTimerProxy.isTyping(); - final int code = alterCode ? key.mAltCode : primaryCode; + final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); + final int code = altersCode ? key.mAltCode : primaryCode; if (DEBUG_LISTENER) { Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText + " x=" + x + " y=" + y - + " ignoreModifier=" + ignoreModifierKey + " alterCode=" + alterCode + + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + " enabled=" + key.isEnabled()); } if (ignoreModifierKey) { return; } - if (key.isEnabled()) { + // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. + if (key.isEnabled() || altersCode) { if (code == Keyboard.CODE_OUTPUT_TEXT) { mListener.onTextInput(key.mOutputText); } else if (code != Keyboard.CODE_UNSPECIFIED) { mListener.onCodeInput(code, x, y); } if (!key.altCodeWhileTyping() && !key.isModifier()) { - mTimerProxy.startKeyTypedTimer(); + mTimerProxy.startTypingStateTimer(); } } } @@ -322,10 +323,11 @@ public class PointerTracker { private void setReleasedKeyGraphics(Key key) { mDrawingProxy.dismissKeyPreview(this); - if (key == null || !key.isEnabled()) { + if (key == null) { return; } + // Even if the key is disabled, update the key release graphics just in case. updateReleaseKeyGraphics(key); if (key.isShift()) { @@ -351,7 +353,14 @@ public class PointerTracker { } private void setPressedKeyGraphics(Key key) { - if (key == null || !key.isEnabled()) { + if (key == null) { + return; + } + + // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. + final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); + final boolean needsToUpdateGraphics = key.isEnabled() || altersCode; + if (!needsToUpdateGraphics) { return; } @@ -368,7 +377,7 @@ public class PointerTracker { } } - if (key.altCodeWhileTyping() && mTimerProxy.isTyping()) { + if (key.altCodeWhileTyping() && mTimerProxy.isTypingState()) { final int altCode = key.mAltCode; final Key altKey = mKeyboard.getKey(altCode); if (altKey != null) { diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index e2a48306a..61d75e278 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -124,40 +124,40 @@ public class ProximityInfo { final float[] sweetSpotCenterXs; final float[] sweetSpotCenterYs; final float[] sweetSpotRadii; - final boolean calculateSweetSpotParams; + + for (int i = 0; i < keyCount; ++i) { + final Key key = keys[i]; + keyXCoordinates[i] = key.mX; + keyYCoordinates[i] = key.mY; + keyWidths[i] = key.mWidth; + keyHeights[i] = key.mHeight; + keyCharCodes[i] = key.mCode; + } + if (touchPositionCorrection != null && touchPositionCorrection.isValid()) { sweetSpotCenterXs = new float[keyCount]; sweetSpotCenterYs = new float[keyCount]; sweetSpotRadii = new float[keyCount]; - calculateSweetSpotParams = true; for (int i = 0; i < keyCount; i++) { final Key key = keys[i]; - keyXCoordinates[i] = key.mX; - keyYCoordinates[i] = key.mY; - keyWidths[i] = key.mWidth; - keyHeights[i] = key.mHeight; - keyCharCodes[i] = key.mCode; - if (calculateSweetSpotParams) { - final Rect hitBox = key.mHitBox; - final int row = hitBox.top / mKeyHeight; - if (row < touchPositionCorrection.mRadii.length) { - final float hitBoxCenterX = (hitBox.left + hitBox.right) * 0.5f; - final float hitBoxCenterY = (hitBox.top + hitBox.bottom) * 0.5f; - final float hitBoxWidth = hitBox.right - hitBox.left; - final float hitBoxHeight = hitBox.bottom - hitBox.top; - final float x = touchPositionCorrection.mXs[row]; - final float y = touchPositionCorrection.mYs[row]; - final float radius = touchPositionCorrection.mRadii[row]; - sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth; - sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight; - sweetSpotRadii[i] = radius * (float) Math.sqrt( - hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight); - } + final Rect hitBox = key.mHitBox; + final int row = hitBox.top / mKeyHeight; + if (row < touchPositionCorrection.mRadii.length) { + final float hitBoxCenterX = (hitBox.left + hitBox.right) * 0.5f; + final float hitBoxCenterY = (hitBox.top + hitBox.bottom) * 0.5f; + final float hitBoxWidth = hitBox.right - hitBox.left; + final float hitBoxHeight = hitBox.bottom - hitBox.top; + final float x = touchPositionCorrection.mXs[row]; + final float y = touchPositionCorrection.mYs[row]; + final float radius = touchPositionCorrection.mRadii[row]; + sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth; + sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight; + sweetSpotRadii[i] = radius * (float) Math.sqrt( + hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight); } } } else { sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null; - calculateSweetSpotParams = false; } mNativeProximityInfo = setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE, diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index f41972e8b..9f5931de9 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -924,17 +924,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } final List<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords = - SuggestedWords.Builder.getFromApplicationSpecifiedCompletions( + SuggestedWords.getFromApplicationSpecifiedCompletions( applicationSpecifiedCompletions); - SuggestedWords.Builder builder = new SuggestedWords.Builder(applicationSuggestedWords, + final SuggestedWords suggestedWords = new SuggestedWords( + applicationSuggestedWords, false /* typedWordValid */, - false /* hasMinimalSuggestion */, + false /* hasAutoCorrectionCandidate */, false /* allowsToBeAutoCorrected */, false /* isPunctuationSuggestions */); // When in fullscreen mode, show completions generated by the application - final SuggestedWords words = builder.build(); final boolean isAutoCorrection = false; - setSuggestions(words, isAutoCorrection); + setSuggestions(suggestedWords, isAutoCorrection); setAutoCorrectionIndicator(isAutoCorrection); // TODO: is this the right thing to do? What should we auto-correct to in // this case? This says to keep whatever the user typed. @@ -1767,7 +1767,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final CharSequence typedWord = mWordComposer.getTypedWord(); // getSuggestedWordBuilder handles gracefully a null value of prevWord - final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer, + final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); // Basically, we update the suggestion strip only when suggestion count > 1. However, @@ -1776,24 +1776,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // in most cases, suggestion count is 1 when typed word's length is 1, but we do always // need to clear the previous state when the user starts typing a word (i.e. typed word's // length == 1). - if (builder.size() > 1 || typedWord.length() == 1 || !builder.allowsToBeAutoCorrected() + if (suggestedWords.size() > 1 || typedWord.length() == 1 + || !suggestedWords.mAllowsToBeAutoCorrected || mSuggestionsView.isShowingAddToDictionaryHint()) { - showSuggestions(builder.build(), typedWord); + showSuggestions(suggestedWords, typedWord); } else { SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); if (previousSuggestions == mSettingsValues.mSuggestPuncList) { previousSuggestions = SuggestedWords.EMPTY; } final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions = - SuggestedWords.Builder.getTypedWordAndPreviousSuggestions( + SuggestedWords.getTypedWordAndPreviousSuggestions( typedWord, previousSuggestions); - final SuggestedWords.Builder obsoleteSuggestionsBuilder = - new SuggestedWords.Builder(typedWordAndPreviousSuggestions, + final SuggestedWords obsoleteSuggestedWords = + new SuggestedWords(typedWordAndPreviousSuggestions, false /* typedWordValid */, - false /* hasMinimalSuggestion */, + false /* hasAutoCorrectionCandidate */, false /* allowsToBeAutoCorrected */, false /* isPunctuationSuggestions */); - showSuggestions(obsoleteSuggestionsBuilder.build(), typedWord); + showSuggestions(obsoleteSuggestedWords, typedWord); } } @@ -1973,23 +1974,23 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return; } - final SuggestedWords.Builder builder; + final SuggestedWords suggestedWords; if (mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), mSettingsValues.mWordSeparators); if (!TextUtils.isEmpty(prevWord)) { - builder = mSuggest.getBigramPredictionWordBuilder(prevWord); + suggestedWords = mSuggest.getBigramPredictions(prevWord); } else { - builder = null; + suggestedWords = null; } } else { - builder = null; + suggestedWords = null; } - if (null != builder && builder.size() > 0) { + if (null != suggestedWords && suggestedWords.size() > 0) { // Explicitly supply an empty typed word (the no-second-arg version of // showSuggestions will retrieve the word near the cursor, we don't want that here) - showSuggestions(builder.build(), ""); + showSuggestions(suggestedWords, ""); } else { if (!isShowingPunctuationList()) setPunctuationSuggestions(); } diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 0a4aea140..d12b9c428 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -183,12 +183,11 @@ public class SettingsValues { KeySpecParser.getLabel(puncSpec))); } } - final SuggestedWords.Builder builder = new SuggestedWords.Builder(puncList, + return new SuggestedWords(puncList, false /* typedWordValid */, - false /* hasMinimalSuggestion */, + false /* hasAutoCorrectionCandidate */, false /* allowsToBeAutoCorrected */, true /* isPunctuationSuggestions */); - return builder.build(); } private static SuggestedWords createSuggestPuncOutputTextList(final String[] puncs) { @@ -205,12 +204,11 @@ public class SettingsValues { } } } - final SuggestedWords.Builder builder = new SuggestedWords.Builder(puncOutputTextList, + return new SuggestedWords(puncOutputTextList, false /* typedWordValid */, - false /* hasMinimalSuggestion */, + false /* hasAutoCorrectionCandidate */, false /* allowsToBeAutoCorrected */, true /* isPunctuationSuggestions */); - return builder.build(); } private static String createWordSeparators(final String weakSpaceStrippers, diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 28d3b4437..3089625e7 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -239,7 +239,7 @@ public class Suggest implements Dictionary.WordCallback { } private static final WordComposer sEmptyWordComposer = new WordComposer(); - public SuggestedWords.Builder getBigramPredictionWordBuilder(CharSequence prevWordForBigram) { + public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) { LatinImeLogger.onStartSuggestion(prevWordForBigram); mIsFirstCharCapitalized = false; mIsAllUpperCase = false; @@ -269,16 +269,15 @@ public class Suggest implements Dictionary.WordCallback { StringUtils.removeDupes(mSuggestions); - return new SuggestedWords.Builder( - SuggestedWords.Builder.getFromCharSequenceList(mSuggestions), + return new SuggestedWords(SuggestedWords.getFromCharSequenceList(mSuggestions), false /* typedWordValid */, - false /* hasMinimalSuggestion */, + false /* hasAutoCorrectionCandidate */, false /* allowsToBeAutoCorrected */, false /* isPunctuationSuggestions */); } // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder - public SuggestedWords.Builder getSuggestedWordBuilder( + public SuggestedWords getSuggestedWords( final WordComposer wordComposer, CharSequence prevWordForBigram, final ProximityInfo proximityInfo, final int correctionMode) { LatinImeLogger.onStartSuggestion(prevWordForBigram); @@ -344,21 +343,22 @@ public class Suggest implements Dictionary.WordCallback { } } else if (wordComposer.size() > 1) { + final WordComposer wordComposerForLookup; + if (mTrailingSingleQuotesCount > 0) { + wordComposerForLookup = new WordComposer(wordComposer); + for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) { + wordComposerForLookup.deleteLast(); + } + } else { + wordComposerForLookup = wordComposer; + } // At second character typed, search the unigrams (scores being affected by bigrams) for (final String key : mUnigramDictionaries.keySet()) { // Skip UserUnigramDictionary and WhitelistDictionary to lookup if (key.equals(DICT_KEY_USER_UNIGRAM) || key.equals(DICT_KEY_WHITELIST)) continue; final Dictionary dictionary = mUnigramDictionaries.get(key); - if (mTrailingSingleQuotesCount > 0) { - final WordComposer tmpWordComposer = new WordComposer(wordComposer); - for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) { - tmpWordComposer.deleteLast(); - } - dictionary.getWords(tmpWordComposer, this, proximityInfo); - } else { - dictionary.getWords(wordComposer, this, proximityInfo); - } + dictionary.getWords(wordComposerForLookup, this, proximityInfo); } } @@ -392,42 +392,36 @@ public class Suggest implements Dictionary.WordCallback { mSuggestions.add(0, typedWord); StringUtils.removeDupes(mSuggestions); - final SuggestedWords.Builder builder; - final ArrayList<SuggestedWords.SuggestedWordInfo> scoreInfoList; + final ArrayList<SuggestedWords.SuggestedWordInfo> suggestionsList; if (DBG) { // TODO: this doesn't take into account the fact that removing dupes from mSuggestions // may have made mScores[] and mSuggestions out of sync. final CharSequence autoCorrectionSuggestion = mSuggestions.get(0); - final int autoCorrectionSuggestionScore = mScores[0]; double normalizedScore = BinaryDictionary.calcNormalizedScore( - typedWord, autoCorrectionSuggestion.toString(), - autoCorrectionSuggestionScore); - scoreInfoList = new ArrayList<SuggestedWords.SuggestedWordInfo>(); - scoreInfoList.add(new SuggestedWords.SuggestedWordInfo(autoCorrectionSuggestion, "+", + typedWord, autoCorrectionSuggestion.toString(), mScores[0]); + suggestionsList = new ArrayList<SuggestedWords.SuggestedWordInfo>(); + suggestionsList.add(new SuggestedWords.SuggestedWordInfo(autoCorrectionSuggestion, "+", false)); final int suggestionsSize = mSuggestions.size(); // Note: i here is the index in mScores[], but the index in mSuggestions is one more // than i because we added the typed word to mSuggestions without touching mScores. for (int i = 0; i < mScores.length && i < suggestionsSize - 1; ++i) { + final String scoreInfoString; if (normalizedScore > 0) { - final String scoreThreshold = String.format("%d (%4.2f)", mScores[i], - normalizedScore); - scoreInfoList.add( - new SuggestedWords.SuggestedWordInfo(mSuggestions.get(i + 1), - scoreThreshold, false)); + scoreInfoString = String.format("%d (%4.2f)", mScores[i], normalizedScore); normalizedScore = 0.0; } else { - final String score = Integer.toString(mScores[i]); - scoreInfoList.add(new SuggestedWords.SuggestedWordInfo(mSuggestions.get(i + 1), - score, false)); + scoreInfoString = Integer.toString(mScores[i]); } + suggestionsList.add(new SuggestedWords.SuggestedWordInfo(mSuggestions.get(i + 1), + scoreInfoString, false)); } for (int i = mScores.length; i < suggestionsSize; ++i) { - scoreInfoList.add(new SuggestedWords.SuggestedWordInfo(mSuggestions.get(i), + suggestionsList.add(new SuggestedWords.SuggestedWordInfo(mSuggestions.get(i), "--", false)); } } else { - scoreInfoList = SuggestedWords.Builder.getFromCharSequenceList(mSuggestions); + suggestionsList = SuggestedWords.getFromCharSequenceList(mSuggestions); } boolean autoCorrectionAvailable = hasAutoCorrection; @@ -437,16 +431,20 @@ public class Suggest implements Dictionary.WordCallback { } // Don't auto-correct words with multiple capital letter autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); - builder = new SuggestedWords.Builder(scoreInfoList, + final boolean shouldBlockAutoCorrectionBySatefyNet; + if (allowsToBeAutoCorrected && suggestionsList.size() > 1 && mAutoCorrectionThreshold > 0 + && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord, + suggestionsList.get(1).mWord)) { + shouldBlockAutoCorrectionBySatefyNet = true; + } else { + shouldBlockAutoCorrectionBySatefyNet = false; + } + return new SuggestedWords(suggestionsList, !allowsToBeAutoCorrected /* typedWordValid */, - autoCorrectionAvailable /* hasMinimalSuggestion */, + autoCorrectionAvailable & !shouldBlockAutoCorrectionBySatefyNet + /* hasAutoCorrectionCandidate */, allowsToBeAutoCorrected /* allowsToBeAutoCorrected */, false /* isPunctuationSuggestions */); - if (allowsToBeAutoCorrected && builder.size() > 1 && mAutoCorrectionThreshold > 0 - && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord, builder.getWord(1))) { - builder.setShouldBlockAutoCorrectionBySafetyNet(); - } - return builder; } @Override diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 144e67482..6b231f81c 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -16,31 +16,35 @@ package com.android.inputmethod.latin; +import android.text.TextUtils; import android.view.inputmethod.CompletionInfo; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; public class SuggestedWords { - public static final SuggestedWords EMPTY = new SuggestedWords(false, false, false, false, - Collections.<SuggestedWordInfo>emptyList()); + public static final SuggestedWords EMPTY = new SuggestedWords( + Collections.<SuggestedWordInfo>emptyList(), false, false, false, false); public final boolean mTypedWordValid; public final boolean mHasAutoCorrectionCandidate; public final boolean mIsPunctuationSuggestions; + public final boolean mAllowsToBeAutoCorrected; private final List<SuggestedWordInfo> mSuggestedWordInfoList; - SuggestedWords(boolean typedWordValid, - boolean hasAutoCorrectionCandidate, boolean isPunctuationSuggestions, - boolean shouldBlockAutoCorrectionBySafetyNet, - List<SuggestedWordInfo> suggestedWordInfoList) { + public SuggestedWords(final List<SuggestedWordInfo> suggestedWordInfoList, + final boolean typedWordValid, + final boolean hasAutoCorrectionCandidate, + final boolean allowsToBeAutoCorrected, + final boolean isPunctuationSuggestions) { + mSuggestedWordInfoList = suggestedWordInfoList; mTypedWordValid = typedWordValid; - mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate - && !shouldBlockAutoCorrectionBySafetyNet; + mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate; + mAllowsToBeAutoCorrected = allowsToBeAutoCorrected; mIsPunctuationSuggestions = isPunctuationSuggestions; - mSuggestedWordInfoList = suggestedWordInfoList; } public int size() { @@ -69,104 +73,51 @@ public class SuggestedWords { return "SuggestedWords:" + " mTypedWordValid=" + mTypedWordValid + " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate - + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions; + + " mAllowsToBeAutoCorrected=" + mAllowsToBeAutoCorrected + + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions + + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray()); } - public static class Builder { - private final boolean mTypedWordValid; - private final boolean mHasMinimalSuggestion; - private final boolean mIsPunctuationSuggestions; - private boolean mShouldBlockAutoCorrectionBySafetyNet; - private final boolean mAllowsToBeAutoCorrected; - private final List<SuggestedWordInfo> mSuggestedWordInfoList; - - public Builder(final List<SuggestedWordInfo> suggestedWordInfoList, - final boolean typedWordValid, - final boolean hasMinimalSuggestion, - final boolean allowsToBeAutoCorrected, - final boolean isPunctuationSuggestions) { - mSuggestedWordInfoList = suggestedWordInfoList; - mTypedWordValid = typedWordValid; - mHasMinimalSuggestion = hasMinimalSuggestion; - mAllowsToBeAutoCorrected = allowsToBeAutoCorrected; - mIsPunctuationSuggestions = isPunctuationSuggestions; - } - - public static ArrayList<SuggestedWordInfo> getFromCharSequenceList( - final List<CharSequence> wordList) { - final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>(); - for (CharSequence word : wordList) { - if (null != word) result.add(new SuggestedWordInfo(word, null, false)); - } - return result; - } - - public static List<SuggestedWordInfo> getFromApplicationSpecifiedCompletions( - final CompletionInfo[] infos) { - final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>(); - for (CompletionInfo info : infos) { - if (null != info) result.add(new SuggestedWordInfo(info.getText(), null, false)); - } - return result; + public static ArrayList<SuggestedWordInfo> getFromCharSequenceList( + final List<CharSequence> wordList) { + final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>(); + for (CharSequence word : wordList) { + if (null != word) result.add(new SuggestedWordInfo(word, null, false)); } + return result; + } - public Builder setShouldBlockAutoCorrectionBySafetyNet() { - mShouldBlockAutoCorrectionBySafetyNet = true; - return this; + public static List<SuggestedWordInfo> getFromApplicationSpecifiedCompletions( + final CompletionInfo[] infos) { + final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>(); + for (CompletionInfo info : infos) { + if (null != info) result.add(new SuggestedWordInfo(info.getText(), null, false)); } + return result; + } - // Should get rid of the first one (what the user typed previously) from suggestions - // and replace it with what the user currently typed. - public static ArrayList<SuggestedWordInfo> getTypedWordAndPreviousSuggestions( - final CharSequence typedWord, final SuggestedWords previousSuggestions) { - final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<SuggestedWordInfo>(); - final HashSet<String> alreadySeen = new HashSet<String>(); - suggestionsList.add(new SuggestedWordInfo(typedWord, null, false)); - alreadySeen.add(typedWord.toString()); - final int previousSize = previousSuggestions.size(); - for (int pos = 1; pos < previousSize; pos++) { - final String prevWord = previousSuggestions.getWord(pos).toString(); - // Filter out duplicate suggestion. - if (!alreadySeen.contains(prevWord)) { - suggestionsList.add(new SuggestedWordInfo(prevWord, null, true)); - alreadySeen.add(prevWord); - } + // Should get rid of the first one (what the user typed previously) from suggestions + // and replace it with what the user currently typed. + public static ArrayList<SuggestedWordInfo> getTypedWordAndPreviousSuggestions( + final CharSequence typedWord, final SuggestedWords previousSuggestions) { + final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<SuggestedWordInfo>(); + final HashSet<String> alreadySeen = new HashSet<String>(); + suggestionsList.add(new SuggestedWordInfo(typedWord, null, false)); + alreadySeen.add(typedWord.toString()); + final int previousSize = previousSuggestions.size(); + for (int pos = 1; pos < previousSize; pos++) { + final String prevWord = previousSuggestions.getWord(pos).toString(); + // Filter out duplicate suggestion. + if (!alreadySeen.contains(prevWord)) { + suggestionsList.add(new SuggestedWordInfo(prevWord, null, true)); + alreadySeen.add(prevWord); } - return suggestionsList; - } - - public SuggestedWords build() { - return new SuggestedWords(mTypedWordValid, mHasMinimalSuggestion, - mIsPunctuationSuggestions, mShouldBlockAutoCorrectionBySafetyNet, - mSuggestedWordInfoList); - } - - public int size() { - return mSuggestedWordInfoList.size(); - } - - public CharSequence getWord(int pos) { - return mSuggestedWordInfoList.get(pos).mWord; - } - - public boolean allowsToBeAutoCorrected() { - return mAllowsToBeAutoCorrected; - } - - @Override - public String toString() { - // Pretty-print method to help debug - return "SuggestedWords.Builder:" - + " mTypedWordValid=" + mTypedWordValid - + " mHasMinimalSuggestion=" + mHasMinimalSuggestion - + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions - + " mShouldBlockAutoCorrectionBySafetyNet=" - + mShouldBlockAutoCorrectionBySafetyNet; } + return suggestionsList; } public static class SuggestedWordInfo { - private final CharSequence mWord; + public final CharSequence mWord; private final CharSequence mDebugString; private final boolean mPreviousSuggestedWord; @@ -194,5 +145,14 @@ public class SuggestedWords { public boolean isObsoleteSuggestedWord () { return mPreviousSuggestedWord; } + + @Override + public String toString() { + if (TextUtils.isEmpty(mDebugString)) { + return mWord.toString(); + } else { + return mWord.toString() + " (" + mDebugString.toString() + ")"; + } + } } } |