Search in sources :

Example 1 with TextRange

use of com.android.inputmethod.latin.utils.TextRange in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class RichInputConnectionAndTextRangeTests method testGetWordRangeAtCursor.

public void testGetWordRangeAtCursor() {
    /**
         * Test logic in getting the word range at the cursor.
         */
    final SpacingAndPunctuations SPACE = new SpacingAndPunctuations(mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
    final SpacingAndPunctuations TAB = new SpacingAndPunctuations(mSpacingAndPunctuations, new int[] { Constants.CODE_TAB });
    // A character that needs surrogate pair to represent its code point (U+2008A).
    final String SUPPLEMENTARY_CHAR_STRING = "𠂊";
    final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(mSpacingAndPunctuations, StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR_STRING));
    // あいうえお
    final String HIRAGANA_WORD = "あいうえお";
    // και
    final String GREEK_WORD = "και";
    ExtractedText et = new ExtractedText();
    final MockInputMethodService mockInputMethodService = new MockInputMethodService();
    final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
    mockInputMethodService.setInputConnection(new MockConnection("word wo", "rd", et));
    et.startOffset = 0;
    et.selectionStart = 7;
    TextRange r;
    ic.beginBatchEdit();
    // basic case
    r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN);
    assertTrue(TextUtils.equals("word", r.mWord));
    // tab character instead of space
    mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et));
    ic.beginBatchEdit();
    r = ic.getWordRangeAtCursor(TAB, ScriptUtils.SCRIPT_LATIN);
    ic.endBatchEdit();
    assertTrue(TextUtils.equals("word", r.mWord));
    // splitting on supplementary character
    mockInputMethodService.setInputConnection(new MockConnection("one word" + SUPPLEMENTARY_CHAR_STRING + "wo", "rd", et));
    ic.beginBatchEdit();
    r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_LATIN);
    ic.endBatchEdit();
    assertTrue(TextUtils.equals("word", r.mWord));
    // split on chars outside the specified script
    mockInputMethodService.setInputConnection(new MockConnection(HIRAGANA_WORD + "wo", "rd" + GREEK_WORD, et));
    ic.beginBatchEdit();
    r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_LATIN);
    ic.endBatchEdit();
    assertTrue(TextUtils.equals("word", r.mWord));
    // likewise for greek
    mockInputMethodService.setInputConnection(new MockConnection("text" + GREEK_WORD, "text", et));
    ic.beginBatchEdit();
    r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_GREEK);
    ic.endBatchEdit();
    assertTrue(TextUtils.equals(GREEK_WORD, r.mWord));
}
Also used : SpacingAndPunctuations(com.android.inputmethod.latin.settings.SpacingAndPunctuations) TextRange(com.android.inputmethod.latin.utils.TextRange) SpannableString(android.text.SpannableString) ExtractedText(android.view.inputmethod.ExtractedText)

Example 2 with TextRange

use of com.android.inputmethod.latin.utils.TextRange in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class RichInputConnectionAndTextRangeTests method helpTestGetSuggestionSpansAtWord.

