Merge "If there are no suggestion span, recompute suggestions."
commit
a022c53882
|
@ -1466,7 +1466,13 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
|
|||
"", mWordComposer.getTypedWord(), " ", mWordComposer);
|
||||
}
|
||||
}
|
||||
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
|
||||
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
||||
// If we are in the middle of a recorrection, we need to commit the recorrection
|
||||
// first so that we can insert the character at the current cursor position.
|
||||
resetEntireInputState(mLastSelectionStart);
|
||||
} else {
|
||||
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
|
||||
}
|
||||
}
|
||||
final int keyX, keyY;
|
||||
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
|
||||
|
@ -1522,8 +1528,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
|
|||
}
|
||||
final int wordComposerSize = mWordComposer.size();
|
||||
// Since isComposingWord() is true, the size is at least 1.
|
||||
final int lastChar = mWordComposer.getCodeAt(wordComposerSize - 1);
|
||||
if (wordComposerSize <= 1) {
|
||||
final int lastChar = mWordComposer.getCodeBeforeCursor();
|
||||
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
||||
// If we are in the middle of a recorrection, we need to commit the recorrection
|
||||
// first so that we can insert the batch input at the current cursor position.
|
||||
resetEntireInputState(mLastSelectionStart);
|
||||
} else if (wordComposerSize <= 1) {
|
||||
// We auto-correct the previous (typed, not gestured) string iff it's one character
|
||||
// long. The reason for this is, even in the middle of gesture typing, you'll still
|
||||
// tap one-letter words and you want them auto-corrected (typically, "i" in English
|
||||
|
@ -1734,8 +1744,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
|
|||
// during key repeat.
|
||||
mHandler.postUpdateShiftState();
|
||||
|
||||
if (mWordComposer.isComposingWord() && !mWordComposer.isCursorAtEndOfComposingWord()) {
|
||||
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
||||
// If we are in the middle of a recorrection, we need to commit the recorrection
|
||||
// first so that we can remove the character at the current cursor position.
|
||||
resetEntireInputState(mLastSelectionStart);
|
||||
// When we exit this if-clause, mWordComposer.isComposingWord() will return false.
|
||||
}
|
||||
if (mWordComposer.isComposingWord()) {
|
||||
final int length = mWordComposer.size();
|
||||
|
@ -1870,7 +1883,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
|
|||
promotePhantomSpace();
|
||||
}
|
||||
|
||||
if (mWordComposer.isComposingWord() && !mWordComposer.isCursorAtEndOfComposingWord()) {
|
||||
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
||||
// If we are in the middle of a recorrection, we need to commit the recorrection
|
||||
// first so that we can insert the character at the current cursor position.
|
||||
resetEntireInputState(mLastSelectionStart);
|
||||
isComposingWord = false;
|
||||
}
|
||||
|
@ -1935,7 +1950,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
|
|||
ResearchLogger.latinIME_handleSeparator(primaryCode, mWordComposer.isComposingWord());
|
||||
}
|
||||
boolean didAutoCorrect = false;
|
||||
// Handle separator
|
||||
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
||||
// If we are in the middle of a recorrection, we need to commit the recorrection
|
||||
// first so that we can insert the separator at the current cursor position.
|
||||
resetEntireInputState(mLastSelectionStart);
|
||||
}
|
||||
if (mWordComposer.isComposingWord()) {
|
||||
if (mSettings.getCurrent().mCorrectionEnabled) {
|
||||
// TODO: maybe cache Strings in an <String> sparse array or something
|
||||
|
@ -2357,9 +2376,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
|
|||
final Range range = mConnection.getWordRangeAtCursor(mSettings.getWordSeparators(),
|
||||
0 /* additionalPrecedingWordsCount */);
|
||||
final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
|
||||
final String typedWord = range.mWord.toString();
|
||||
if (range.mWord instanceof SpannableString) {
|
||||
final SpannableString spannableString = (SpannableString)range.mWord;
|
||||
final String typedWord = spannableString.toString();
|
||||
int i = 0;
|
||||
for (Object object : spannableString.getSpans(0, spannableString.length(),
|
||||
SuggestionSpan.class)) {
|
||||
|
@ -2374,18 +2393,42 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
|
|||
}
|
||||
}
|
||||
}
|
||||
mWordComposer.setComposingWord(range.mWord, mKeyboardSwitcher.getKeyboard());
|
||||
mWordComposer.setComposingWord(typedWord, mKeyboardSwitcher.getKeyboard());
|
||||
mWordComposer.setCursorPositionWithinWord(range.mCharsBefore);
|
||||
mConnection.setComposingRegion(mLastSelectionStart - range.mCharsBefore,
|
||||
mLastSelectionEnd + range.mCharsAfter);
|
||||
final SuggestedWords suggestedWords;
|
||||
if (suggestions.isEmpty()) {
|
||||
suggestions.add(new SuggestedWordInfo(range.mWord.toString(), 1,
|
||||
SuggestedWordInfo.KIND_TYPED, Dictionary.TYPE_RESUMED));
|
||||
// We come here if there weren't any suggestion spans on this word. We will try to
|
||||
// compute suggestions for it instead.
|
||||
final SuggestedWords suggestedWordsIncludingTypedWord =
|
||||
getSuggestedWords(Suggest.SESSION_TYPING);
|
||||
if (suggestedWordsIncludingTypedWord.size() > 1) {
|
||||
// We were able to compute new suggestions for this word.
|
||||
// Remove the typed word, since we don't want to display it in this case.
|
||||
// The #getSuggestedWordsExcludingTypedWord() method sets willAutoCorrect to false.
|
||||
suggestedWords =
|
||||
suggestedWordsIncludingTypedWord.getSuggestedWordsExcludingTypedWord();
|
||||
} else {
|
||||
// No saved suggestions, and we were unable to compute any good one either.
|
||||
// Rather than displaying an empty suggestion strip, we'll display the original
|
||||
// word alone in the middle.
|
||||
// Since there is only one word, willAutoCorrect is false.
|
||||
suggestedWords = suggestedWordsIncludingTypedWord;
|
||||
}
|
||||
} else {
|
||||
// We found suggestion spans in the word. We'll create the SuggestedWords out of
|
||||
// them, and make willAutoCorrect false.
|
||||
suggestedWords = new SuggestedWords(suggestions,
|
||||
true /* typedWordValid */, false /* willAutoCorrect */,
|
||||
false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */,
|
||||
false /* isPrediction */);
|
||||
}
|
||||
showSuggestionStrip(new SuggestedWords(suggestions,
|
||||
true /* typedWordValid */, false /* willAutoCorrect */,
|
||||
false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */,
|
||||
false /* isPrediction */), range.mWord.toString());
|
||||
|
||||
// Note that it's very important here that suggestedWords.mWillAutoCorrect is false.
|
||||
// We never want to auto-correct on a resumed suggestion. Please refer to the three
|
||||
// places above where suggestedWords is affected.
|
||||
showSuggestionStrip(suggestedWords, typedWord);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -195,4 +195,21 @@ public final class SuggestedWords {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SuggestedWords is an immutable object, as much as possible. We must not just remove
|
||||
// words from the member ArrayList as some other parties may expect the object to never change.
|
||||
public SuggestedWords getSuggestedWordsExcludingTypedWord() {
|
||||
final ArrayList<SuggestedWordInfo> newSuggestions = CollectionUtils.newArrayList();
|
||||
for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
|
||||
final SuggestedWordInfo info = mSuggestedWordInfoList.get(i);
|
||||
if (SuggestedWordInfo.KIND_TYPED != info.mKind) {
|
||||
newSuggestions.add(info);
|
||||
}
|
||||
}
|
||||
// We should never autocorrect, so we say the typed word is valid. Also, in this case,
|
||||
// no auto-correction should take place hence willAutoCorrect = false.
|
||||
return new SuggestedWords(newSuggestions, true /* typedWordValid */,
|
||||
false /* willAutoCorrect */, mIsPunctuationSuggestions, mIsObsoleteSuggestions,
|
||||
mIsPrediction);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Arrays;
|
|||
*/
|
||||
public final class WordComposer {
|
||||
private static final int MAX_WORD_LENGTH = Constants.Dictionary.MAX_WORD_LENGTH;
|
||||
private static final boolean DBG = LatinImeLogger.sDBG;
|
||||
|
||||
public static final int CAPS_MODE_OFF = 0;
|
||||
// 1 is shift bit, 2 is caps bit, 4 is auto bit but this is just a convention as these bits
|
||||
|
@ -132,6 +133,13 @@ public final class WordComposer {
|
|||
return mPrimaryKeyCodes[index];
|
||||
}
|
||||
|
||||
public int getCodeBeforeCursor() {
|
||||
if (mCursorPositionWithinWord < 1 || mCursorPositionWithinWord > mPrimaryKeyCodes.length) {
|
||||
return Constants.NOT_A_CODE;
|
||||
}
|
||||
return mPrimaryKeyCodes[mCursorPositionWithinWord - 1];
|
||||
}
|
||||
|
||||
public InputPointers getInputPointers() {
|
||||
return mInputPointers;
|
||||
}
|
||||
|
@ -177,8 +185,12 @@ public final class WordComposer {
|
|||
mCursorPositionWithinWord = posWithinWord;
|
||||
}
|
||||
|
||||
public boolean isCursorAtEndOfComposingWord() {
|
||||
return mCursorPositionWithinWord == mCodePointSize;
|
||||
public boolean isCursorFrontOrMiddleOfComposingWord() {
|
||||
if (DBG && mCursorPositionWithinWord > mCodePointSize) {
|
||||
throw new RuntimeException("Wrong cursor position : " + mCursorPositionWithinWord
|
||||
+ "in a word of size " + mCodePointSize);
|
||||
}
|
||||
return mCursorPositionWithinWord != mCodePointSize;
|
||||
}
|
||||
|
||||
public void setBatchInputPointers(final InputPointers batchPointers) {
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
@SmallTest
|
||||
public class SuggestedWordsTests extends AndroidTestCase {
|
||||
public void testGetSuggestedWordsExcludingTypedWord() {
|
||||
final String TYPED_WORD = "typed";
|
||||
final int TYPED_WORD_FREQ = 5;
|
||||
final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
|
||||
final ArrayList<SuggestedWordInfo> list = CollectionUtils.newArrayList();
|
||||
list.add(new SuggestedWordInfo(TYPED_WORD, TYPED_WORD_FREQ,
|
||||
SuggestedWordInfo.KIND_TYPED, ""));
|
||||
for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
|
||||
list.add(new SuggestedWordInfo("" + i, 1, SuggestedWordInfo.KIND_CORRECTION, ""));
|
||||
}
|
||||
|
||||
final SuggestedWords words = new SuggestedWords(
|
||||
list,
|
||||
false /* typedWordValid */,
|
||||
false /* willAutoCorrect */,
|
||||
false /* isPunctuationSuggestions */,
|
||||
false /* isObsoleteSuggestions */,
|
||||
false /* isPrediction*/);
|
||||
assertEquals(NUMBER_OF_ADDED_SUGGESTIONS + 1, words.size());
|
||||
assertEquals("typed", words.getWord(0));
|
||||
assertEquals(SuggestedWordInfo.KIND_TYPED, words.getInfo(0).mKind);
|
||||
assertEquals("0", words.getWord(1));
|
||||
assertEquals(SuggestedWordInfo.KIND_CORRECTION, words.getInfo(1).mKind);
|
||||
assertEquals("4", words.getWord(5));
|
||||
assertEquals(SuggestedWordInfo.KIND_CORRECTION, words.getInfo(5).mKind);
|
||||
|
||||
final SuggestedWords wordsWithoutTyped = words.getSuggestedWordsExcludingTypedWord();
|
||||
assertEquals(words.size() - 1, wordsWithoutTyped.size());
|
||||
assertEquals("0", wordsWithoutTyped.getWord(0));
|
||||
assertEquals(SuggestedWordInfo.KIND_CORRECTION, wordsWithoutTyped.getInfo(0).mKind);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue