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

Commit e90bed18 authored by Gilles Debunne's avatar Gilles Debunne
Browse files

Added an add to dictionary option in suggestions for misspelled words

Change-Id: I031f17a76b4a81ae375b778046b8c391f9b8b2b2
parent 7de6578f
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;
@@ -9417,7 +9419,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
@@ -9472,9 +9473,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();
            }
        }
@@ -9485,6 +9486,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 {
@@ -9623,6 +9633,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);
@@ -9630,6 +9642,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++) {
@@ -9638,7 +9654,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) {
@@ -9649,41 +9666,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();
@@ -9836,10 +9850,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,
@@ -9859,17 +9882,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(
@@ -9916,12 +9931,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.