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

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

Merge "Refactoring in TextViews' handles"

parents b96320c2 2037b827
Loading
Loading
Loading
Loading
+59 −118
Original line number Original line Diff line number Diff line
@@ -81,8 +81,8 @@ import android.text.method.TextKeyListener;
import android.text.method.TimeKeyListener;
import android.text.method.TimeKeyListener;
import android.text.method.TransformationMethod;
import android.text.method.TransformationMethod;
import android.text.style.ClickableSpan;
import android.text.style.ClickableSpan;
import android.text.style.SuggestionSpan;
import android.text.style.ParagraphStyle;
import android.text.style.ParagraphStyle;
import android.text.style.SuggestionSpan;
import android.text.style.URLSpan;
import android.text.style.URLSpan;
import android.text.style.UpdateAppearance;
import android.text.style.UpdateAppearance;
import android.text.util.Linkify;
import android.text.util.Linkify;
@@ -8038,7 +8038,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            case ID_SELECTION_MODE:
            case ID_SELECTION_MODE:
                if (mSelectionActionMode != null) {
                if (mSelectionActionMode != null) {
                    // Selection mode is already started, simply change selected part.
                    // Selection mode is already started, simply change selected part.
                    updateSelectedRegion();
                    selectCurrentWord();
                } else {
                } else {
                    startSelectionActionMode();
                    startSelectionActionMode();
                }
                }
@@ -8188,8 +8188,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                startDrag(data, getTextThumbnailBuilder(selectedText), localState, 0);
                startDrag(data, getTextThumbnailBuilder(selectedText), localState, 0);
                stopSelectionActionMode();
                stopSelectionActionMode();
            } else {
            } else {
                // New selection at touch position
                selectCurrentWord();
                updateSelectedRegion();
            }
            }
            handled = true;
            handled = true;
        }
        }