private void helpTestGetSuggestionSpansAtWord(final int cursorPos) {
    final SpacingAndPunctuations SPACE = new SpacingAndPunctuations(mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
    final MockInputMethodService mockInputMethodService = new MockInputMethodService();
    final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
    final String[] SUGGESTIONS1 = { "swing", "strong" };
    final String[] SUGGESTIONS2 = { "storing", "strung" };
    // Test the usual case.
    SpannableString text = new SpannableString("This is a string for test");
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0), 10, /* start */
    16, /* end */
    0);
    mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
    TextRange r;
    SuggestionSpan[] suggestions;
    r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN);
    suggestions = r.getSuggestionSpansAtWord();
    assertEquals(suggestions.length, 1);
    MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
    // Test the case with 2 suggestion spans in the same place.
    text = new SpannableString("This is a string for test");
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0), 10, /* start */
    16, /* end */
    0);
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0), 10, /* start */
    16, /* end */
    0);
    mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
    r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN);
    suggestions = r.getSuggestionSpansAtWord();
    assertEquals(suggestions.length, 2);
    MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
    MoreAsserts.assertEquals(suggestions[1].getSuggestions(), SUGGESTIONS2);
    // Test a case with overlapping spans, 2nd extending past the start of the word
    text = new SpannableString("This is a string for test");
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0), 10, /* start */
    16, /* end */
    0);
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0), 5, /* start */
    16, /* end */
    0);
    mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
    r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN);
    suggestions = r.getSuggestionSpansAtWord();
    assertEquals(suggestions.length, 1);
    MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
    // Test a case with overlapping spans, 2nd extending past the end of the word
    text = new SpannableString("This is a string for test");
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0), 10, /* start */
    16, /* end */
    0);
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0), 10, /* start */
    20, /* end */
    0);
    mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
    r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN);
    suggestions = r.getSuggestionSpansAtWord();
    assertEquals(suggestions.length, 1);
    MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
    // Test a case with overlapping spans, 2nd extending past both ends of the word
    text = new SpannableString("This is a string for test");
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0), 10, /* start */
    16, /* end */
    0);
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0), 5, /* start */
    20, /* end */
    0);
    mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
    r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN);
    suggestions = r.getSuggestionSpansAtWord();
    assertEquals(suggestions.length, 1);
    MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
    // Test a case with overlapping spans, none right on the word
    text = new SpannableString("This is a string for test");
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0), 5, /* start */
    16, /* end */
    0);
    text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0), 5, /* start */
    20, /* end */
    0);
    mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
    r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN);
    suggestions = r.getSuggestionSpansAtWord();
    assertEquals(suggestions.length, 0);
}
Also used : SpannableString(android.text.SpannableString) SpacingAndPunctuations(com.android.inputmethod.latin.settings.SpacingAndPunctuations) TextRange(com.android.inputmethod.latin.utils.TextRange) SpannableString(android.text.SpannableString) SuggestionSpan(android.text.style.SuggestionSpan)

Example 3 with TextRange

use of com.android.inputmethod.latin.utils.TextRange in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class InputLogic method restartSuggestionsOnWordTouchedByCursor.

/**
     * Check if the cursor is touching a word. If so, restart suggestions on this word, else
     * do nothing.
     *
     * @param settingsValues the current values of the settings.
     * @param forStartInput whether we're doing this in answer to starting the input (as opposed
     *   to a cursor move, for example). In ICS, there is a platform bug that we need to work
     *   around only when we come here at input start time.
     */
