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

Commit f3d78eac authored by Gilles Debunne's avatar Gilles Debunne Committed by Android (Google) Code Review
Browse files

Merge "Added an add to dictionary option in suggestions for misspelled words"

parents 26b5cf40 e90bed18
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.util.AndroidException;
import android.util.Log;
import android.view.WindowOrientationListener;

import java.net.URISyntaxException;
import java.util.HashMap;
@@ -59,7 +60,7 @@ public final class Settings {
     * <p>
     * Input: Nothing.
     * <p>
     * Output: nothing.
     * Output: Nothing.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_SETTINGS = "android.settings.SETTINGS";
@@ -69,7 +70,7 @@ public final class Settings {
     * <p>
     * Input: Nothing.
     * <p>
     * Output: nothing.
     * Output: Nothing.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_APN_SETTINGS = "android.settings.APN_SETTINGS";
@@ -327,6 +328,23 @@ public final class Settings {
    public static final String ACTION_USER_DICTIONARY_SETTINGS =
            "android.settings.USER_DICTIONARY_SETTINGS";

    /**
     * Activity Action: Adds a word to the user dictionary.
     * <p>
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * <p>
     * Input: An extra with key <code>word</code> that contains the word
     * that should be added to the dictionary.
     * <p>
     * Output: Nothing.
     *
     * @hide
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_USER_DICTIONARY_INSERT =
            "com.android.settings.USER_DICTIONARY_INSERT";

    /**
     * Activity Action: Show settings to allow configuration of application-related settings.
     * <p>
@@ -1462,6 +1480,7 @@ public final class Settings {
         * @hide
         * @deprecated
         */
        @Deprecated
        public static final String NOTIFICATIONS_USE_RING_VOLUME =
            "notifications_use_ring_volume";

+53 −44
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.ClipData;
import android.content.ClipData.Item;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -42,6 +43,7 @@ import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.BoringLayout;
import android.text.DynamicLayout;
import android.text.Editable;
@@ -9425,7 +9427,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

    private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
        private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
        private static final int NO_SUGGESTIONS = -1;
        private static final float AVERAGE_HIGHLIGHTS_PER_SUGGESTION = 1.4f;
        private WordIterator mSuggestionWordIterator;
        private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan
@@ -9480,9 +9481,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            listView.setOnItemClickListener(this);
            mContentView = listView;

            // Inflate the suggestion items once and for all.
            mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS];
            for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
            // Inflate the suggestion items once and for all. +1 for add to dictionary
            mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 1];
            for (int i = 0; i < MAX_NUMBER_SUGGESTIONS + 1; i++) {
                mSuggestionInfos[i] = new SuggestionInfo();
            }
        }
@@ -9493,6 +9494,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            SuggestionSpan suggestionSpan; // the SuggestionSpan that this TextView represents
            int suggestionIndex; // the index of the suggestion inside suggestionSpan
            SpannableStringBuilder text = new SpannableStringBuilder();

            void removeMisspelledFlag() {
                int suggestionSpanFlags = suggestionSpan.getFlags();
                if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) {
                    suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED);
                    suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT);
                    suggestionSpan.setFlags(suggestionSpanFlags);
                }
            }
        }

        private class SuggestionAdapter extends BaseAdapter {
@@ -9631,6 +9641,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            int spanUnionStart = mText.length();
            int spanUnionEnd = 0;

            SuggestionSpan misspelledSpan = null;

            for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
                SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
                final int spanStart = spannable.getSpanStart(suggestionSpan);
@@ -9638,6 +9650,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                spanUnionStart = Math.min(spanStart, spanUnionStart);
                spanUnionEnd = Math.max(spanEnd, spanUnionEnd);

                if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
                    misspelledSpan = suggestionSpan;
                }

                String[] suggestions = suggestionSpan.getSuggestions();
                int nbSuggestions = suggestions.length;
                for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