@@ -8205,17 +8204,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return handled;
        return handled;
    }
    }


    /**
     * When selection mode is already started, this method simply updates the selected part of text
     * to the text under the finger.
     */
    private void updateSelectedRegion() {
        // Start a new selection at current position, keep selectionAction mode on
        selectCurrentWord();
        // Updates handles' positions
        getSelectionController().show();
    }

    private boolean touchPositionIsInSelection() {
    private boolean touchPositionIsInSelection() {
        int selectionStart = getSelectionStart();
        int selectionStart = getSelectionStart();
        int selectionEnd = getSelectionEnd();
        int selectionEnd = getSelectionEnd();
@@ -8783,7 +8771,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        private float mTouchOffsetY;
        private float mTouchOffsetY;
        // Where the touch position should be on the handle to ensure a maximum cursor visibility
        // Where the touch position should be on the handle to ensure a maximum cursor visibility
        private float mIdealVerticalOffset;
        private float mIdealVerticalOffset;
        // Parent's (TextView) position in window
        // Parent's (TextView) previous position in window
        private int mLastParentX, mLastParentY;
        private int mLastParentX, mLastParentY;
        // PopupWindow container absolute position with respect to the enclosing window
        // PopupWindow container absolute position with respect to the enclosing window
        private int mContainerPositionX, mContainerPositionY;
        private int mContainerPositionX, mContainerPositionY;
@@ -8857,12 +8845,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }
        }


        public void show() {
        public void show() {
            updateContainerPosition();
            if (isShowing()) {
            if (isShowing()) {
                mContainer.update(mContainerPositionX, mContainerPositionY,
                mContainer.update(mContainerPositionX, mContainerPositionY,
                        mRight - mLeft, mBottom - mTop);
                        mRight - mLeft, mBottom - mTop);

                hideAssociatedPopupWindow();
            } else {
            } else {
                mContainer.showAtLocation(TextView.this, 0,
                mContainer.showAtLocation(TextView.this, 0,
                        mContainerPositionX, mContainerPositionY);
                        mContainerPositionX, mContainerPositionY);
@@ -8877,7 +8862,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        protected void dismiss() {
        protected void dismiss() {
            mIsDragging = false;
            mIsDragging = false;
            mContainer.dismiss();
            mContainer.dismiss();
            hideAssociatedPopupWindow();
        }
        }


        public void hide() {
        public void hide() {
@@ -8908,22 +8892,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            final int compoundPaddingLeft = getCompoundPaddingLeft();
            final int compoundPaddingLeft = getCompoundPaddingLeft();
            final int compoundPaddingRight = getCompoundPaddingRight();
            final int compoundPaddingRight = getCompoundPaddingRight();


            final TextView hostView = TextView.this;
            final TextView textView = TextView.this;


            if (mTempRect == null) mTempRect = new Rect();
            if (mTempRect == null) mTempRect = new Rect();
            final Rect clip = mTempRect;
            final Rect clip = mTempRect;
            clip.left = compoundPaddingLeft;
            clip.left = compoundPaddingLeft;
            clip.top = extendedPaddingTop;
            clip.top = extendedPaddingTop;
            clip.right = hostView.getWidth() - compoundPaddingRight;
            clip.right = textView.getWidth() - compoundPaddingRight;
            clip.bottom = hostView.getHeight() - extendedPaddingBottom;
            clip.bottom = textView.getHeight() - extendedPaddingBottom;


            final ViewParent parent = hostView.getParent();
            final ViewParent parent = textView.getParent();
            if (parent == null || !parent.getChildVisibleRect(hostView, clip, null)) {
            if (parent == null || !parent.getChildVisibleRect(textView, clip, null)) {
                return false;
                return false;
            }
            }


            final int[] coords = mTempCoords;
            final int[] coords = mTempCoords;
            hostView.getLocationInWindow(coords);
            textView.getLocationInWindow(coords);
            final int posX = coords[0] + mPositionX + (int) mHotspotX;
            final int posX = coords[0] + mPositionX + (int) mHotspotX;
            final int posY = coords[1] + mPositionY;
            final int posY = coords[1] + mPositionY;


@@ -8932,23 +8916,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    posY >= clip.top && posY <= clip.bottom;
                    posY >= clip.top && posY <= clip.bottom;
        }
        }


        private void moveTo(int x, int y) {
            mPositionX = x - TextView.this.mScrollX;
            mPositionY = y - TextView.this.mScrollY;

            if (mIsDragging) {
                TextView.this.getLocationInWindow(mTempCoords);
                if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) {
                    mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX;
                    mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY;
                    mLastParentX = mTempCoords[0];
                    mLastParentY = mTempCoords[1];
                }

                hideAssociatedPopupWindow();
            }
        }

        public abstract int getCurrentCursorOffset();
        public abstract int getCurrentCursorOffset();


        public abstract void updateOffset(int offset);
        public abstract void updateOffset(int offset);
@@ -8957,44 +8924,44 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener


        protected void positionAtCursorOffset(int offset) {
        protected void positionAtCursorOffset(int offset) {
            addPositionToTouchUpFilter(offset);
            addPositionToTouchUpFilter(offset);
            final int width = mDrawable.getIntrinsicWidth();
            final int height = mDrawable.getIntrinsicHeight();
            final int line = mLayout.getLineForOffset(offset);
            final int line = mLayout.getLineForOffset(offset);
            final int lineBottom = mLayout.getLineBottom(line);
            final int lineBottom = mLayout.getLineBottom(line);


            final Rect bounds = sCursorControllerTempRect;
            mPositionX = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX);
            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX) +
            mPositionY = lineBottom;
                    TextView.this.mScrollX;
            bounds.top = lineBottom + TextView.this.mScrollY;

            bounds.right = bounds.left + width;
            bounds.bottom = bounds.top + height;


            convertFromViewportToContentCoordinates(bounds);
            // Take TextView's padding into account.
            moveTo(bounds.left, bounds.top);
            mPositionX += viewportToContentHorizontalOffset();
            mPositionY += viewportToContentVerticalOffset();
        }
        }


        /**
        protected boolean updateContainerPosition() {
         * Updates the global container's position.
         * @return whether or not the position has actually changed
         */
        private boolean updateContainerPosition() {
            positionAtCursorOffset(getCurrentCursorOffset());
            positionAtCursorOffset(getCurrentCursorOffset());

            final int previousContainerPositionX = mContainerPositionX;
            final int previousContainerPositionY = mContainerPositionY;

            TextView.this.getLocationInWindow(mTempCoords);
            TextView.this.getLocationInWindow(mTempCoords);
            final int containerPositionX = mTempCoords[0] + mPositionX;
            mContainerPositionX = mTempCoords[0] + mPositionX;
            final int containerPositionY = mTempCoords[1] + mPositionY;
            mContainerPositionY = mTempCoords[1] + mPositionY;


            if (containerPositionX != mContainerPositionX ||
            return (previousContainerPositionX != mContainerPositionX ||
                containerPositionY != mContainerPositionY) {
                    previousContainerPositionY != mContainerPositionY);
                mContainerPositionX = containerPositionX;
                mContainerPositionY = containerPositionY;
                return true;
            }
            return false;
        }
        }


        public boolean onPreDraw() {
        public boolean onPreDraw() {
            if (updateContainerPosition()) {
            if (updateContainerPosition()) {
                if (mIsDragging) {
                    if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) {
                        mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX;
                        mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY;
                        mLastParentX = mTempCoords[0];
                        mLastParentY = mTempCoords[1];
                    }
                }

                onHandleMoved();

                if (isPositionVisible()) {
                if (isPositionVisible()) {
                    mContainer.update(mContainerPositionX, mContainerPositionY,
                    mContainer.update(mContainerPositionX, mContainerPositionY,
                            mRight - mLeft, mBottom - mTop);
                            mRight - mLeft, mBottom - mTop);
@@ -9007,9 +8974,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                        dismiss();
                        dismiss();
                    }
                    }
                }
                }

                // Hide paste popup as soon as the view is scrolled or moved
                hideAssociatedPopupWindow();
            }
            }
            return true;
            return true;
        }
        }
