Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fbfd587 authored by satok's avatar satok
Browse files

Move re-correction codes to Recorrection.java

Change-Id: I0641f333bbc7d4ac27361c97252c4591584efb9d
parent 5c051dfe
Loading
Loading
Loading
Loading
+12 −159
Original line number Diff line number Diff line
@@ -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())
+126 −1
Original line number Diff line number Diff line
@@ -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();
        }
    }
}
+59 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}
 No newline at end of file
+8 −4
Original line number Diff line number Diff line
@@ -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);