Always show the typed word in recorrections.

Bug: 11330140
Bug: 17875601
Bug: 17623275
Change-Id: Ie4620f36f312c54c7b01b5f6cbdb0bc9171b6179
This commit is contained in:
Jean Chalard 2014-10-08 14:40:03 +09:00
parent 41302021d6
commit bc18005948
7 changed files with 38 additions and 97 deletions

View File

@ -1627,7 +1627,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
@Override
public void showAddToDictionaryHint(final String word) {
public void suggestAddingToDictionary(final String word, final boolean isFromSuggestionStrip) {
if (!hasSuggestionStripView()) {
return;
}
@ -1637,7 +1637,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
wordToShow = word;
}
mSuggestionStripView.showAddToDictionaryHint(wordToShow);
mSuggestionStripView.showAddToDictionaryHint(wordToShow,
isFromSuggestionStrip /* shouldShowWordToSave */);
}
// This will show either an empty suggestion strip (if prediction is enabled) or

View File

@ -413,28 +413,6 @@ public class SuggestedWords {
return isPrediction(mInputStyle);
}
// 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.
// This is only ever called by recorrection at the moment, hence the ForRecorrection moniker.
public SuggestedWords getSuggestedWordsExcludingTypedWordForRecorrection() {
final ArrayList<SuggestedWordInfo> newSuggestions = new ArrayList<>();
String typedWord = null;
for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
final SuggestedWordInfo info = mSuggestedWordInfoList.get(i);
if (!info.isKindOf(SuggestedWordInfo.KIND_TYPED)) {
newSuggestions.add(info);
} else {
assert(null == typedWord);
typedWord = info.mWord;
}
}
// 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, null /* rawSuggestions */, typedWord,
true /* typedWordValid */, false /* willAutoCorrect */, mIsObsoleteSuggestions,
SuggestedWords.INPUT_STYLE_RECORRECTION, NOT_A_SEQUENCE_NUMBER);
}
// Creates a new SuggestedWordInfo from the currently suggested words that removes all but the
// last word of all suggestions, separated by a space. This is necessary because when we commit
// a multiple-word suggestion, the IME only retains the last word as the composing word, and

View File