public void restartSuggestionsOnWordTouchedByCursor(final SettingsValues settingsValues, final boolean forStartInput, // TODO: remove this argument, put it into settingsValues
final int currentKeyboardScriptId) {
    // TODO: remove this.
    if (settingsValues.isBrokenByRecorrection() || // how to segment them yet.
    !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces || // If no suggestions are requested, don't try restarting suggestions.
    !settingsValues.needsToLookupSuggestions() || // that the app moves the cursor on its own accord during a batch input.
    mInputLogicHandler.isInBatchInput() || // If the cursor is not touching a word, or if there is a selection, return right away.
    mConnection.hasSelection() || // If we don't know the cursor location, return.
    mConnection.getExpectedSelectionStart() < 0) {
        mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
        return;
    }
    final int expectedCursorPosition = mConnection.getExpectedSelectionStart();
    if (!mConnection.isCursorTouchingWord(settingsValues.mSpacingAndPunctuations, true)) {
        // Show predictions.
        mWordComposer.setCapitalizedModeAtStartComposingTime(WordComposer.CAPS_MODE_OFF);
        mLatinIME.mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_RECORRECTION);
        return;
    }
    final TextRange range = mConnection.getWordRangeAtCursor(settingsValues.mSpacingAndPunctuations, currentKeyboardScriptId);
    // Happens if we don't have an input connection at all
    if (null == range)
        return;
    if (range.length() <= 0) {
        // Race condition, or touching a word in a non-supported script.
        mLatinIME.setNeutralSuggestionStrip();
        return;
    }
    // If there are links, we don't resume suggestions. Making
    if (range.mHasUrlSpans)
        return;
    // edits to a linkified text through batch commands would ruin the URL spans, and unless
    // we take very complicated steps to preserve the whole link, we can't do things right so
    // we just do not resume because it's safer.
    final int numberOfCharsInWordBeforeCursor = range.getNumberOfCharsInWordBeforeCursor();
    if (numberOfCharsInWordBeforeCursor > expectedCursorPosition)
        return;
    final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
    final String typedWordString = range.mWord.toString();
    final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(typedWordString, "", /* prevWordsContext */
    SuggestedWords.MAX_SUGGESTIONS + 1, SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED, SuggestedWordInfo.NOT_AN_INDEX, /* indexOfTouchPointOfSecondWord */
    SuggestedWordInfo.NOT_A_CONFIDENCE);
    suggestions.add(typedWordInfo);
    if (!isResumableWord(settingsValues, typedWordString)) {
        mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
        return;
    }
    int i = 0;
    for (final SuggestionSpan span : range.getSuggestionSpansAtWord()) {
        for (final String s : span.getSuggestions()) {
            ++i;
            if (!TextUtils.equals(s, typedWordString)) {
                suggestions.add(new SuggestedWordInfo(s, "", /* prevWordsContext */
                SuggestedWords.MAX_SUGGESTIONS - i, SuggestedWordInfo.KIND_RESUMED, Dictionary.DICTIONARY_RESUMED, SuggestedWordInfo.NOT_AN_INDEX, /* indexOfTouchPointOfSecondWord */
                SuggestedWordInfo.NOT_A_CONFIDENCE));
            }
        }
    }
    final int[] codePoints = StringUtils.toCodePointArray(typedWordString);
    mWordComposer.setComposingWord(codePoints, mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
    mWordComposer.setCursorPositionWithinWord(typedWordString.codePointCount(0, numberOfCharsInWordBeforeCursor));
    if (forStartInput) {
        mConnection.maybeMoveTheCursorAroundAndRestoreToWorkaroundABug();
    }
    mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor, expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor());
    if (suggestions.size() <= 1) {
        // If there weren't any suggestion spans on this word, suggestions#size() will be 1
        // if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
        // have no useful suggestions, so we will try to compute some for it instead.
        mInputLogicHandler.getSuggestedWords(Suggest.SESSION_ID_TYPING, SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {

            @Override
            public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
                doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
            }
        });
    } else {
        // We found suggestion spans in the word. We'll create the SuggestedWords out of
        // them, and make willAutoCorrect false. We make typedWordValid false, because the
        // color of the word in the suggestion strip changes according to this parameter,
        // and false gives the correct color.
        final SuggestedWords suggestedWords = new SuggestedWords(suggestions, null, /* rawSuggestions */
        typedWordInfo, false, /* typedWordValid */
        false, /* willAutoCorrect */
        false, /* isObsoleteSuggestions */
        SuggestedWords.INPUT_STYLE_RECORRECTION, SuggestedWords.NOT_A_SEQUENCE_NUMBER);
        doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
    }
}
Also used : OnGetSuggestedWordsCallback(com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback) SuggestedWordInfo(com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo) ArrayList(java.util.ArrayList) SuggestedWords(com.android.inputmethod.latin.SuggestedWords) TextRange(com.android.inputmethod.latin.utils.TextRange) SpannableString(android.text.SpannableString) SuggestionSpan(android.text.style.SuggestionSpan)

Aggregations

SpannableString (android.text.SpannableString)3 TextRange (com.android.inputmethod.latin.utils.TextRange)3 SuggestionSpan (android.text.style.SuggestionSpan)2 SpacingAndPunctuations (com.android.inputmethod.latin.settings.SpacingAndPunctuations)2 ExtractedText (android.view.inputmethod.ExtractedText)1 OnGetSuggestedWordsCallback (com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback)1 SuggestedWords (com.android.inputmethod.latin.SuggestedWords)1 SuggestedWordInfo (com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo)1 ArrayList (java.util.ArrayList)1