Make SuggestedWords immutable completely

Change-Id: I1b0f7b857e89307c987187c1969a2846aa97fdcc
main
Tadashi G. Takaoka 2012-03-05 22:08:16 +09:00
parent 40b6e666e1
commit e79b1a8312
4 changed files with 88 additions and 66 deletions

View File

@ -1827,9 +1827,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions);
} }
} }
final SuggestedWords suggestedWords = builder.build(); if (Utils.shouldBlockAutoCorrectionBySafetyNet(builder, mSuggest)) {
if (Utils.shouldBlockAutoCorrectionBySafetyNet(suggestedWords, mSuggest)) { builder.setShouldBlockAutoCorrectionBySafetyNet();
suggestedWords.setShouldBlockAutoCorrectionBySafetyNet();
} }
showSuggestions(builder.build(), typedWord); showSuggestions(builder.build(), typedWord);
} }
@ -1837,7 +1836,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) { public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) {
final CharSequence autoCorrection; final CharSequence autoCorrection;
if (suggestedWords.size() > 0) { if (suggestedWords.size() > 0) {
if (!suggestedWords.shouldBlockAutoCorrectionBySafetyNet() if (!suggestedWords.mShouldBlockAutoCorrectionBySafetyNet
&& suggestedWords.hasAutoCorrectionWord()) { && suggestedWords.hasAutoCorrectionWord()) {
autoCorrection = suggestedWords.getWord(1); autoCorrection = suggestedWords.getWord(1);
} else { } else {

View File

@ -26,18 +26,19 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
public class SuggestedWords { public class SuggestedWords {
public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, false, null); public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, false, false,
null);
private final List<CharSequence> mWords; private final List<CharSequence> mWords;
public final boolean mTypedWordValid; public final boolean mTypedWordValid;
public final boolean mHasAutoCorrectionCandidate; public final boolean mHasAutoCorrectionCandidate;
public final boolean mIsPunctuationSuggestions; public final boolean mIsPunctuationSuggestions;
public final boolean mShouldBlockAutoCorrectionBySafetyNet;
private final List<SuggestedWordInfo> mSuggestedWordInfoList; private final List<SuggestedWordInfo> mSuggestedWordInfoList;
// TODO: Make the following member final.
private boolean mShouldBlockAutoCorrectionBySafetyNet;
SuggestedWords(List<CharSequence> words, boolean typedWordValid, SuggestedWords(List<CharSequence> words, boolean typedWordValid,
boolean hasAutoCorrectionCandidate, boolean isPunctuationSuggestions, boolean hasAutoCorrectionCandidate, boolean isPunctuationSuggestions,
boolean shouldBlockAutoCorrectionBySafetyNet,
List<SuggestedWordInfo> suggestedWordInfoList) { List<SuggestedWordInfo> suggestedWordInfoList) {
if (words != null) { if (words != null) {
mWords = words; mWords = words;
@ -47,8 +48,8 @@ public class SuggestedWords {
mTypedWordValid = typedWordValid; mTypedWordValid = typedWordValid;
mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate; mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate;
mIsPunctuationSuggestions = isPunctuationSuggestions; mIsPunctuationSuggestions = isPunctuationSuggestions;
mShouldBlockAutoCorrectionBySafetyNet = shouldBlockAutoCorrectionBySafetyNet;
mSuggestedWordInfoList = suggestedWordInfoList; mSuggestedWordInfoList = suggestedWordInfoList;
mShouldBlockAutoCorrectionBySafetyNet = false;
} }
public int size() { public int size() {
@ -67,18 +68,20 @@ public class SuggestedWords {
return mHasAutoCorrectionCandidate && size() > 1 && !mTypedWordValid; return mHasAutoCorrectionCandidate && size() > 1 && !mTypedWordValid;
} }
// TODO: Remove this method.
public void setShouldBlockAutoCorrectionBySafetyNet() {
mShouldBlockAutoCorrectionBySafetyNet = true;
}
public boolean shouldBlockAutoCorrectionBySafetyNet() {
return mShouldBlockAutoCorrectionBySafetyNet;
}
public boolean willAutoCorrect() { public boolean willAutoCorrect() {
return !mTypedWordValid && mHasAutoCorrectionCandidate return !mTypedWordValid && mHasAutoCorrectionCandidate
&& !shouldBlockAutoCorrectionBySafetyNet(); && !mShouldBlockAutoCorrectionBySafetyNet;
}
@Override
public String toString() {
// Pretty-print method to help debug
return "SuggestedWords:"
+ " mTypedWordValid=" + mTypedWordValid
+ " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate
+ " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions
+ " mShouldBlockAutoCorrectionBySafetyNet=" + mShouldBlockAutoCorrectionBySafetyNet
+ " mWords=" + Arrays.toString(mWords.toArray());
} }
public static class Builder { public static class Builder {
@ -86,6 +89,7 @@ public class SuggestedWords {
private boolean mTypedWordValid; private boolean mTypedWordValid;
private boolean mHasMinimalSuggestion; private boolean mHasMinimalSuggestion;
private boolean mIsPunctuationSuggestions; private boolean mIsPunctuationSuggestions;
private boolean mShouldBlockAutoCorrectionBySafetyNet;
private List<SuggestedWordInfo> mSuggestedWordInfoList = private List<SuggestedWordInfo> mSuggestedWordInfoList =
new ArrayList<SuggestedWordInfo>(); new ArrayList<SuggestedWordInfo>();
@ -150,6 +154,11 @@ public class SuggestedWords {
return this; return this;
} }
public Builder setShouldBlockAutoCorrectionBySafetyNet() {
mShouldBlockAutoCorrectionBySafetyNet = true;
return this;
}
// Should get rid of the first one (what the user typed previously) from suggestions // Should get rid of the first one (what the user typed previously) from suggestions
// and replace it with what the user currently typed. // and replace it with what the user currently typed.
public Builder addTypedWordAndPreviousSuggestions(CharSequence typedWord, public Builder addTypedWordAndPreviousSuggestions(CharSequence typedWord,
@ -175,7 +184,8 @@ public class SuggestedWords {
public SuggestedWords build() { public SuggestedWords build() {
return new SuggestedWords(mWords, mTypedWordValid, mHasMinimalSuggestion, return new SuggestedWords(mWords, mTypedWordValid, mHasMinimalSuggestion,
mIsPunctuationSuggestions, mSuggestedWordInfoList); mIsPunctuationSuggestions, mShouldBlockAutoCorrectionBySafetyNet,
mSuggestedWordInfoList);
} }
public int size() { public int size() {
@ -186,13 +196,19 @@ public class SuggestedWords {
return mWords.get(pos); return mWords.get(pos);
} }
public boolean isTypedWordValid() {
return mTypedWordValid;
}
@Override @Override
public String toString() { public String toString() {
// Pretty-print method to help debug // Pretty-print method to help debug
return "SuggestedWords.Builder:" return "SuggestedWords.Builder:"
+ " mTypedWordValid = " + mTypedWordValid + " mTypedWordValid=" + mTypedWordValid
+ " mHasMinimalSuggestion = " + mHasMinimalSuggestion + " mHasMinimalSuggestion=" + mHasMinimalSuggestion
+ " mIsPunctuationSuggestions = " + mIsPunctuationSuggestions + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions
+ " mShouldBlockAutoCorrectionBySafetyNet="
+ mShouldBlockAutoCorrectionBySafetyNet
+ " mWords=" + Arrays.toString(mWords.toArray()); + " mWords=" + Arrays.toString(mWords.toArray());
} }
} }

View File

@ -190,19 +190,25 @@ public class Utils {
// TODO: Resolve the inconsistencies between the native auto correction algorithms and // TODO: Resolve the inconsistencies between the native auto correction algorithms and
// this safety net // this safety net
public static boolean shouldBlockAutoCorrectionBySafetyNet(SuggestedWords suggestions, public static boolean shouldBlockAutoCorrectionBySafetyNet(
Suggest suggest) { SuggestedWords.Builder suggestedWordsBuilder, Suggest suggest) {
// Safety net for auto correction. // Safety net for auto correction.
// Actually if we hit this safety net, it's actually a bug. // Actually if we hit this safety net, it's actually a bug.
if (suggestions.size() <= 1 || suggestions.mTypedWordValid) return false; if (suggestedWordsBuilder.size() <= 1 || suggestedWordsBuilder.isTypedWordValid()) {
return false;
}
// If user selected aggressive auto correction mode, there is no need to use the safety // If user selected aggressive auto correction mode, there is no need to use the safety
// net. // net.
if (suggest.isAggressiveAutoCorrectionMode()) return false; if (suggest.isAggressiveAutoCorrectionMode()) {
final CharSequence typedWord = suggestions.getWord(0); return false;
}
final CharSequence typedWord = suggestedWordsBuilder.getWord(0);
// If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH, // 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. // we should not use net because relatively edit distance can be big.
if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) return false; if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) {
final CharSequence suggestionWord = suggestions.getWord(1); return false;
}
final CharSequence suggestionWord = suggestedWordsBuilder.getWord(1);
final int typedWordLength = typedWord.length(); final int typedWordLength = typedWord.length();
final int maxEditDistanceOfNativeDictionary = final int maxEditDistanceOfNativeDictionary =
(typedWordLength < 5 ? 2 : typedWordLength / 2) + 1; (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1;

View File

@ -94,7 +94,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private final TextView mPreviewText; private final TextView mPreviewText;
private Listener mListener; private Listener mListener;
private SuggestedWords mSuggestions = SuggestedWords.EMPTY; private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
private final SuggestionsViewParams mParams; private final SuggestionsViewParams mParams;
private static final float MIN_TEXT_XSCALE = 0.70f; private static final float MIN_TEXT_XSCALE = 0.70f;
@ -258,10 +258,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
return a.getFraction(index, 1000, 1000, 1) / 1000.0f; return a.getFraction(index, 1000, 1000, 1) / 1000.0f;
} }
private CharSequence getStyledSuggestionWord(SuggestedWords suggestions, int pos) { private CharSequence getStyledSuggestionWord(SuggestedWords suggestedWords, int pos) {
final CharSequence word = suggestions.getWord(pos); final CharSequence word = suggestedWords.getWord(pos);
final boolean isAutoCorrect = pos == 1 && suggestions.willAutoCorrect(); final boolean isAutoCorrect = pos == 1 && suggestedWords.willAutoCorrect();
final boolean isTypedWordValid = pos == 0 && suggestions.mTypedWordValid; final boolean isTypedWordValid = pos == 0 && suggestedWords.mTypedWordValid;
if (!isAutoCorrect && !isTypedWordValid) if (!isAutoCorrect && !isTypedWordValid)
return word; return word;
@ -278,10 +278,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
return spannedWord; return spannedWord;
} }
private int getWordPosition(int index, SuggestedWords suggestions) { private int getWordPosition(int index, SuggestedWords suggestedWords) {
// TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
// suggestions. // suggestions.
final int centerPos = suggestions.willAutoCorrect() ? 1 : 0; final int centerPos = suggestedWords.willAutoCorrect() ? 1 : 0;
if (index == mCenterSuggestionIndex) { if (index == mCenterSuggestionIndex) {
return centerPos; return centerPos;
} else if (index == centerPos) { } else if (index == centerPos) {
@ -291,14 +291,14 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
} }
} }
private int getSuggestionTextColor(int index, SuggestedWords suggestions, int pos) { private int getSuggestionTextColor(int index, SuggestedWords suggestedWords, int pos) {
// TODO: Need to revisit this logic with bigram suggestions // TODO: Need to revisit this logic with bigram suggestions
final boolean isSuggested = (pos != 0); final boolean isSuggested = (pos != 0);
final int color; final int color;
if (index == mCenterSuggestionIndex && suggestions.willAutoCorrect()) { if (index == mCenterSuggestionIndex && suggestedWords.willAutoCorrect()) {
color = mColorAutoCorrect; color = mColorAutoCorrect;
} else if (index == mCenterSuggestionIndex && suggestions.mTypedWordValid) { } else if (index == mCenterSuggestionIndex && suggestedWords.mTypedWordValid) {
color = mColorValidTypedWord; color = mColorValidTypedWord;
} else if (isSuggested) { } else if (isSuggested) {
color = mColorSuggested; color = mColorSuggested;
@ -306,14 +306,14 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
color = mColorTypedWord; color = mColorTypedWord;
} }
if (LatinImeLogger.sDBG) { if (LatinImeLogger.sDBG) {
if (index == mCenterSuggestionIndex && suggestions.mHasAutoCorrectionCandidate if (index == mCenterSuggestionIndex && suggestedWords.mHasAutoCorrectionCandidate
&& suggestions.shouldBlockAutoCorrectionBySafetyNet()) { && suggestedWords.mShouldBlockAutoCorrectionBySafetyNet) {
return 0xFFFF0000; return 0xFFFF0000;
} }
} }
final SuggestedWordInfo info = (pos < suggestions.size()) final SuggestedWordInfo info = (pos < suggestedWords.size())
? suggestions.getInfo(pos) : null; ? suggestedWords.getInfo(pos) : null;
if (info != null && info.isObsoleteSuggestedWord()) { if (info != null && info.isObsoleteSuggestedWord()) {
return applyAlpha(color, mAlphaObsoleted); return applyAlpha(color, mAlphaObsoleted);
} else { } else {
@ -333,19 +333,19 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
params.gravity = Gravity.CENTER; params.gravity = Gravity.CENTER;
} }
public void layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer, public void layout(SuggestedWords suggestedWords, ViewGroup stripView, ViewGroup placer,
int stripWidth) { int stripWidth) {
if (suggestions.mIsPunctuationSuggestions) { if (suggestedWords.mIsPunctuationSuggestions) {
layoutPunctuationSuggestions(suggestions, stripView); layoutPunctuationSuggestions(suggestedWords, stripView);
return; return;
} }
final int countInStrip = mSuggestionsCountInStrip; final int countInStrip = mSuggestionsCountInStrip;
setupTexts(suggestions, countInStrip); setupTexts(suggestedWords, countInStrip);
mMoreSuggestionsAvailable = (suggestions.size() > countInStrip); mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
int x = 0; int x = 0;
for (int index = 0; index < countInStrip; index++) { for (int index = 0; index < countInStrip; index++) {
final int pos = getWordPosition(index, suggestions); final int pos = getWordPosition(index, suggestedWords);
if (index != 0) { if (index != 0) {
final View divider = mDividers.get(pos); final View divider = mDividers.get(pos);
@ -368,7 +368,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
// Disable this suggestion if the suggestion is null or empty. // Disable this suggestion if the suggestion is null or empty.
word.setEnabled(!TextUtils.isEmpty(styled)); word.setEnabled(!TextUtils.isEmpty(styled));
word.setTextColor(getSuggestionTextColor(index, suggestions, pos)); word.setTextColor(getSuggestionTextColor(index, suggestedWords, pos));
final int width = getSuggestionWidth(index, stripWidth); final int width = getSuggestionWidth(index, stripWidth);
final CharSequence text = getEllipsizedText(styled, width, word.getPaint()); final CharSequence text = getEllipsizedText(styled, width, word.getPaint());
final float scaleX = word.getTextScaleX(); final float scaleX = word.getTextScaleX();
@ -380,7 +380,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
x += word.getMeasuredWidth(); x += word.getMeasuredWidth();
if (DBG) { if (DBG) {
final CharSequence debugInfo = getDebugInfo(suggestions, pos); final CharSequence debugInfo = getDebugInfo(suggestedWords, pos);
if (debugInfo != null) { if (debugInfo != null) {
final TextView info = mInfos.get(pos); final TextView info = mInfos.get(pos);
info.setText(debugInfo); info.setText(debugInfo);
@ -412,11 +412,11 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
} }
} }
private void setupTexts(SuggestedWords suggestions, int countInStrip) { private void setupTexts(SuggestedWords suggestedWords, int countInStrip) {
mTexts.clear(); mTexts.clear();
final int count = Math.min(suggestions.size(), countInStrip); final int count = Math.min(suggestedWords.size(), countInStrip);
for (int pos = 0; pos < count; pos++) { for (int pos = 0; pos < count; pos++) {
final CharSequence styled = getStyledSuggestionWord(suggestions, pos); final CharSequence styled = getStyledSuggestionWord(suggestedWords, pos);
mTexts.add(styled); mTexts.add(styled);
} }
for (int pos = count; pos < countInStrip; pos++) { for (int pos = count; pos < countInStrip; pos++) {
@ -425,8 +425,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
} }
} }
private void layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) { private void layoutPunctuationSuggestions(SuggestedWords suggestedWords,
final int countInStrip = Math.min(suggestions.size(), PUNCTUATIONS_IN_STRIP); ViewGroup stripView) {
final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP);
for (int index = 0; index < countInStrip; index++) { for (int index = 0; index < countInStrip; index++) {
if (index != 0) { if (index != 0) {
// Add divider if this isn't the left most suggestion in suggestions strip. // Add divider if this isn't the left most suggestion in suggestions strip.
@ -436,7 +437,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final TextView word = mWords.get(index); final TextView word = mWords.get(index);
word.setEnabled(true); word.setEnabled(true);
word.setTextColor(mColorAutoCorrect); word.setTextColor(mColorAutoCorrect);
final CharSequence text = suggestions.getWord(index); final CharSequence text = suggestedWords.getWord(index);
word.setText(text); word.setText(text);
word.setTextScaleX(1.0f); word.setTextScaleX(1.0f);
word.setCompoundDrawables(null, null, null, null); word.setCompoundDrawables(null, null, null, null);
@ -635,13 +636,13 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view); mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view);
} }
public void setSuggestions(SuggestedWords suggestions) { public void setSuggestions(SuggestedWords suggestedWords) {
if (suggestions == null || suggestions.size() == 0) if (suggestedWords == null || suggestedWords.size() == 0)
return; return;
clear(); clear();
mSuggestions = suggestions; mSuggestedWords = suggestedWords;
mParams.layout(mSuggestions, mSuggestionsStrip, this, getWidth()); mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth());
} }
@ -664,7 +665,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
} }
public SuggestedWords getSuggestions() { public SuggestedWords getSuggestions() {
return mSuggestions; return mSuggestedWords;
} }
public void clear() { public void clear() {
@ -687,7 +688,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
@Override @Override
public boolean onCustomRequest(int requestCode) { public boolean onCustomRequest(int requestCode) {
final int index = requestCode; final int index = requestCode;
final CharSequence word = mSuggestions.getWord(index); final CharSequence word = mSuggestedWords.getWord(index);
mListener.pickSuggestionManually(index, word); mListener.pickSuggestionManually(index, word);
dismissMoreSuggestions(); dismissMoreSuggestions();
return true; return true;
@ -732,7 +733,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final int maxWidth = stripWidth - container.getPaddingLeft() final int maxWidth = stripWidth - container.getPaddingLeft()
- container.getPaddingRight(); - container.getPaddingRight();
final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder;
builder.layout(mSuggestions, params.mSuggestionsCountInStrip, maxWidth, builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth,
(int)(maxWidth * params.mMinMoreSuggestionsWidth), (int)(maxWidth * params.mMinMoreSuggestionsWidth),
params.mMaxMoreSuggestionsRow); params.mMaxMoreSuggestionsRow);
mMoreSuggestionsView.setKeyboard(builder.build()); mMoreSuggestionsView.setKeyboard(builder.build());
@ -834,10 +835,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
if (!(tag instanceof Integer)) if (!(tag instanceof Integer))
return; return;
final int index = (Integer) tag; final int index = (Integer) tag;
if (index >= mSuggestions.size()) if (index >= mSuggestedWords.size())
return; return;
final CharSequence word = mSuggestions.getWord(index); final CharSequence word = mSuggestedWords.getWord(index);
mListener.pickSuggestionManually(index, word); mListener.pickSuggestionManually(index, word);
} }