@ -349,7 +349,8 @@ public final class InputLogic {
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
if (shouldShowAddToDictionaryHint) {
mSuggestionStripViewAccessor.showAddToDictionaryHint(suggestion);
mSuggestionStripViewAccessor.suggestAddingToDictionary(suggestion,
true /* isFromSuggestionStrip */);
} else {
// If we're not showing the "Touch again to save", then update the suggestion strip.
// That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
@ -1485,6 +1486,11 @@ public final class InputLogic {
if (numberOfCharsInWordBeforeCursor > expectedCursorPosition) return;
final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
final String typedWord = range.mWord.toString();
suggestions.add(new SuggestedWordInfo(typedWord,
SuggestedWords.MAX_SUGGESTIONS + 1,
SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
if (!isResumableWord(settingsValues, typedWord)) {
mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
return;
@ -1517,30 +1523,14 @@ public final class InputLogic {
mConnection.maybeMoveTheCursorAroundAndRestoreToWorkaroundABug();
mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor());
if (suggestions.size() <= 0) {
if (suggestions.size() <= 1) {
// If there weren't any suggestion spans on this word, suggestions#size() will be 1
// if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
// have no useful suggestions, so we will try to compute some for it instead.
mInputLogicHandler.getSuggestedWords(Suggest.SESSION_ID_TYPING,
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(
final SuggestedWords suggestedWordsIncludingTypedWord) {
final SuggestedWords suggestedWords;
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 #getSuggestedWordsExcludingTypedWordForRecorrection()
// method sets willAutoCorrect to false.
suggestedWords = suggestedWordsIncludingTypedWord
.getSuggestedWordsExcludingTypedWordForRecorrection();
} 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;
}
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
mIsAutoCorrectionIndicatorOn = false;
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
}});
@ -1684,7 +1674,8 @@ public final class InputLogic {
mConnection.getExpectedSelectionStart(),
mConnection.getExpectedSelectionEnd());
}
mSuggestionStripViewAccessor.showAddToDictionaryHint(originallyTypedWordString);
mSuggestionStripViewAccessor.suggestAddingToDictionary(originallyTypedWordString,
false /* isFromSuggestionStrip */);
} else {
// We have a separator between the word and the cursor: we should show predictions.
inputTransaction.setRequiresUpdateSuggestions();

View File

@ -553,12 +553,12 @@ final class SuggestionStripLayoutHelper {
return countInStrip;
}
public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip) {
final boolean shouldShowUiToAcceptTypedWord = Settings.getInstance().getCurrent()
.mShouldShowLxxSuggestionUi;
public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip,
final boolean shouldShowWordToSave) {
final boolean showsHintWithWord = shouldShowWordToSave
|| !Settings.getInstance().getCurrent().mShouldShowLxxSuggestionUi;
final int stripWidth = addToDictionaryStrip.getWidth();
final int width = shouldShowUiToAcceptTypedWord ? stripWidth
: stripWidth - mDividerWidth - mPadding * 2;
final int width = stripWidth - (showsHintWithWord ? mDividerWidth + mPadding * 2 : 0);
final TextView wordView = (TextView)addToDictionaryStrip.findViewById(R.id.word_to_save);
wordView.setTextColor(mColorTypedWord);
@ -569,7 +569,7 @@ final class SuggestionStripLayoutHelper {
wordView.setText(wordToSave);
wordView.setTextScaleX(wordScaleX);
setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
final int wordVisibility = shouldShowUiToAcceptTypedWord ? View.GONE : View.VISIBLE;
final int wordVisibility = showsHintWithWord ? View.VISIBLE : View.GONE;
wordView.setVisibility(wordVisibility);
addToDictionaryStrip.findViewById(R.id.word_to_save_divider).setVisibility(wordVisibility);
@ -579,12 +579,7 @@ final class SuggestionStripLayoutHelper {
final float hintWeight;
final TextView hintView = (TextView)addToDictionaryStrip.findViewById(
R.id.hint_add_to_dictionary);
if (shouldShowUiToAcceptTypedWord) {
hintText = res.getText(R.string.hint_add_to_dictionary_without_word);
hintWidth = width;
hintWeight = 1.0f;
hintView.setGravity(Gravity.CENTER);
} else {
if (showsHintWithWord) {
final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip)
== ViewCompat.LAYOUT_DIRECTION_RTL);
final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW;
@ -595,6 +590,11 @@ final class SuggestionStripLayoutHelper {
hintWidth = width - wordWidth;
hintWeight = 1.0f - mCenterSuggestionWeight;
hintView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
} else {
hintText = res.getText(R.string.hint_add_to_dictionary_without_word);
hintWidth = width;
hintWeight = 1.0f;
hintView.setGravity(Gravity.CENTER);
}
hintView.setTextColor(mColorAutoCorrect);
final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());

View File

@ -231,8 +231,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
return mStripVisibilityGroup.isShowingAddToDictionaryStrip();
}
public void showAddToDictionaryHint(final String word) {
mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip);
public void showAddToDictionaryHint(final String word, final boolean shouldShowWordToSave) {
mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip, shouldShowWordToSave);
// {@link TextView#setTag()} is used to hold the word to be added to dictionary. The word
// will be extracted at {@link #onClick(View)}.
mAddToDictionaryStrip.setTag(word);
@ -501,7 +501,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
return;
}
final Object tag = view.getTag();
// {@link String} tag is set at {@link #showAddToDictionaryHint(String,CharSequence)}.
// {@link String} tag is set at {@link #suggestAddingToDictionary(String,CharSequence)}.
if (tag instanceof String) {
final String wordToSave = (String)tag;
mListener.addWordToUserDictionary(wordToSave);

View File

@ -22,7 +22,7 @@ import com.android.inputmethod.latin.SuggestedWords;
* An object that gives basic control of a suggestion strip and some info on it.
*/
public interface SuggestionStripViewAccessor {
public void showAddToDictionaryHint(final String word);
public void suggestAddingToDictionary(final String word, final boolean isFromSuggestionStrip);
public boolean isShowingAddToDictionaryHint();
public void dismissAddToDictionaryHint();
public void setNeutralSuggestionStrip();

View File

@ -59,40 +59,6 @@ public class SuggestedWordsTests extends AndroidTestCase {
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
}
public void testGetSuggestedWordsExcludingTypedWord() {
final String TYPED_WORD = "typed";
final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
final int KIND_OF_SECOND_CORRECTION = SuggestedWordInfo.KIND_CORRECTION;
final ArrayList<SuggestedWordInfo> list = new ArrayList<>();
list.add(createTypedWordInfo(TYPED_WORD));
for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
list.add(createCorrectionWordInfo(Integer.toString(i)));
}
final SuggestedWords words = new SuggestedWords(
list, null /* rawSuggestions */,
false /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
SuggestedWords.INPUT_STYLE_NONE);
assertEquals(NUMBER_OF_ADDED_SUGGESTIONS + 1, words.size());
assertEquals("typed", words.getWord(0));
assertTrue(words.getInfo(0).isKindOf(SuggestedWordInfo.KIND_TYPED));
assertEquals("0", words.getWord(1));
assertTrue(words.getInfo(1).isKindOf(KIND_OF_SECOND_CORRECTION));
assertEquals("4", words.getWord(5));
assertTrue(words.getInfo(5).isKindOf(KIND_OF_SECOND_CORRECTION));
final SuggestedWords wordsWithoutTyped =
words.getSuggestedWordsExcludingTypedWordForRecorrection();
// Make sure that the typed word has indeed been excluded, by testing the size of the
// suggested words, the string and the kind of the top suggestion, which should match
// the string and kind of what we inserted after the typed word.
assertEquals(words.size() - 1, wordsWithoutTyped.size());
assertEquals("0", wordsWithoutTyped.getWord(0));
assertTrue(wordsWithoutTyped.getInfo(0).isKindOf(KIND_OF_SECOND_CORRECTION));
}
// Helper for testGetTransformedWordInfo
private SuggestedWordInfo transformWordInfo(final String info,
final int trailingSingleQuotesCount) {
@ -141,9 +107,14 @@ public class SuggestedWordsTests extends AndroidTestCase {
assertNotNull(typedWord);
assertEquals(TYPED_WORD, typedWord.mWord);
// Make sure getTypedWordInfoOrNull() returns null.
final SuggestedWords wordsWithoutTypedWord =
wordsWithTypedWord.getSuggestedWordsExcludingTypedWordForRecorrection();
// Make sure getTypedWordInfoOrNull() returns null when no typed word.
list.remove(0);
final SuggestedWords wordsWithoutTypedWord = new SuggestedWords(
list, null /* rawSuggestions */,
false /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
SuggestedWords.INPUT_STYLE_NONE);
assertNull(wordsWithoutTypedWord.getTypedWordInfoOrNull());
// Make sure getTypedWordInfoOrNull() returns null.