Always show the typed word in recorrections.
Bug: 11330140 Bug: 17875601 Bug: 17623275 Change-Id: Ie4620f36f312c54c7b01b5f6cbdb0bc9171b6179main
parent
41302021d6
commit
bc18005948
|
@ -1627,7 +1627,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showAddToDictionaryHint(final String word) {
|
public void suggestAddingToDictionary(final String word, final boolean isFromSuggestionStrip) {
|
||||||
if (!hasSuggestionStripView()) {
|
if (!hasSuggestionStripView()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1637,7 +1637,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
} else {
|
} else {
|
||||||
wordToShow = word;
|
wordToShow = word;
|
||||||
}
|
}
|
||||||
mSuggestionStripView.showAddToDictionaryHint(wordToShow);
|
mSuggestionStripView.showAddToDictionaryHint(wordToShow,
|
||||||
|
isFromSuggestionStrip /* shouldShowWordToSave */);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will show either an empty suggestion strip (if prediction is enabled) or
|
// This will show either an empty suggestion strip (if prediction is enabled) or
|
||||||
|
|
|
@ -413,28 +413,6 @@ public class SuggestedWords {
|
||||||
return isPrediction(mInputStyle);
|
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
|
// 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
|
// 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
|
// a multiple-word suggestion, the IME only retains the last word as the composing word, and
|
||||||
|
|
|
@ -349,7 +349,8 @@ public final class InputLogic {
|
||||||
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
|
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
|
||||||
|
|
||||||
if (shouldShowAddToDictionaryHint) {
|
if (shouldShowAddToDictionaryHint) {
|
||||||
mSuggestionStripViewAccessor.showAddToDictionaryHint(suggestion);
|
mSuggestionStripViewAccessor.suggestAddingToDictionary(suggestion,
|
||||||
|
true /* isFromSuggestionStrip */);
|
||||||
} else {
|
} else {
|
||||||
// If we're not showing the "Touch again to save", then update the suggestion strip.
|
// 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.
|
// 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;
|
if (numberOfCharsInWordBeforeCursor > expectedCursorPosition) return;
|
||||||
final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
|
final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
|
||||||
final String typedWord = range.mWord.toString();
|
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)) {
|
if (!isResumableWord(settingsValues, typedWord)) {
|
||||||
mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
|
mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
|
||||||
return;
|
return;
|
||||||
|
@ -1517,30 +1523,14 @@ public final class InputLogic {
|
||||||
mConnection.maybeMoveTheCursorAroundAndRestoreToWorkaroundABug();
|
mConnection.maybeMoveTheCursorAroundAndRestoreToWorkaroundABug();
|
||||||
mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
|
mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
|
||||||
expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor());
|
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 there weren't any suggestion spans on this word, suggestions#size() will be 1
|
||||||
// if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
|
// if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
|
||||||
// have no useful suggestions, so we will try to compute some for it instead.
|
// have no useful suggestions, so we will try to compute some for it instead.
|
||||||
mInputLogicHandler.getSuggestedWords(Suggest.SESSION_ID_TYPING,
|
mInputLogicHandler.getSuggestedWords(Suggest.SESSION_ID_TYPING,
|
||||||
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
|
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onGetSuggestedWords(
|
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
mIsAutoCorrectionIndicatorOn = false;
|
mIsAutoCorrectionIndicatorOn = false;
|
||||||
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
|
||||||
}});
|
}});
|
||||||
|
@ -1684,7 +1674,8 @@ public final class InputLogic {
|
||||||
mConnection.getExpectedSelectionStart(),
|
mConnection.getExpectedSelectionStart(),
|
||||||
mConnection.getExpectedSelectionEnd());
|
mConnection.getExpectedSelectionEnd());
|
||||||
}
|
}
|
||||||
mSuggestionStripViewAccessor.showAddToDictionaryHint(originallyTypedWordString);
|
mSuggestionStripViewAccessor.suggestAddingToDictionary(originallyTypedWordString,
|
||||||
|
false /* isFromSuggestionStrip */);
|
||||||
} else {
|
} else {
|
||||||
// We have a separator between the word and the cursor: we should show predictions.
|
// We have a separator between the word and the cursor: we should show predictions.
|
||||||
inputTransaction.setRequiresUpdateSuggestions();
|
inputTransaction.setRequiresUpdateSuggestions();
|
||||||
|
|
|
@ -553,12 +553,12 @@ final class SuggestionStripLayoutHelper {
|
||||||
return countInStrip;
|
return countInStrip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip) {
|
public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip,
|
||||||
final boolean shouldShowUiToAcceptTypedWord = Settings.getInstance().getCurrent()
|
final boolean shouldShowWordToSave) {
|
||||||
.mShouldShowLxxSuggestionUi;
|
final boolean showsHintWithWord = shouldShowWordToSave
|
||||||
|
|| !Settings.getInstance().getCurrent().mShouldShowLxxSuggestionUi;
|
||||||
final int stripWidth = addToDictionaryStrip.getWidth();
|
final int stripWidth = addToDictionaryStrip.getWidth();
|
||||||
final int width = shouldShowUiToAcceptTypedWord ? stripWidth
|
final int width = stripWidth - (showsHintWithWord ? mDividerWidth + mPadding * 2 : 0);
|
||||||
: stripWidth - mDividerWidth - mPadding * 2;
|
|
||||||
|
|
||||||
final TextView wordView = (TextView)addToDictionaryStrip.findViewById(R.id.word_to_save);
|
final TextView wordView = (TextView)addToDictionaryStrip.findViewById(R.id.word_to_save);
|
||||||
wordView.setTextColor(mColorTypedWord);
|
wordView.setTextColor(mColorTypedWord);
|
||||||
|
@ -569,7 +569,7 @@ final class SuggestionStripLayoutHelper {
|
||||||
wordView.setText(wordToSave);
|
wordView.setText(wordToSave);
|
||||||
wordView.setTextScaleX(wordScaleX);
|
wordView.setTextScaleX(wordScaleX);
|
||||||
setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
|
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);
|
wordView.setVisibility(wordVisibility);
|
||||||
addToDictionaryStrip.findViewById(R.id.word_to_save_divider).setVisibility(wordVisibility);
|
addToDictionaryStrip.findViewById(R.id.word_to_save_divider).setVisibility(wordVisibility);
|
||||||
|
|
||||||
|
@ -579,12 +579,7 @@ final class SuggestionStripLayoutHelper {
|
||||||
final float hintWeight;
|
final float hintWeight;
|
||||||
final TextView hintView = (TextView)addToDictionaryStrip.findViewById(
|
final TextView hintView = (TextView)addToDictionaryStrip.findViewById(
|
||||||
R.id.hint_add_to_dictionary);
|
R.id.hint_add_to_dictionary);
|
||||||
if (shouldShowUiToAcceptTypedWord) {
|
if (showsHintWithWord) {
|
||||||
hintText = res.getText(R.string.hint_add_to_dictionary_without_word);
|
|
||||||
hintWidth = width;
|
|
||||||
hintWeight = 1.0f;
|
|
||||||
hintView.setGravity(Gravity.CENTER);
|
|
||||||
} else {
|
|
||||||
final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip)
|
final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip)
|
||||||
== ViewCompat.LAYOUT_DIRECTION_RTL);
|
== ViewCompat.LAYOUT_DIRECTION_RTL);
|
||||||
final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW;
|
final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW;
|
||||||
|
@ -595,6 +590,11 @@ final class SuggestionStripLayoutHelper {
|
||||||
hintWidth = width - wordWidth;
|
hintWidth = width - wordWidth;
|
||||||
hintWeight = 1.0f - mCenterSuggestionWeight;
|
hintWeight = 1.0f - mCenterSuggestionWeight;
|
||||||
hintView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
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);
|
hintView.setTextColor(mColorAutoCorrect);
|
||||||
final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
|
final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
|
||||||
|
|
|
@ -231,8 +231,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
return mStripVisibilityGroup.isShowingAddToDictionaryStrip();
|
return mStripVisibilityGroup.isShowingAddToDictionaryStrip();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showAddToDictionaryHint(final String word) {
|
public void showAddToDictionaryHint(final String word, final boolean shouldShowWordToSave) {
|
||||||
mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip);
|
mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip, shouldShowWordToSave);
|
||||||
// {@link TextView#setTag()} is used to hold the word to be added to dictionary. The word
|
// {@link TextView#setTag()} is used to hold the word to be added to dictionary. The word
|
||||||
// will be extracted at {@link #onClick(View)}.
|
// will be extracted at {@link #onClick(View)}.
|
||||||
mAddToDictionaryStrip.setTag(word);
|
mAddToDictionaryStrip.setTag(word);
|
||||||
|
@ -501,7 +501,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Object tag = view.getTag();
|
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) {
|
if (tag instanceof String) {
|
||||||
final String wordToSave = (String)tag;
|
final String wordToSave = (String)tag;
|
||||||
mListener.addWordToUserDictionary(wordToSave);
|
mListener.addWordToUserDictionary(wordToSave);
|
||||||
|
|
|
@ -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.
|
* An object that gives basic control of a suggestion strip and some info on it.
|
||||||
*/
|
*/
|
||||||
public interface SuggestionStripViewAccessor {
|
public interface SuggestionStripViewAccessor {
|
||||||
public void showAddToDictionaryHint(final String word);
|
public void suggestAddingToDictionary(final String word, final boolean isFromSuggestionStrip);
|
||||||
public boolean isShowingAddToDictionaryHint();
|
public boolean isShowingAddToDictionaryHint();
|
||||||
public void dismissAddToDictionaryHint();
|
public void dismissAddToDictionaryHint();
|
||||||
public void setNeutralSuggestionStrip();
|
public void setNeutralSuggestionStrip();
|
||||||
|
|
|
@ -59,40 +59,6 @@ public class SuggestedWordsTests extends AndroidTestCase {
|
||||||
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
|
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
|
// Helper for testGetTransformedWordInfo
|
||||||
private SuggestedWordInfo transformWordInfo(final String info,
|
private SuggestedWordInfo transformWordInfo(final String info,
|
||||||
final int trailingSingleQuotesCount) {
|
final int trailingSingleQuotesCount) {
|
||||||
|
@ -141,9 +107,14 @@ public class SuggestedWordsTests extends AndroidTestCase {
|
||||||
assertNotNull(typedWord);
|
assertNotNull(typedWord);
|
||||||
assertEquals(TYPED_WORD, typedWord.mWord);
|
assertEquals(TYPED_WORD, typedWord.mWord);
|
||||||
|
|
||||||
// Make sure getTypedWordInfoOrNull() returns null.
|
// Make sure getTypedWordInfoOrNull() returns null when no typed word.
|
||||||
final SuggestedWords wordsWithoutTypedWord =
|
list.remove(0);
|
||||||
wordsWithTypedWord.getSuggestedWordsExcludingTypedWordForRecorrection();
|
final SuggestedWords wordsWithoutTypedWord = new SuggestedWords(
|
||||||
|
list, null /* rawSuggestions */,
|
||||||
|
false /* typedWordValid */,
|
||||||
|
false /* willAutoCorrect */,
|
||||||
|
false /* isObsoleteSuggestions */,
|
||||||
|
SuggestedWords.INPUT_STYLE_NONE);
|
||||||
assertNull(wordsWithoutTypedWord.getTypedWordInfoOrNull());
|
assertNull(wordsWithoutTypedWord.getTypedWordInfoOrNull());
|
||||||
|
|
||||||
// Make sure getTypedWordInfoOrNull() returns null.
|
// Make sure getTypedWordInfoOrNull() returns null.
|
||||||
|
|
Loading…
Reference in New Issue