@@ -9076,8 +9040,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return mIsDragging;
            return mIsDragging;
        }
        }


        void hideAssociatedPopupWindow() {
        void onHandleMoved() {
            // No associated popup window by default
            // Does nothing by default
        }
        }


        public void onDetached() {
        public void onDetached() {
@@ -9096,15 +9060,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        private Runnable mHider;
        private Runnable mHider;
        private Runnable mPastePopupShower;
        private Runnable mPastePopupShower;


        public InsertionHandleView() {
            super();
        }

        @Override
        @Override
        public void show() {
        public void show() {
            super.show();
            super.show();
            hideDelayed();
            hideDelayed();
            removePastePopupCallback();
            hidePastePopupWindow();
        }
        }


        public void show(int delayBeforePaste) {
        public void show(int delayBeforePaste) {
@@ -9118,11 +9078,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                if (mPastePopupShower == null) {
                if (mPastePopupShower == null) {
                    mPastePopupShower = new Runnable() {
                    mPastePopupShower = new Runnable() {
                        public void run() {
                        public void run() {
                            showAssociatedPopupWindow();
                            showPastePopupWindow();
                        }
                        }
                    };
                    };
                }
                }
                postDelayed(mPastePopupShower, delayBeforePaste);
                TextView.this.postDelayed(mPastePopupShower, delayBeforePaste);
            }
            }
        }
        }


@@ -9132,11 +9092,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            onDetached();
            onDetached();
        }
        }


        @Override
        public void hide() {
            super.hide();
        }

        private void hideDelayed() {
        private void hideDelayed() {
            removeHiderCallback();
            removeHiderCallback();
            if (mHider == null) {
            if (mHider == null) {
@@ -9146,18 +9101,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    }
                    }
                };
                };
            }
            }
            postDelayed(mHider, DELAY_BEFORE_FADE_OUT);
            TextView.this.postDelayed(mHider, DELAY_BEFORE_FADE_OUT);
        }

        private void removePastePopupCallback() {
            if (mPastePopupShower != null) {
                removeCallbacks(mPastePopupShower);
            }
        }
        }


        private void removeHiderCallback() {
        private void removeHiderCallback() {
            if (mHider != null) {
            if (mHider != null) {
                removeCallbacks(mHider);
                TextView.this.removeCallbacks(mHider);
            }
            }
        }
        }


@@ -9197,6 +9146,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                            }
                            }
                        }
                        }
                    }
                    }
                    hideDelayed();
                    break;

                case MotionEvent.ACTION_CANCEL:
                    hideDelayed();
                    break;
                    break;


                default:
                default:
