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

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

Merge "Suggestions popup window is dismissed on tap outside."

parents 082a9fa3 28294cc7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1610,6 +1610,7 @@ package android {
    field public static final int TextAppearance_StatusBar_EventContent_Title = 16973928; // 0x1030068
    field public static final int TextAppearance_StatusBar_Icon = 16973926; // 0x1030066
    field public static final int TextAppearance_StatusBar_Title = 16973925; // 0x1030065
    field public static final int TextAppearance_SuggestionHighlight = 16974104; // 0x1030118
    field public static final int TextAppearance_Theme = 16973888; // 0x1030040
    field public static final int TextAppearance_Theme_Dialog = 16973896; // 0x1030048
    field public static final int TextAppearance_Widget = 16973897; // 0x1030049
+14 −0
Original line number Diff line number Diff line
@@ -31,9 +31,11 @@ import android.text.style.QuoteSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.ReplacementSpan;
import android.text.style.ScaleXSpan;
import android.text.style.SpellCheckSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuggestionRangeSpan;
import android.text.style.SuggestionSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TextAppearanceSpan;
@@ -579,6 +581,10 @@ public class TextUtils {
    public static final int ANNOTATION = 18;
    /** @hide */
    public static final int SUGGESTION_SPAN = 19;
    /** @hide */
    public static final int SPELL_CHECK_SPAN = 20;
    /** @hide */
    public static final int SUGGESTION_RANGE_SPAN = 21;

    /**
     * Flatten a CharSequence and whatever styles can be copied across processes
@@ -734,6 +740,14 @@ public class TextUtils {
                    readSpan(p, sp, new SuggestionSpan(p));
                    break;

                case SPELL_CHECK_SPAN:
                    readSpan(p, sp, new SpellCheckSpan(p));
                    break;

                case SUGGESTION_RANGE_SPAN:
                    readSpan(p, sp, new SuggestionRangeSpan());
                    break;
                    
                default:
                    throw new RuntimeException("bogus span encoding " + kind);
                }
+24 −1
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package android.text.style;

import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;

/**
 * A SpellCheckSpan is an internal data structure created by the TextView's SpellChecker to
 * annotate portions of the text that are about to or currently being spell checked. They are
@@ -23,7 +27,7 @@ package android.text.style;
 *
 * @hide
 */
public class SpellCheckSpan {
public class SpellCheckSpan implements ParcelableSpan {

    private boolean mSpellCheckInProgress;

@@ -31,6 +35,10 @@ public class SpellCheckSpan {
        mSpellCheckInProgress = false;
    }

    public SpellCheckSpan(Parcel src) {
        mSpellCheckInProgress = (src.readInt() != 0);
    }

    public void setSpellCheckInProgress() {
        mSpellCheckInProgress = true;
    }
@@ -38,4 +46,19 @@ public class SpellCheckSpan {
    public boolean isSpellCheckInProgress() {
        return mSpellCheckInProgress;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mSpellCheckInProgress ? 1 : 0);
    }

    @Override
    public int getSpanTypeId() {
        return TextUtils.SPELL_CHECK_SPAN;
    }
}
+51 −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 android.text.style;

import android.graphics.Color;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.TextUtils;

/**
 * A SuggestionRangeSpan is used to show which part of an EditText is affected by a suggestion
 * popup window.
 *
 * @hide
 */
public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpan {
    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setColor(Color.GREEN);            
    }

    public SuggestionRangeSpan() { /* Nothing to do*/ }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) { /* Nothing to do*/ }

    @Override
    public int getSpanTypeId() {
        return TextUtils.SUGGESTION_RANGE_SPAN;
    }
}
+37 −35
Original line number Diff line number Diff line
@@ -84,10 +84,10 @@ import android.text.method.WordIterator;
import android.text.style.ClickableSpan;
import android.text.style.ParagraphStyle;
import android.text.style.SpellCheckSpan;
import android.text.style.SuggestionRangeSpan;
import android.text.style.SuggestionSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.text.style.UpdateAppearance;
import android.text.util.Linkify;
import android.util.AttributeSet;
@@ -2894,7 +2894,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    sp.removeSpan(cw);
                }

                // hideControllers would do it, but it gets called after this method on rotation
                sp.removeSpan(mSuggestionRangeSpan);

                ss.text = sp;
