Merge "Introduce SuggestedWords class to represent suggestions list"

main
Tadashi G. Takaoka 2010-12-12 03:58:50 -08:00 committed by Android (Google) Code Review
commit 3ef38b2907
7 changed files with 254 additions and 147 deletions

View File

@ -23,6 +23,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/candidate_strip_height" android:layout_height="@dimen/candidate_strip_height"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingRight="12dip"
> >
<ImageView <ImageView
android:id="@+id/candidate_divider" android:id="@+id/candidate_divider"
@ -44,6 +45,16 @@
android:focusable="true" android:focusable="true"
android:clickable="true" android:clickable="true"
android:gravity="center_vertical|center_horizontal" android:gravity="center_vertical|center_horizontal"
android:paddingLeft="12dip" android:paddingLeft="12dip" />
android:paddingRight="12dip" /> <TextView
android:id="@+id/candidate_debug_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:textSize="10dip"
android:textColor="#ff808080"
android:focusable="false"
android:clickable="false"
android:gravity="bottom"
android:paddingLeft="4dip" />
</LinearLayout> </LinearLayout>

View File

@ -43,11 +43,9 @@ import android.widget.PopupWindow;
import android.widget.TextView; import android.widget.TextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener { public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener {
private LatinIME mService; private LatinIME mService;
private final ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
private final ArrayList<View> mWords = new ArrayList<View>(); private final ArrayList<View> mWords = new ArrayList<View>();
private final TextView mPreviewText; private final TextView mPreviewText;
@ -64,27 +62,12 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
private final CharacterStyle mInvertedForegroundColorSpan; private final CharacterStyle mInvertedForegroundColorSpan;
private final CharacterStyle mInvertedBackgroundColorSpan; private final CharacterStyle mInvertedBackgroundColorSpan;
private boolean mShowingCompletions; private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
private boolean mShowingAutoCorrectionInverted; private boolean mShowingAutoCorrectionInverted;
private boolean mShowingAddToDictionary; private boolean mShowingAddToDictionary;
private final UiHandler mHandler = new UiHandler(); private final UiHandler mHandler = new UiHandler();
private static class UpdateSuggestionsArgs {
public final List<CharSequence> mSuggestions;
public final boolean mCompletions;
public final boolean mTypedWordValid;
public final boolean mHaveMinimalSuggestion;
public UpdateSuggestionsArgs(List<CharSequence> suggestions, boolean completions,
boolean typedWordValid, boolean haveMinimalSuggestion) {
mSuggestions = suggestions;
mCompletions = completions;
mTypedWordValid = typedWordValid;
mHaveMinimalSuggestion = haveMinimalSuggestion;
}
}
private class UiHandler extends Handler { private class UiHandler extends Handler {
private static final int MSG_HIDE_PREVIEW = 0; private static final int MSG_HIDE_PREVIEW = 0;
private static final int MSG_UPDATE_SUGGESTION = 1; private static final int MSG_UPDATE_SUGGESTION = 1;
@ -99,9 +82,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
hidePreview(); hidePreview();
break; break;
case MSG_UPDATE_SUGGESTION: case MSG_UPDATE_SUGGESTION:
UpdateSuggestionsArgs args = (UpdateSuggestionsArgs)msg.obj; updateSuggestions((SuggestedWords)msg.obj);
updateSuggestions(args.mSuggestions, args.mCompletions, args.mTypedWordValid,
args.mHaveMinimalSuggestion);
break; break;
} }
} }
@ -115,11 +96,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
removeMessages(MSG_HIDE_PREVIEW); removeMessages(MSG_HIDE_PREVIEW);
} }
public void postUpdateSuggestions(List<CharSequence> suggestions, boolean completions, public void postUpdateSuggestions(SuggestedWords suggestions) {
boolean typedWordValid, boolean haveMinimalSuggestion) {
cancelUpdateSuggestions(); cancelUpdateSuggestions();
sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION, new UpdateSuggestionsArgs( sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION, suggestions),
suggestions, completions, typedWordValid, haveMinimalSuggestion)),
DELAY_UPDATE_SUGGESTION); DELAY_UPDATE_SUGGESTION);
} }
@ -167,7 +146,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
tv.setOnLongClickListener(this); tv.setOnLongClickListener(this);
ImageView divider = (ImageView)v.findViewById(R.id.candidate_divider); ImageView divider = (ImageView)v.findViewById(R.id.candidate_divider);
// Do not display divider of first candidate. // Do not display divider of first candidate.
divider.setVisibility(i == 0 ? View.GONE : View.VISIBLE); divider.setVisibility(i == 0 ? GONE : VISIBLE);
mWords.add(v); mWords.add(v);
} }
@ -182,44 +161,35 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mService = listener; mService = listener;
} }
public void setSuggestions(List<CharSequence> suggestions, boolean completions, public void setSuggestions(SuggestedWords suggestions) {
boolean typedWordValid, boolean haveMinimalSuggestion) { // Don't update suggestions when there is only one suggestion found.
// Don't update suggestions when there is zero or only one suggestion found. // Empty (size zero) suggestions will be passed in order to clear candidate view.
if (suggestions != null && suggestions.size() <= 1) if (suggestions == null || suggestions.size() == 1)
return; return;
if (mShowingAutoCorrectionInverted) { if (mShowingAutoCorrectionInverted) {
mHandler.postUpdateSuggestions(suggestions, completions, typedWordValid, mHandler.postUpdateSuggestions(suggestions);
haveMinimalSuggestion);
} else { } else {
updateSuggestions(suggestions, completions, typedWordValid, haveMinimalSuggestion); updateSuggestions(suggestions);
} }
} }
private void updateSuggestions(List<CharSequence> suggestions, boolean completions, private void updateSuggestions(SuggestedWords suggestions) {
boolean typedWordValid, boolean haveMinimalSuggestion) {
clear(); clear();
if (suggestions != null) { mSuggestions = suggestions;
int insertCount = Math.min(suggestions.size(), MAX_SUGGESTIONS); final int count = suggestions.size();
for (CharSequence suggestion : suggestions) { final Object[] debugInfo = suggestions.mDebugInfo;
mSuggestions.add(suggestion);
if (--insertCount == 0)
break;
}
}
final int count = mSuggestions.size();
boolean existsAutoCompletion = false;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
CharSequence suggestion = mSuggestions.get(i); CharSequence word = suggestions.getWord(i);
if (suggestion == null) continue; if (word == null) continue;
final int wordLength = suggestion.length(); final int wordLength = word.length();
final View v = mWords.get(i); final View v = mWords.get(i);
final TextView tv = (TextView)v.findViewById(R.id.candidate_word); final TextView tv = (TextView)v.findViewById(R.id.candidate_word);
final TextView dv = (TextView)v.findViewById(R.id.candidate_debug_info);
tv.setTextColor(mColorNormal); tv.setTextColor(mColorNormal);
if (haveMinimalSuggestion if (suggestions.mHasMinimalSuggestion
&& ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) { && ((i == 1 && !suggestions.mTypedWordValid) ||
(i == 0 && suggestions.mTypedWordValid))) {
final CharacterStyle style; final CharacterStyle style;
if (mConfigCandidateHighlightFontColorEnabled) { if (mConfigCandidateHighlightFontColorEnabled) {
style = BOLD_SPAN; style = BOLD_SPAN;
@ -227,10 +197,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
} else { } else {
style = UNDERLINE_SPAN; style = UNDERLINE_SPAN;
} }
final Spannable word = new SpannableString(suggestion); final Spannable spannedWord = new SpannableString(word);
word.setSpan(style, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); spannedWord.setSpan(style, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
suggestion = word; word = spannedWord;
existsAutoCompletion = true;
} else if (i != 0 || (wordLength == 1 && count > 1)) { } else if (i != 0 || (wordLength == 1 && count > 1)) {
// HACK: even if i == 0, we use mColorOther when this // HACK: even if i == 0, we use mColorOther when this
// suggestion's length is 1 // suggestion's length is 1
@ -239,16 +208,18 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
if (mConfigCandidateHighlightFontColorEnabled) if (mConfigCandidateHighlightFontColorEnabled)
tv.setTextColor(mColorOther); tv.setTextColor(mColorOther);
} }
tv.setText(suggestion); tv.setText(word);
tv.setClickable(true); tv.setClickable(true);
if (debugInfo != null && i < debugInfo.length && debugInfo[i] != null
&& !TextUtils.isEmpty(debugInfo[i].toString())) {
dv.setText(debugInfo[i].toString());
dv.setVisibility(VISIBLE);
} else {
dv.setVisibility(GONE);
}
addView(v); addView(v);
} }
mShowingCompletions = completions;
// TODO: Move this call back to LatinIME
if (mConfigCandidateHighlightFontColorEnabled)
mService.onAutoCompletionStateChanged(existsAutoCompletion);
scrollTo(0, getScrollY()); scrollTo(0, getScrollY());
requestLayout(); requestLayout();
} }
@ -267,15 +238,19 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mShowingAutoCorrectionInverted = true; mShowingAutoCorrectionInverted = true;
} }
public boolean isConfigCandidateHighlightFontColorEnabled() {
return mConfigCandidateHighlightFontColorEnabled;
}
public boolean isShowingAddToDictionaryHint() { public boolean isShowingAddToDictionaryHint() {
return mShowingAddToDictionary; return mShowingAddToDictionary;
} }
public void showAddToDictionaryHint(CharSequence word) { public void showAddToDictionaryHint(CharSequence word) {
ArrayList<CharSequence> suggestions = new ArrayList<CharSequence>(); SuggestedWords.Builder builder = new SuggestedWords.Builder()
suggestions.add(word); .addWord(word)
suggestions.add(getContext().getText(R.string.hint_add_to_dictionary)); .addWord(getContext().getText(R.string.hint_add_to_dictionary));
setSuggestions(suggestions, false, false, false); setSuggestions(builder.build());
mShowingAddToDictionary = true; mShowingAddToDictionary = true;
// Disable R.string.hint_add_to_dictionary button // Disable R.string.hint_add_to_dictionary button
TextView tv = (TextView)getChildAt(1).findViewById(R.id.candidate_word); TextView tv = (TextView)getChildAt(1).findViewById(R.id.candidate_word);
@ -288,14 +263,11 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
return true; return true;
} }
/* package */ List<CharSequence> getSuggestions() { public SuggestedWords getSuggestions() {
return mSuggestions; return mSuggestions;
} }
public void clear() { public void clear() {
// Don't call mSuggestions.clear() because it's being used for logging
// in LatinIME.pickSuggestionManually().
mSuggestions.clear();
mShowingAddToDictionary = false; mShowingAddToDictionary = false;
mShowingAutoCorrectionInverted = false; mShowingAutoCorrectionInverted = false;
removeAllViews(); removeAllViews();
@ -337,7 +309,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
@Override @Override
public boolean onLongClick(View view) { public boolean onLongClick(View view) {
int index = (Integer) view.getTag(); int index = (Integer) view.getTag();
CharSequence word = mSuggestions.get(index); CharSequence word = mSuggestions.getWord(index);
if (word.length() < 2) if (word.length() < 2)
return false; return false;
addToDictionary(word); addToDictionary(word);
@ -347,12 +319,12 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
@Override @Override
public void onClick(View view) { public void onClick(View view) {
int index = (Integer) view.getTag(); int index = (Integer) view.getTag();
CharSequence word = mSuggestions.get(index); CharSequence word = mSuggestions.getWord(index);
if (mShowingAddToDictionary && index == 0) { if (mShowingAddToDictionary && index == 0) {
addToDictionary(word); addToDictionary(word);
} else { } else {
if (!mShowingCompletions) { if (!mSuggestions.mIsApplicationSpecifiedCompletions) {
TextEntryState.acceptedSuggestion(mSuggestions.get(0), word); TextEntryState.acceptedSuggestion(mSuggestions.getWord(0), word);
} }
mService.pickSuggestionManually(index, word); mService.pickSuggestionManually(index, word);
} }

View File

@ -77,7 +77,6 @@ import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Locale; import java.util.Locale;
/** /**
@ -162,7 +161,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Keep track of the last selection range to decide if we need to show word alternatives // Keep track of the last selection range to decide if we need to show word alternatives
private int mLastSelectionStart; private int mLastSelectionStart;
private int mLastSelectionEnd; private int mLastSelectionEnd;
private List<CharSequence> mSuggestPuncList; private SuggestedWords mSuggestPuncList;
// Input type is such that we should not auto-correct // Input type is such that we should not auto-correct
private boolean mInputTypeNoAutoCorrect; private boolean mInputTypeNoAutoCorrect;
@ -212,7 +211,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return mChosenWord; return mChosenWord;
} }
public abstract List<CharSequence> getAlternatives(); public abstract SuggestedWords.Builder getAlternatives();
} }
public class TypedWordAlternatives extends WordAlternatives { public class TypedWordAlternatives extends WordAlternatives {
@ -233,7 +232,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
@Override @Override
public List<CharSequence> getAlternatives() { public SuggestedWords.Builder getAlternatives() {
return getTypedSuggestions(word); return getTypedSuggestions(word);
} }
} }
@ -655,7 +654,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
super.onFinishInput(); super.onFinishInput();
LatinImeLogger.commit(); LatinImeLogger.commit();
onAutoCompletionStateChanged(false); mKeyboardSwitcher.onAutoCompletionStateChanged(false);
mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging); mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging);
@ -790,7 +789,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public void hideWindow() { public void hideWindow() {
LatinImeLogger.commit(); LatinImeLogger.commit();
onAutoCompletionStateChanged(false); mKeyboardSwitcher.onAutoCompletionStateChanged(false);
if (TRACE) Debug.stopMethodTracing(); if (TRACE) Debug.stopMethodTracing();
if (mOptionsDialog != null && mOptionsDialog.isShowing()) { if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
@ -818,13 +817,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return; return;
} }
List<CharSequence> stringList = new ArrayList<CharSequence>(); SuggestedWords.Builder builder = new SuggestedWords.Builder()
for (int i = 0; i < completions.length; i++) { .setApplicationSpecifiedCompletions(completions)
CompletionInfo ci = completions[i]; .setTypedWordValid(true)
if (ci != null) stringList.add(ci.getText()); .setHasMinimalSuggestion(true);
}
// When in fullscreen mode, show completions generated by the application // When in fullscreen mode, show completions generated by the application
setSuggestions(stringList, true, true, true); setSuggestions(builder.build());
mBestWord = null; mBestWord = null;
setCandidatesViewShown(true); setCandidatesViewShown(true);
} }
@ -1382,7 +1380,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
private boolean isShowingPunctuationList() { private boolean isShowingPunctuationList() {
return mSuggestPuncList.equals(mCandidateView.getSuggestions()); return mSuggestPuncList == mCandidateView.getSuggestions();
} }
private boolean isSuggestionShown() { private boolean isSuggestionShown() {
@ -1422,22 +1420,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
public void clearSuggestions() { public void clearSuggestions() {
setSuggestions(null, false, false, false); setSuggestions(SuggestedWords.EMPTY);
} }
public void setSuggestions( public void setSuggestions(SuggestedWords words) {
List<CharSequence> suggestions,
boolean completions,
boolean typedWordValid,
boolean haveMinimalSuggestion) {
if (mVoiceConnector.getAndResetIsShowingHint()) { if (mVoiceConnector.getAndResetIsShowingHint()) {
setCandidatesView(mCandidateViewContainer); setCandidatesView(mCandidateViewContainer);
} }
if (mCandidateView != null) { if (mCandidateView != null) {
mCandidateView.setSuggestions( mCandidateView.setSuggestions(words);
suggestions, completions, typedWordValid, haveMinimalSuggestion); if (mCandidateView.isConfigCandidateHighlightFontColorEnabled())
mKeyboardSwitcher.onAutoCompletionStateChanged(words.hasAutoCorrectionWord());
} }
} }
@ -1457,16 +1451,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
showSuggestions(mWord); showSuggestions(mWord);
} }
private List<CharSequence> getTypedSuggestions(WordComposer word) { private SuggestedWords.Builder getTypedSuggestions(WordComposer word) {
List<CharSequence> stringList = mSuggest.getSuggestions( return mSuggest.getSuggestedWordBuilder(
mKeyboardSwitcher.getInputView(), word, false, null); mKeyboardSwitcher.getInputView(), word, false, null);
return stringList;
} }
private void showCorrections(WordAlternatives alternatives) { private void showCorrections(WordAlternatives alternatives) {
mKeyboardSwitcher.setPreferredLetters(null); mKeyboardSwitcher.setPreferredLetters(null);
List<CharSequence> stringList = alternatives.getAlternatives(); SuggestedWords.Builder builder = alternatives.getAlternatives();
showSuggestions(stringList, alternatives.getOriginalWord(), false, false); builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
showSuggestions(builder.build(), alternatives.getOriginalWord());
} }
private void showSuggestions(WordComposer word) { private void showSuggestions(WordComposer word) {
@ -1474,7 +1468,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO Maybe need better way of retrieving previous word // TODO Maybe need better way of retrieving previous word
CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
mWordSeparators); mWordSeparators);
List<CharSequence> stringList = mSuggest.getSuggestions( SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
mKeyboardSwitcher.getInputView(), word, false, prevWord); mKeyboardSwitcher.getInputView(), word, false, prevWord);
// long stopTime = System.currentTimeMillis(); // TIME MEASUREMENT! // long stopTime = System.currentTimeMillis(); // TIME MEASUREMENT!
// Log.d("LatinIME","Suggest Total Time - " + (stopTime - startTime)); // Log.d("LatinIME","Suggest Total Time - " + (stopTime - startTime));
@ -1497,15 +1491,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
correctionAvailable &= !word.isMostlyCaps(); correctionAvailable &= !word.isMostlyCaps();
correctionAvailable &= !TextEntryState.isCorrecting(); correctionAvailable &= !TextEntryState.isCorrecting();
showSuggestions(stringList, typedWord, typedWordValid, correctionAvailable); builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(correctionAvailable);
showSuggestions(builder.build(), typedWord);
} }
private void showSuggestions(List<CharSequence> stringList, CharSequence typedWord, private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) {
boolean typedWordValid, boolean correctionAvailable) { setSuggestions(suggestedWords);
setSuggestions(stringList, false, typedWordValid, correctionAvailable); if (suggestedWords.size() > 0) {
if (stringList.size() > 0) { if (suggestedWords.mHasMinimalSuggestion
if (correctionAvailable && !typedWordValid && stringList.size() > 1) { && !suggestedWords.mTypedWordValid && suggestedWords.size() > 1) {
mBestWord = stringList.get(1); mBestWord = suggestedWords.getWord(1);
} else { } else {
mBestWord = typedWord; mBestWord = typedWord;
} }
@ -1534,7 +1529,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
public void pickSuggestionManually(int index, CharSequence suggestion) { public void pickSuggestionManually(int index, CharSequence suggestion) {
List<CharSequence> suggestions = mCandidateView.getSuggestions(); SuggestedWords suggestions = mCandidateView.getSuggestions();
mVoiceConnector.flushAndLogAllTextModificationCounters(index, suggestion, mWordSeparators); mVoiceConnector.flushAndLogAllTextModificationCounters(index, suggestion, mWordSeparators);
final boolean correcting = TextEntryState.isCorrecting(); final boolean correcting = TextEntryState.isCorrecting();
@ -1565,7 +1560,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Word separators are suggested before the user inputs something. // Word separators are suggested before the user inputs something.
// So, LatinImeLogger logs "" as a user's input. // So, LatinImeLogger logs "" as a user's input.
LatinImeLogger.logOnManualSuggestion( LatinImeLogger.logOnManualSuggestion(
"", suggestion.toString(), index, suggestions); "", suggestion.toString(), index, suggestions.mWords);
final char primaryCode = suggestion.charAt(0); final char primaryCode = suggestion.charAt(0);
onKey(primaryCode, new int[]{primaryCode}, KeyboardView.NOT_A_TOUCH_COORDINATE, onKey(primaryCode, new int[]{primaryCode}, KeyboardView.NOT_A_TOUCH_COORDINATE,
KeyboardView.NOT_A_TOUCH_COORDINATE); KeyboardView.NOT_A_TOUCH_COORDINATE);
@ -1583,7 +1578,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
addToBigramDictionary(suggestion, 1); addToBigramDictionary(suggestion, 1);
} }
LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(), LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(),
index, suggestions); index, suggestions.mWords);
TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion);
// Follow it with a space // Follow it with a space
if (mAutoSpace && !correcting) { if (mAutoSpace && !correcting) {
@ -1718,7 +1713,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void setPunctuationSuggestions() { private void setPunctuationSuggestions() {
setCandidatesViewShown(isCandidateStripVisible()); setCandidatesViewShown(isCandidateStripVisible());
setSuggestions(mSuggestPuncList, false, false, false); setSuggestions(mSuggestPuncList);
} }
private void addToDictionaries(CharSequence suggestion, int frequencyDelta) { private void addToDictionaries(CharSequence suggestion, int frequencyDelta) {
@ -2106,13 +2101,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
private void initSuggestPuncList() { private void initSuggestPuncList() {
mSuggestPuncList = new ArrayList<CharSequence>(); if (mSuggestPuncs != null || mSuggestPuncList != null)
mSuggestPuncs = mResources.getString(R.string.suggested_punctuations); return;
if (mSuggestPuncs != null) { SuggestedWords.Builder builder = new SuggestedWords.Builder();
for (int i = 0; i < mSuggestPuncs.length(); i++) { String puncs = mResources.getString(R.string.suggested_punctuations);
mSuggestPuncList.add(mSuggestPuncs.subSequence(i, i + 1)); if (puncs != null) {
for (int i = 0; i < puncs.length(); i++) {
builder.addWord(puncs.subSequence(i, i + 1));
} }
} }
mSuggestPuncList = builder.build();
mSuggestPuncs = puncs;
} }
private boolean isSuggestedPunctuation(int code) { private boolean isSuggestedPunctuation(int code) {
@ -2192,10 +2191,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total));
} }
public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
mKeyboardSwitcher.onAutoCompletionStateChanged(isAutoCompletion);
}
@Override @Override
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
SubtypeSwitcher.getInstance().updateSubtype(subtype); SubtypeSwitcher.getInstance().updateSubtype(subtype);

View File

@ -25,12 +25,10 @@ import android.view.View;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
/** /**
* This class loads a dictionary and provides a list of suggestions for a given sequence of * This class loads a dictionary and provides a list of suggestions for a given sequence of
* characters. This includes corrections and completions. * characters. This includes corrections and completions.
* @hide pending API Council Approval
*/ */
public class Suggest implements Dictionary.WordCallback { public class Suggest implements Dictionary.WordCallback {
@ -191,14 +189,21 @@ public class Suggest implements Dictionary.WordCallback {
} }
/** /**
* Returns a list of words that match the list of character codes passed in. * Returns a object which represents suggested words that match the list of character codes
* This list will be overwritten the next time this function is called. * passed in. This object contents will be overwritten the next time this function is called.
* @param view a view for retrieving the context for AutoText * @param view a view for retrieving the context for AutoText
* @param wordComposer contains what is currently being typed * @param wordComposer contains what is currently being typed
* @param prevWordForBigram previous word (used only for bigram) * @param prevWordForBigram previous word (used only for bigram)
* @return list of suggestions. * @return suggested words object.
*/ */
public List<CharSequence> getSuggestions(View view, WordComposer wordComposer, public SuggestedWords getSuggestions(View view, WordComposer wordComposer,
boolean includeTypedWordIfValid, CharSequence prevWordForBigram) {
return getSuggestedWordBuilder(view, wordComposer, includeTypedWordIfValid,
prevWordForBigram).build();
}
// TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer,
boolean includeTypedWordIfValid, CharSequence prevWordForBigram) { boolean includeTypedWordIfValid, CharSequence prevWordForBigram) {
LatinImeLogger.onStartSuggestion(prevWordForBigram); LatinImeLogger.onStartSuggestion(prevWordForBigram);
mHaveCorrection = false; mHaveCorrection = false;
@ -342,7 +347,7 @@ public class Suggest implements Dictionary.WordCallback {
} }
} }
removeDupes(); removeDupes();
return mSuggestions; return new SuggestedWords.Builder().setWords(mSuggestions);
} }
public int[] getNextLettersFrequencies() { public int[] getNextLettersFrequencies() {

View File

@ -0,0 +1,120 @@
/*
* Copyright (C) 2010 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 android.view.inputmethod.CompletionInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SuggestedWords {
public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, false, null);
public final List<CharSequence> mWords;
public final boolean mIsApplicationSpecifiedCompletions;
public final boolean mTypedWordValid;
public final boolean mHasMinimalSuggestion;
public final Object[] mDebugInfo;
private SuggestedWords(List<CharSequence> words, boolean isApplicationSpecifiedCompletions,
boolean typedWordValid, boolean hasMinamlSuggestion, Object[] debugInfo) {
if (words != null) {
mWords = words;
} else {
mWords = Collections.emptyList();
}
mIsApplicationSpecifiedCompletions = isApplicationSpecifiedCompletions;
mTypedWordValid = typedWordValid;
mHasMinimalSuggestion = hasMinamlSuggestion;
mDebugInfo = debugInfo;
}
public int size() {
return mWords.size();
}
public CharSequence getWord(int pos) {
return mWords.get(pos);
}
public boolean hasAutoCorrectionWord() {
return mHasMinimalSuggestion && ((size() >= 1 && !mTypedWordValid) || mTypedWordValid);
}
public static class Builder {
private List<CharSequence> mWords;
private boolean mIsCompletions;
private boolean mTypedWordVallid;
private boolean mHasMinimalSuggestion;
private Object[] mDebugInfo;
public Builder() {
// Nothing to do here.
}
public Builder setWords(List<CharSequence> words) {
mWords = words;
return this;
}
public Builder setDebugInfo(Object[] debuginfo) {
mDebugInfo = debuginfo;
return this;
}
public Builder addWord(int pos, CharSequence word) {
if (mWords == null)
mWords = new ArrayList<CharSequence>();
mWords.add(pos, word);
return this;
}
public Builder addWord(CharSequence word) {
if (mWords == null)
mWords = new ArrayList<CharSequence>();
mWords.add(word);
return this;
}
public Builder setApplicationSpecifiedCompletions(CompletionInfo[] infos) {
for (CompletionInfo info : infos)
addWord(info.getText());
mIsCompletions = true;
return this;
}
public Builder setTypedWordValid(boolean typedWordValid) {
mTypedWordVallid = typedWordValid;
return this;
}
public Builder setHasMinimalSuggestion(boolean hasMinamlSuggestion) {
mHasMinimalSuggestion = hasMinamlSuggestion;
return this;
}
public CharSequence getWord(int pos) {
return mWords.get(pos);
}
public SuggestedWords build() {
return new SuggestedWords(mWords, mIsCompletions, mTypedWordVallid,
mHasMinimalSuggestion, mDebugInfo);
}
}
}

View File

@ -22,6 +22,7 @@ import com.android.inputmethod.latin.LatinIME.UIHandler;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SharedPreferencesCompat; import com.android.inputmethod.latin.SharedPreferencesCompat;
import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.SuggestedWords;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
@ -424,17 +425,20 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
if (mWordToSuggestions.containsKey(selectedWord)) { if (mWordToSuggestions.containsKey(selectedWord)) {
mShowingVoiceSuggestions = true; mShowingVoiceSuggestions = true;
List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord); List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
SuggestedWords.Builder builder = new SuggestedWords.Builder();
// If the first letter of touching is capitalized, make all the suggestions // If the first letter of touching is capitalized, make all the suggestions
// start with a capital letter. // start with a capital letter.
if (Character.isUpperCase(touching.mWord.charAt(0))) { if (Character.isUpperCase(touching.mWord.charAt(0))) {
for (int i = 0; i < suggestions.size(); i++) { for (CharSequence word : suggestions) {
String origSugg = (String) suggestions.get(i); String str = word.toString();
String capsSugg = origSugg.toUpperCase().charAt(0) word = Character.toUpperCase(str.charAt(0)) + str.substring(1);
+ origSugg.subSequence(1, origSugg.length()).toString(); builder.addWord(word);
suggestions.set(i, capsSugg);
} }
} else {
builder.setWords(suggestions);
} }
mContext.setSuggestions(suggestions, false, true, true); builder.setTypedWordValid(true).setHasMinimalSuggestion(true);
mContext.setSuggestions(builder.build());
mContext.setCandidatesViewShown(true); mContext.setCandidatesViewShown(true);
return true; return true;
} }

View File

@ -116,30 +116,30 @@ public class SuggestHelper {
return word; return word;
} }
private boolean isDefaultSuggestion(List<CharSequence> suggestions, CharSequence word) { private boolean isDefaultSuggestion(SuggestedWords suggestions, CharSequence word) {
// Check if either the word is what you typed or the first alternative // Check if either the word is what you typed or the first alternative
return suggestions.size() > 0 && return suggestions.size() > 0 &&
(/*TextUtils.equals(suggestions.get(0), word) || */ (/*TextUtils.equals(suggestions.get(0), word) || */
(suggestions.size() > 1 && TextUtils.equals(suggestions.get(1), word))); (suggestions.size() > 1 && TextUtils.equals(suggestions.getWord(1), word)));
} }
boolean isDefaultSuggestion(CharSequence typed, CharSequence expected) { boolean isDefaultSuggestion(CharSequence typed, CharSequence expected) {
WordComposer word = createWordComposer(typed); WordComposer word = createWordComposer(typed);
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null); SuggestedWords suggestions = mSuggest.getSuggestions(null, word, false, null);
return isDefaultSuggestion(suggestions, expected); return isDefaultSuggestion(suggestions, expected);
} }
boolean isDefaultCorrection(CharSequence typed, CharSequence expected) { boolean isDefaultCorrection(CharSequence typed, CharSequence expected) {
WordComposer word = createWordComposer(typed); WordComposer word = createWordComposer(typed);
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null); SuggestedWords suggestions = mSuggest.getSuggestions(null, word, false, null);
return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection(); return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection();
} }
boolean isASuggestion(CharSequence typed, CharSequence expected) { boolean isASuggestion(CharSequence typed, CharSequence expected) {
WordComposer word = createWordComposer(typed); WordComposer word = createWordComposer(typed);
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, null); SuggestedWords suggestions = mSuggest.getSuggestions(null, word, false, null);
for (int i = 1; i < suggestions.size(); i++) { for (int i = 1; i < suggestions.size(); i++) {
if (TextUtils.equals(suggestions.get(i), expected)) return true; if (TextUtils.equals(suggestions.getWord(i), expected)) return true;
} }
return false; return false;
} }
@ -155,7 +155,7 @@ public class SuggestHelper {
CharSequence expected) { CharSequence expected) {
WordComposer word = createWordComposer(typed); WordComposer word = createWordComposer(typed);
getBigramSuggestions(previous, typed); getBigramSuggestions(previous, typed);
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous); SuggestedWords suggestions = mSuggest.getSuggestions(null, word, false, previous);
return isDefaultSuggestion(suggestions, expected); return isDefaultSuggestion(suggestions, expected);
} }
@ -163,7 +163,7 @@ public class SuggestHelper {
CharSequence expected) { CharSequence expected) {
WordComposer word = createWordComposer(typed); WordComposer word = createWordComposer(typed);
getBigramSuggestions(previous, typed); getBigramSuggestions(previous, typed);
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous); SuggestedWords suggestions = mSuggest.getSuggestions(null, word, false, previous);
return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection(); return isDefaultSuggestion(suggestions, expected) && mSuggest.hasMinimalCorrection();
} }
@ -171,9 +171,9 @@ public class SuggestHelper {
CharSequence expected) { CharSequence expected) {
WordComposer word = createWordComposer(typed); WordComposer word = createWordComposer(typed);
getBigramSuggestions(previous, typed); getBigramSuggestions(previous, typed);
List<CharSequence> suggestions = mSuggest.getSuggestions(null, word, false, previous); SuggestedWords suggestions = mSuggest.getSuggestions(null, word, false, previous);
for (int i = 1; i < suggestions.size(); i++) { for (int i = 1; i < suggestions.size(); i++) {
if (TextUtils.equals(suggestions.get(i), expected)) return true; if (TextUtils.equals(suggestions.getWord(i), expected)) return true;
} }
return false; return false;
} }