@@ -9214,31 +9168,30 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        @Override
        @Override
        public void updateOffset(int offset) {
        public void updateOffset(int offset) {
            Selection.setSelection((Spannable) mText, offset);
            Selection.setSelection((Spannable) mText, offset);
            positionAtCursorOffset(offset);
        }
        }


        @Override
        @Override
        public void updatePosition(int x, int y) {
        public void updatePosition(int x, int y) {
            final int previousOffset = getCurrentCursorOffset();
            updateOffset(getOffset(x, y));
            final int newOffset = getOffset(x, y);

            if (newOffset != previousOffset) {
                updateOffset(newOffset);
                removePastePopupCallback();
            }
            hideDelayed();
        }
        }


        void showAssociatedPopupWindow() {
        void showPastePopupWindow() {
            if (mPastePopupWindow == null) {
            if (mPastePopupWindow == null) {
                // Lazy initialisation: create when actually shown only.
                mPastePopupWindow = new PastePopupWindow();
                mPastePopupWindow = new PastePopupWindow();
            }
            }
            mPastePopupWindow.show();
            mPastePopupWindow.show();
        }
        }


        @Override
        @Override
        void hideAssociatedPopupWindow() {
        void onHandleMoved() {
            removeHiderCallback();
            hidePastePopupWindow();
        }

        void hidePastePopupWindow() {
            if (mPastePopupShower != null) {
                TextView.this.removeCallbacks(mPastePopupShower);
            }
            if (mPastePopupWindow != null) {
            if (mPastePopupWindow != null) {
                mPastePopupWindow.hide();
                mPastePopupWindow.hide();
            }
            }
@@ -9247,15 +9200,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        @Override
        @Override
        public void onDetached() {
        public void onDetached() {
            removeHiderCallback();
            removeHiderCallback();
            removePastePopupCallback();
            hidePastePopupWindow();
        }
        }
    }
    }


    private class SelectionStartHandleView extends HandleView {
    private class SelectionStartHandleView extends HandleView {
        public SelectionStartHandleView() {
            super();
        }

        @Override
        @Override
        protected void initDrawable() {
        protected void initDrawable() {
            if (mSelectHandleLeft == null) {
            if (mSelectHandleLeft == null) {
@@ -9274,7 +9223,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        @Override
        @Override
        public void updateOffset(int offset) {
        public void updateOffset(int offset) {
            Selection.setSelection((Spannable) mText, offset, getSelectionEnd());
            Selection.setSelection((Spannable) mText, offset, getSelectionEnd());
            positionAtCursorOffset(offset);
        }
        }


        @Override
        @Override
@@ -9290,15 +9238,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            if (offset >= selectionEnd) offset = selectionEnd - 1;
            if (offset >= selectionEnd) offset = selectionEnd - 1;


            Selection.setSelection((Spannable) mText, offset, selectionEnd);
            Selection.setSelection((Spannable) mText, offset, selectionEnd);
            positionAtCursorOffset(offset);
        }
        }
    }
    }


    private class SelectionEndHandleView extends HandleView {
    private class SelectionEndHandleView extends HandleView {
        public SelectionEndHandleView() {
            super();
        }

        @Override
        @Override
        protected void initDrawable() {
        protected void initDrawable() {
            if (mSelectHandleRight == null) {
            if (mSelectHandleRight == null) {
@@ -9317,7 +9260,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        @Override
        @Override
        public void updateOffset(int offset) {
        public void updateOffset(int offset) {
            Selection.setSelection((Spannable) mText, getSelectionStart(), offset);
            Selection.setSelection((Spannable) mText, getSelectionStart(), offset);
            positionAtCursorOffset(offset);
        }
        }


        @Override
        @Override
@@ -9333,7 +9275,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            if (offset <= selectionStart) offset = selectionStart + 1;
            if (offset <= selectionStart) offset = selectionStart + 1;


            Selection.setSelection((Spannable) mText, selectionStart, offset);
            Selection.setSelection((Spannable) mText, selectionStart, offset);
            positionAtCursorOffset(offset);
        }
        }
    }
    }