@@ -9646,7 +9662,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    suggestionInfo.spanEnd = spanEnd;
                    suggestionInfo.suggestionSpan = suggestionSpan;
                    suggestionInfo.suggestionIndex = suggestionIndex;
                    suggestionInfo.text = new SpannableStringBuilder(suggestions[suggestionIndex]);
                    suggestionInfo.text.replace(0, suggestionInfo.text.length(),
                            suggestions[suggestionIndex]);

                    mNumberOfSuggestions++;
                    if (mNumberOfSuggestions == MAX_NUMBER_SUGGESTIONS) {
@@ -9657,41 +9674,38 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                }
            }

            for (int i = 0; i < mNumberOfSuggestions; i++) {
                highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd);
            }

            if (misspelledSpan != null) {
                final int misspelledStart = spannable.getSpanStart(misspelledSpan);
                final int misspelledEnd = spannable.getSpanEnd(misspelledSpan);
                if (misspelledStart >= 0 && misspelledEnd > misspelledStart) {
                    SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions];
                    suggestionInfo.spanStart = misspelledStart;
                    suggestionInfo.spanEnd = misspelledEnd;
                    suggestionInfo.suggestionSpan = misspelledSpan;
                    suggestionInfo.suggestionIndex = -1;
                    suggestionInfo.text.replace(0, suggestionInfo.text.length(),
                            getContext().getString(com.android.internal.R.string.addToDictionary));

                    mNumberOfSuggestions++;
                }
            }

            if (mNumberOfSuggestions == 0) return false;

            if (mSuggestionRangeSpan == null) mSuggestionRangeSpan =
                    new SuggestionRangeSpan(mHighlightColor);

            ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            for (int i = 0; i < mNumberOfSuggestions; i++) {
                highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd);
            }
            mSuggestionsAdapter.notifyDataSetChanged();

            return true;
        }

        private void onDictionarySuggestionsReceived(String[] suggestions) {
            if (suggestions.length == 0) {
                // TODO Actual implementation of this feature
                suggestions = new String[] {"Add to dictionary"};
            }

            WordIterator wordIterator = getWordIterator();
            wordIterator.setCharSequence(mText);

            final int pos = getSelectionStart();
            int wordStart = wordIterator.getBeginning(pos);
            int wordEnd = wordIterator.getEnd(pos);

            SuggestionSpan suggestionSpan = new SuggestionSpan(getContext(), suggestions, 0);
            ((Editable) mText).setSpan(suggestionSpan, wordStart, wordEnd,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            show();
        }

        private long[] getWordLimits(CharSequence text) {
            // TODO locale for mSuggestionWordIterator
            if (mSuggestionWordIterator == null) mSuggestionWordIterator = new WordIterator();
@@ -9844,10 +9858,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (view instanceof TextView) {
                TextView textView = (TextView) view;

                SuggestionInfo suggestionInfo = mSuggestionInfos[position];
                final int spanStart = suggestionInfo.spanStart;
                final int spanEnd = suggestionInfo.spanEnd;
                if (spanStart != NO_SUGGESTIONS) {
                final String originalText = mText.subSequence(spanStart, spanEnd).toString();

                if (suggestionInfo.suggestionIndex < 0) {
                    Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
                    intent.putExtra("word", originalText);
                    intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                    getContext().startActivity(intent);
                    suggestionInfo.removeMisspelledFlag();
                } else {
                    // SuggestionSpans are removed by replace: save them before
                    Editable editable = (Editable) mText;
                    SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
@@ -9867,17 +9890,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    final int suggestionEnd = suggestionInfo.suggestionEnd;
                    final String suggestion = textView.getText().subSequence(
                            suggestionStart, suggestionEnd).toString();
                    final String originalText = mText.subSequence(spanStart, spanEnd).toString();
                    editable.replace(spanStart, spanEnd, suggestion);

                    // A replacement on a misspelled text removes the misspelled flag.
                    // TODO restore the flag if the misspelled word is selected back?
                    int suggestionSpanFlags = suggestionInfo.suggestionSpan.getFlags();
                    if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) {
                        suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED);
                        suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT);
                        suggestionInfo.suggestionSpan.setFlags(suggestionSpanFlags);
                    }
                    suggestionInfo.removeMisspelledFlag();

                    // Notify source IME of the suggestion pick. Do this before swaping texts.
                    if (!TextUtils.isEmpty(
@@ -9924,12 +9939,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing();
    }

    void onDictionarySuggestionsReceived(String[] suggestions) {
        if (mSuggestionsPopupWindow != null) {
            mSuggestionsPopupWindow.onDictionarySuggestionsReceived(suggestions);
        }
    }

    /**
     * Return whether or not suggestions are enabled on this TextView. The suggestions are generated
     * by the IME or by the spell checker as the user types. This is done by adding
+3 −0
Original line number Diff line number Diff line
@@ -2484,6 +2484,9 @@
    <!-- Text selection contextual mode title, displayed in the CAB. [CHAR LIMIT=20] -->
    <string name="textSelectionCABTitle">Text selection</string>

    <!-- Option to add the current misspelled word to the user dictionary. [CHAR LIMIT=25] -->
    <string name="addToDictionary">+ add to dictionary</string>

    <!-- EditText context menu -->
    <string name="inputMethod">Input method</string>

+1 −1

File changed.

Contains only whitespace changes.