Move re-correction codes to Recorrection.java

Change-Id: I0641f333bbc7d4ac27361c97252c4591584efb9d
This commit is contained in:
satok 2011-05-10 16:40:28 +09:00
parent 5c051dfefb
commit 9fbfd58773
4 changed files with 205 additions and 164 deletions

View file

@ -73,7 +73,6 @@ import android.widget.LinearLayout;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
@ -228,39 +227,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Keeps track of most recently inserted text (multi-character key) for reverting
private CharSequence mEnteredText;
private final ArrayList<WordAlternatives> mWordHistory = new ArrayList<WordAlternatives>();
public class WordAlternatives {
private final CharSequence mChosenWord;
private final WordComposer mWordComposer;
public WordAlternatives(CharSequence chosenWord, WordComposer wordComposer) {
mChosenWord = chosenWord;
mWordComposer = wordComposer;
}
public CharSequence getChosenWord() {
return mChosenWord;
}
public CharSequence getOriginalWord() {
return mWordComposer.getTypedWord();
}
public SuggestedWords.Builder getAlternatives() {
return getTypedSuggestions(mWordComposer);
}
@Override
public int hashCode() {
return mChosenWord.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof CharSequence && TextUtils.equals(mChosenWord, (CharSequence)o);
}
}
public final UIHandler mHandler = new UIHandler();
@ -283,7 +249,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
updateSuggestions();
break;
case MSG_UPDATE_OLD_SUGGESTIONS:
setOldSuggestions();
mRecorrection.setRecorrectionSuggestions(mVoiceProxy, mCandidateView, mSuggest,
mKeyboardSwitcher, mWord, mHasUncommittedTypedChars, mLastSelectionStart,
mLastSelectionEnd, mWordSeparators);
break;
case MSG_UPDATE_SHIFT_STATE:
switcher.updateShiftState();
@ -749,7 +717,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// If the composing span has been cleared, save the typed word in the history for
// recorrection before we reset the candidate strip. Then, we'll be able to show
// suggestions for recorrection right away.
saveWordInHistory(mComposing);
mRecorrection.saveWordInHistory(mWord, mComposing);
}
mComposing.setLength(0);
mHasUncommittedTypedChars = false;
@ -832,7 +800,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mOptionsDialog = null;
}
mVoiceProxy.hideVoiceWindow(mConfigurationChanging);
mWordHistory.clear();
mRecorrection.clearWordsInHistory();
super.hideWindow();
}
@ -1164,7 +1132,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mVoiceProxy.commitVoiceInput();
InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
abortRecorrection(false);
mRecorrection.abortRecorrection(false);
ic.beginBatchEdit();
commitTyped(ic);
maybeRemovePreviousPeriod(text);
@ -1270,15 +1238,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
public void abortRecorrection(boolean force) {
if (force || TextEntryState.isRecorrecting()) {
TextEntryState.onAbortRecorrection();
setCandidatesViewShown(isCandidateStripVisible());
getCurrentInputConnection().finishComposingText();
clearSuggestions();
}
}
private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) {
mVoiceProxy.handleCharacter();
@ -1287,7 +1246,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
if (mLastSelectionStart == mLastSelectionEnd) {
abortRecorrection(false);
mRecorrection.abortRecorrection(false);
}
int code = primaryCode;
@ -1295,7 +1254,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (!mHasUncommittedTypedChars) {
mHasUncommittedTypedChars = true;
mComposing.setLength(0);
saveWordInHistory(mBestWord);
mRecorrection.saveWordInHistory(mWord, mBestWord);
mWord.reset();
clearSuggestions();
}
@ -1363,7 +1322,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.beginBatchEdit();
abortRecorrection(false);
mRecorrection.abortRecorrection(false);
}
if (mHasUncommittedTypedChars) {
// In certain languages where single quote is a separator, it's better
@ -1432,22 +1391,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
inputView.closing();
}
private void saveWordInHistory(CharSequence result) {
if (mWord.size() <= 1) {
return;
}
// Skip if result is null. It happens in some edge case.
if (TextUtils.isEmpty(result)) {
return;
}
// Make a copy of the CharSequence, since it is/could be a mutable CharSequence
final String resultCopy = result.toString();
WordAlternatives entry = new WordAlternatives(resultCopy,
new WordComposer(mWord));
mWordHistory.add(entry);
}
public boolean isSuggestionsRequested() {
return mIsSettingsSuggestionStripOn
&& (mCorrectionMode > 0 || isShowingSuggestionsStrip());
@ -1463,7 +1406,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
&& mOrientation == Configuration.ORIENTATION_PORTRAIT);
}
private boolean isCandidateStripVisible() {
public boolean isCandidateStripVisible() {
if (mCandidateView == null)
return false;
if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting())
@ -1525,16 +1468,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
showSuggestions(mWord);
}
private SuggestedWords.Builder getTypedSuggestions(WordComposer word) {
return mSuggest.getSuggestedWordBuilder(mKeyboardSwitcher.getInputView(), word, null);
}
private void showCorrections(WordAlternatives alternatives) {
SuggestedWords.Builder builder = alternatives.getAlternatives();
builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
showSuggestions(builder.build(), alternatives.getOriginalWord());
}
private void showSuggestions(WordComposer word) {
// TODO: May need a better way of retrieving previous word
CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
@ -1573,7 +1506,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
showSuggestions(builder.build(), typedWord);
}
private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) {
public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) {
setSuggestions(suggestedWords);
if (suggestedWords.size() > 0) {
if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords, mSuggest)) {
@ -1728,91 +1661,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mVoiceProxy.rememberReplacedWord(suggestion, mWordSeparators);
ic.commitText(suggestion, 1);
}
saveWordInHistory(suggestion);
mRecorrection.saveWordInHistory(mWord, suggestion);
mHasUncommittedTypedChars = false;
mCommittedLength = suggestion.length();
}
/**
* Tries to apply any typed alternatives for the word if we have any cached alternatives,
* otherwise tries to find new corrections and completions for the word.
* @param touching The word that the cursor is touching, with position information
* @return true if an alternative was found, false otherwise.
*/
private boolean applyTypedAlternatives(EditingUtils.SelectedWord touching) {
// If we didn't find a match, search for result in typed word history
WordComposer foundWord = null;
WordAlternatives alternatives = null;
// Search old suggestions to suggest re-corrected suggestions.
for (WordAlternatives entry : mWordHistory) {
if (TextUtils.equals(entry.getChosenWord(), touching.mWord)) {
foundWord = entry.mWordComposer;
alternatives = entry;
break;
}
}
// If we didn't find a match, at least suggest corrections as re-corrected suggestions.
if (foundWord == null
&& (AutoCorrection.isValidWord(
mSuggest.getUnigramDictionaries(), touching.mWord, true))) {
foundWord = new WordComposer();
for (int i = 0; i < touching.mWord.length(); i++) {
foundWord.add(touching.mWord.charAt(i), new int[] {
touching.mWord.charAt(i)
}, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
}
foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.mWord.charAt(0)));
}
// Found a match, show suggestions
if (foundWord != null || alternatives != null) {
if (alternatives == null) {
alternatives = new WordAlternatives(touching.mWord, foundWord);
}
showCorrections(alternatives);
if (foundWord != null) {
mWord = new WordComposer(foundWord);
} else {
mWord.reset();
}
return true;
}
return false;
}
private void setOldSuggestions() {
if (!InputConnectionCompatUtils.RECORRECTION_SUPPORTED) return;
mVoiceProxy.setShowingVoiceSuggestions(false);
if (mCandidateView != null && mCandidateView.isShowingAddToDictionaryHint()) {
return;
}
InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
if (!mHasUncommittedTypedChars) {
// Extract the selected or touching text
EditingUtils.SelectedWord touching = EditingUtils.getWordAtCursorOrSelection(ic,
mLastSelectionStart, mLastSelectionEnd, mWordSeparators);
if (touching != null && touching.mWord.length() > 1) {
ic.beginBatchEdit();
if (!mVoiceProxy.applyVoiceAlternatives(touching)
&& !applyTypedAlternatives(touching)) {
abortRecorrection(true);
} else {
TextEntryState.selectedForRecorrection();
InputConnectionCompatUtils.underlineWord(ic, touching);
}
ic.endBatchEdit();
} else {
abortRecorrection(true);
setPunctuationSuggestions(); // Show the punctuation suggestions list
}
} else {
abortRecorrection(true);
}
}
private static final WordComposer sEmptyWordComposer = new WordComposer();
private void updateBigramPredictions() {
if (mSuggest == null || !isSuggestionsRequested())

View file

@ -16,6 +16,8 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.compat.InputConnectionCompatUtils;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import android.content.SharedPreferences;
@ -25,6 +27,8 @@ import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import java.util.ArrayList;
/**
* Manager of re-correction functionalities
*/
@ -33,6 +37,7 @@ public class Recorrection {
private LatinIME mService;
private boolean mRecorrectionEnabled = false;
private final ArrayList<WordAlternatives> mWordHistory = new ArrayList<WordAlternatives>();
public static Recorrection getInstance() {
return sInstance;
@ -108,7 +113,7 @@ public class Recorrection {
mService.mHandler.cancelUpdateBigramPredictions();
mService.mHandler.postUpdateOldSuggestions();
} else {
mService.abortRecorrection(false);
abortRecorrection(false);
// If showing the "touch again to save" hint, do not replace it. Else,
// show the bigrams if we are at the end of the text, punctuation otherwise.
if (candidateView != null
@ -127,4 +132,124 @@ public class Recorrection {
}
}
}
public void saveWordInHistory(WordComposer word, CharSequence result) {
if (word.size() <= 1) {
return;
}
// Skip if result is null. It happens in some edge case.
if (TextUtils.isEmpty(result)) {
return;
}
// Make a copy of the CharSequence, since it is/could be a mutable CharSequence
final String resultCopy = result.toString();
WordAlternatives entry = new WordAlternatives(resultCopy, new WordComposer(word));
mWordHistory.add(entry);
}
public void clearWordsInHistory() {
mWordHistory.clear();
}
/**
* Tries to apply any typed alternatives for the word if we have any cached alternatives,
* otherwise tries to find new corrections and completions for the word.
* @param touching The word that the cursor is touching, with position information
* @return true if an alternative was found, false otherwise.
*/
public boolean applyTypedAlternatives(WordComposer word, Suggest suggest,
KeyboardSwitcher keyboardSwitcher, EditingUtils.SelectedWord touching) {
// If we didn't find a match, search for result in typed word history
WordComposer foundWord = null;
WordAlternatives alternatives = null;
// Search old suggestions to suggest re-corrected suggestions.
for (WordAlternatives entry : mWordHistory) {
if (TextUtils.equals(entry.getChosenWord(), touching.mWord)) {
foundWord = entry.mWordComposer;
alternatives = entry;
break;
}
}
// If we didn't find a match, at least suggest corrections as re-corrected suggestions.
if (foundWord == null
&& (AutoCorrection.isValidWord(suggest.getUnigramDictionaries(),
touching.mWord, true))) {
foundWord = new WordComposer();
for (int i = 0; i < touching.mWord.length(); i++) {
foundWord.add(touching.mWord.charAt(i),
new int[] { touching.mWord.charAt(i) }, WordComposer.NOT_A_COORDINATE,
WordComposer.NOT_A_COORDINATE);
}
foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.mWord.charAt(0)));
}
// Found a match, show suggestions
if (foundWord != null || alternatives != null) {
if (alternatives == null) {
alternatives = new WordAlternatives(touching.mWord, foundWord);
}
showRecorrections(suggest, keyboardSwitcher, alternatives);
if (foundWord != null) {
word.init(foundWord);
} else {
word.reset();
}
return true;
}
return false;
}
private void showRecorrections(Suggest suggest, KeyboardSwitcher keyboardSwitcher,
WordAlternatives alternatives) {
SuggestedWords.Builder builder = alternatives.getAlternatives(suggest, keyboardSwitcher);
builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
mService.showSuggestions(builder.build(), alternatives.getOriginalWord());
}
public void setRecorrectionSuggestions(VoiceProxy voiceProxy, CandidateView candidateView,
Suggest suggest, KeyboardSwitcher keyboardSwitcher, WordComposer word,
boolean hasUncommittedTypedChars, int lastSelectionStart, int lastSelectionEnd,
String wordSeparators) {
if (!InputConnectionCompatUtils.RECORRECTION_SUPPORTED) return;
voiceProxy.setShowingVoiceSuggestions(false);
if (candidateView != null && candidateView.isShowingAddToDictionaryHint()) {
return;
}
InputConnection ic = mService.getCurrentInputConnection();
if (ic == null) return;
if (!hasUncommittedTypedChars) {
// Extract the selected or touching text
EditingUtils.SelectedWord touching = EditingUtils.getWordAtCursorOrSelection(ic,
lastSelectionStart, lastSelectionEnd, wordSeparators);
if (touching != null && touching.mWord.length() > 1) {
ic.beginBatchEdit();
if (applyTypedAlternatives(word, suggest, keyboardSwitcher, touching)
|| voiceProxy.applyVoiceAlternatives(touching)) {
TextEntryState.selectedForRecorrection();
InputConnectionCompatUtils.underlineWord(ic, touching);
} else {
abortRecorrection(true);
}
ic.endBatchEdit();
} else {
abortRecorrection(true);
mService.setPunctuationSuggestions(); // Show the punctuation suggestions list
}
} else {
abortRecorrection(true);
}
}
public void abortRecorrection(boolean force) {
if (force || TextEntryState.isRecorrecting()) {
TextEntryState.onAbortRecorrection();
mService.setCandidatesViewShown(mService.isCandidateStripVisible());
mService.getCurrentInputConnection().finishComposingText();
mService.clearSuggestions();
}
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2011 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.keyboard.KeyboardSwitcher;
import android.text.TextUtils;
public class WordAlternatives {
public final CharSequence mChosenWord;
public final WordComposer mWordComposer;
public WordAlternatives(CharSequence chosenWord, WordComposer wordComposer) {
mChosenWord = chosenWord;
mWordComposer = wordComposer;
}
public CharSequence getChosenWord() {
return mChosenWord;
}
public CharSequence getOriginalWord() {
return mWordComposer.getTypedWord();
}
public SuggestedWords.Builder getAlternatives(
Suggest suggest, KeyboardSwitcher keyboardSwitcher) {
return getTypedSuggestions(suggest, keyboardSwitcher, mWordComposer);
}
@Override
public int hashCode() {
return mChosenWord.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof CharSequence && TextUtils.equals(mChosenWord, (CharSequence)o);
}
private static SuggestedWords.Builder getTypedSuggestions(
Suggest suggest, KeyboardSwitcher keyboardSwitcher, WordComposer word) {
return suggest.getSuggestedWordBuilder(keyboardSwitcher.getInputView(), word, null);
}
}

View file

@ -31,18 +31,18 @@ public class WordComposer {
/**
* The list of unicode values for each keystroke (including surrounding keys)
*/
private final ArrayList<int[]> mCodes;
private ArrayList<int[]> mCodes;
private int mTypedLength;
private final int[] mXCoordinates;
private final int[] mYCoordinates;
private int[] mXCoordinates;
private int[] mYCoordinates;
/**
* The word chosen from the candidate list, until it is committed.
*/
private String mPreferredWord;
private final StringBuilder mTypedWord;
private StringBuilder mTypedWord;
private int mCapsCount;
@ -63,6 +63,10 @@ public class WordComposer {
}
WordComposer(WordComposer source) {
init(source);
}
public void init(WordComposer source) {
mCodes = new ArrayList<int[]>(source.mCodes);
mPreferredWord = source.mPreferredWord;
mTypedWord = new StringBuilder(source.mTypedWord);