@@ -5099,10 +5098,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            boolean areSuggestionsShown = areSuggestionsShown();
            boolean isInSelectionMode = mSelectionActionMode != null;

            if (areSuggestionsShown || isInSelectionMode) {
            if (isInSelectionMode) {
                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
                    KeyEvent.DispatcherState state = getKeyDispatcherState();
                    if (state != null) {
@@ -5115,10 +5113,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                        state.handleUpEvent(event);
                    }
                    if (event.isTracking() && !event.isCanceled()) {
                        if (areSuggestionsShown) {
                            hideSuggestions();
                            return true;
                        }
                        if (isInSelectionMode) {
                            stopSelectionActionMode();
                            return true;
@@ -5282,10 +5276,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

                // Has to be done on key down (and not on key up) to correctly be intercepted.
            case KeyEvent.KEYCODE_BACK:
                if (areSuggestionsShown()) {
                    hideSuggestions();
                    return -1;
                }
                if (mSelectionActionMode != null) {
                    stopSelectionActionMode();
                    return -1;
@@ -7950,9 +7940,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            }

            hideControllers();

            removeSpans(0, mText.length(), SuggestionSpan.class);
            removeSpans(0, mText.length(), SpellCheckSpan.class);
        }

        startStopMarquee(hasWindowFocus);
@@ -9196,11 +9183,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }
    }

    private static class SuggestionRangeSpan extends UnderlineSpan {
        // TODO themable, would be nice to make it a child class of TextAppearanceSpan, but
        // there is no way to have underline and TextAppearanceSpan.
    }

    private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnClickListener {
        private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
        private static final int NO_SUGGESTIONS = -1;
@@ -9208,13 +9190,42 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        private WordIterator mSuggestionWordIterator;
        private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan
                [(int) (AVERAGE_HIGHLIGHTS_PER_SUGGESTION * MAX_NUMBER_SUGGESTIONS)];
        private boolean mCursorWasVisibleBeforeSuggestions;

        private class CustomPopupWindow extends PopupWindow {
            public CustomPopupWindow(Context context, int defStyle) {
                super(context, null, defStyle);
            }

            @Override
            public void dismiss() {
                super.dismiss();

                if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
                    ((Editable) mText).removeSpan(mSuggestionRangeSpan);
                }

                setCursorVisible(mCursorWasVisibleBeforeSuggestions);
                if (hasInsertionController()) {
                    getInsertionController().show(); 
                }
            }
        }

        public SuggestionsPopupWindow() {
            for (int i = 0; i < mHighlightSpans.length; i++) {
                mHighlightSpans[i] = new TextAppearanceSpan(mContext,
                        android.R.style.TextAppearance_SuggestionHighlight);
            }
            mCursorWasVisibleBeforeSuggestions = mCursorVisible;
        }

        @Override
        protected void createPopupWindow() {
            mPopupWindow = new PopupWindow(TextView.this.mContext, null,
            mPopupWindow = new CustomPopupWindow(TextView.this.mContext,
                com.android.internal.R.attr.textSuggestionsWindowStyle);
            mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
            mPopupWindow.setOutsideTouchable(true);
            mPopupWindow.setFocusable(true);
            mPopupWindow.setClippingEnabled(false);
        }

@@ -9288,6 +9299,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            if (!(mText instanceof Editable)) return;

            if (updateSuggestions()) {
                mCursorWasVisibleBeforeSuggestions = mCursorVisible;
                setCursorVisible(false);
                super.show();
            }
        }
@@ -9312,9 +9325,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        @Override
        public void hide() {
            super.hide();
            if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
                ((Editable) mText).removeSpan(mSuggestionRangeSpan);
            }
        }

        private boolean updateSuggestions() {
@@ -9553,7 +9563,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                final int spanEnd = suggestionInfo.spanEnd;
                if (spanStart != NO_SUGGESTIONS) {
                    // SuggestionSpans are removed by replace: save them before
                    Editable editable = ((Editable) mText);
                    Editable editable = (Editable) mText;
                    SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
                            SuggestionSpan.class);
                    final int length = suggestionSpans.length;
@@ -9572,7 +9582,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    final String suggestion = textView.getText().subSequence(
                            suggestionStart, suggestionEnd).toString();
                    final String originalText = mText.subSequence(spanStart, spanEnd).toString();
                    ((Editable) mText).replace(spanStart, spanEnd, suggestion);
                    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?
@@ -9624,12 +9634,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        mSuggestionsPopupWindow.show();
    }

    void hideSuggestions() {
        if (mSuggestionsPopupWindow != null) {
            mSuggestionsPopupWindow.hide();
        }
    }

    boolean areSuggestionsShown() {
        return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing();
    }
@@ -10579,7 +10583,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            mEndHandle.setActionPopupWindow(mStartHandle.getActionPopupWindow());

            hideInsertionPointCursorController();
            hideSuggestions();
        }

        public void hide() {
@@ -10691,7 +10694,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private void hideControllers() {
        hideInsertionPointCursorController();
        stopSelectionActionMode();
        hideSuggestions();
    }

    /**
Loading