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

Commit 4d56a001 authored by Roozbeh Pournader's avatar Roozbeh Pournader Committed by android-build-merger
Browse files

Merge "Revert "Make selection end handle stick to selection at line end."" into oc-dev

am: d3938821

Change-Id: Icae3c9b7166b4b83b31ad08bcd78db2205c916c1
parents 4c613520 d3938821
Loading
Loading
Loading
Loading
+25 −56
Original line number Diff line number Diff line
@@ -1030,24 +1030,17 @@ public abstract class Layout {
     * the paragraph's primary direction.
     */
    public float getPrimaryHorizontal(int offset) {
        return getPrimaryHorizontal(offset, false /* not clamped */,
                true /* getNewLineStartPosOnLineBreak */);
        return getPrimaryHorizontal(offset, false /* not clamped */);
    }

    /**
     * Get the primary horizontal position for the specified text offset, but
     * optionally clamp it so that it doesn't exceed the width of the layout.
     *
     * @param offset the offset to get horizontal position
     * @param clamped whether to clamp the position by using the width of this layout.
     * @param getNewLineStartPosOnLineBreak whether to get the start position of new line when the
     * offset is at automatic line break.
     * @hide
     */
    public float getPrimaryHorizontal(int offset, boolean clamped,
            boolean getNewLineStartPosOnLineBreak) {
    public float getPrimaryHorizontal(int offset, boolean clamped) {
        boolean trailing = primaryIsTrailingPrevious(offset);
        return getHorizontal(offset, trailing, clamped, getNewLineStartPosOnLineBreak);
        return getHorizontal(offset, trailing, clamped);
    }

    /**
@@ -1056,37 +1049,26 @@ public abstract class Layout {
     * the direction other than the paragraph's primary direction.
     */
    public float getSecondaryHorizontal(int offset) {
        return getSecondaryHorizontal(offset, false /* not clamped */,
                true /* getNewLineStartPosOnLineBreak */);
        return getSecondaryHorizontal(offset, false /* not clamped */);
    }

    /**
     * Get the secondary horizontal position for the specified text offset, but
     * optionally clamp it so that it doesn't exceed the width of the layout.
     *
     * @param offset the offset to get horizontal position
     * @param clamped whether to clamp the position by using the width of this layout.
     * @param getNewLineStartPosOnLineBreak whether to get the start position of new line when the
     * offset is at automatic line break.
     * @hide
     */
    public float getSecondaryHorizontal(int offset, boolean clamped,
            boolean getNewLineStartPosOnLineBreak) {
    public float getSecondaryHorizontal(int offset, boolean clamped) {
        boolean trailing = primaryIsTrailingPrevious(offset);
        return getHorizontal(offset, !trailing, clamped, getNewLineStartPosOnLineBreak);
        return getHorizontal(offset, !trailing, clamped);
    }

    private float getHorizontal(int offset, boolean primary,
            boolean getNewLineStartPosOnLineBreak) {
        return primary ? getPrimaryHorizontal(offset, false /* not clamped */,
                getNewLineStartPosOnLineBreak)
                : getSecondaryHorizontal(offset, false /* not clamped */,
                        getNewLineStartPosOnLineBreak);
    private float getHorizontal(int offset, boolean primary) {
        return primary ? getPrimaryHorizontal(offset) : getSecondaryHorizontal(offset);
    }

    private float getHorizontal(int offset, boolean trailing, boolean clamped,
            boolean getNewLineStartPosOnLineBreak) {
        final int line = getLineForOffset(offset, getNewLineStartPosOnLineBreak);
    private float getHorizontal(int offset, boolean trailing, boolean clamped) {
        int line = getLineForOffset(offset);

        return getHorizontal(offset, trailing, line, clamped);
    }

@@ -1300,10 +1282,6 @@ public abstract class Layout {
     * beyond the end of the text, you get the last line.
     */
    public int getLineForOffset(int offset) {
        return getLineForOffset(offset, true);
    }

    private int getLineForOffset(int offset, boolean getNewLineOnLineBreak) {
        int high = getLineCount(), low = -1, guess;

        while (high - low > 1) {
@@ -1318,10 +1296,6 @@ public abstract class Layout {
        if (low < 0) {
            return 0;
        } else {
            if (!getNewLineOnLineBreak && low > 0 && getLineStart(low) == offset
                    && mText.charAt(offset - 1) != '\n') {
                return low - 1;
            }
            return low;
        }
    }
@@ -1357,14 +1331,14 @@ public abstract class Layout {
                false, null);

        final int max;
        if (line != getLineCount() - 1 && mText.charAt(lineEndOffset - 1) == '\n') {
        if (line == getLineCount() - 1) {
            max = lineEndOffset;
        } else {
            max = tl.getOffsetToLeftRightOf(lineEndOffset - lineStartOffset,
                    !isRtlCharAt(lineEndOffset - 1)) + lineStartOffset;
        } else {
            max = lineEndOffset;
        }
        int best = lineStartOffset;
        float bestdist = Math.abs(getHorizontal(best, primary, true) - horiz);
        float bestdist = Math.abs(getHorizontal(best, primary) - horiz);

        for (int i = 0; i < dirs.mDirections.length; i += 2) {
            int here = lineStartOffset + dirs.mDirections[i];
@@ -1380,9 +1354,7 @@ public abstract class Layout {
                guess = (high + low) / 2;
                int adguess = getOffsetAtStartOf(guess);

                if (getHorizontal(adguess, primary,
                        adguess == lineStartOffset || adguess != lineEndOffset) * swap
                                >= horiz * swap) {
                if (getHorizontal(adguess, primary) * swap >= horiz * swap) {
                    high = guess;
                } else {
                    low = guess;
@@ -1396,11 +1368,9 @@ public abstract class Layout {
                int aft = tl.getOffsetToLeftRightOf(low - lineStartOffset, isRtl) + lineStartOffset;
                low = tl.getOffsetToLeftRightOf(aft - lineStartOffset, !isRtl) + lineStartOffset;
                if (low >= here && low < there) {
                    float dist = Math.abs(getHorizontal(low, primary,
                            low == lineStartOffset || low != lineEndOffset) - horiz);
                    float dist = Math.abs(getHorizontal(low, primary) - horiz);
                    if (aft < there) {
                        float other = Math.abs(getHorizontal(aft, primary,
                                aft == lineStartOffset || aft != lineEndOffset) - horiz);
                        float other = Math.abs(getHorizontal(aft, primary) - horiz);

                        if (other < dist) {
                            dist = other;
@@ -1415,8 +1385,7 @@ public abstract class Layout {
                }
            }

            float dist = Math.abs(getHorizontal(here, primary,
                    here == lineStartOffset || here != lineEndOffset) - horiz);
            float dist = Math.abs(getHorizontal(here, primary) - horiz);

            if (dist < bestdist) {
                bestdist = dist;
@@ -1424,10 +1393,10 @@ public abstract class Layout {
            }
        }

        float dist = Math.abs(getHorizontal(max, primary,
                max == lineStartOffset || max != lineEndOffset) - horiz);
        float dist = Math.abs(getHorizontal(max, primary) - horiz);

        if (dist <= bestdist) {
            bestdist = dist;
            best = max;
        }

@@ -1621,9 +1590,8 @@ public abstract class Layout {
        int bottom = getLineTop(line+1);

        boolean clamped = shouldClampCursor(line);
        float h1 = getPrimaryHorizontal(point, clamped, true) - 0.5f;
        float h2 = isLevelBoundary(point)
                ? getSecondaryHorizontal(point, clamped, true) - 0.5f : h1;
        float h1 = getPrimaryHorizontal(point, clamped) - 0.5f;
        float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point, clamped) - 0.5f : h1;

        int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) |
                   TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING);
@@ -1740,7 +1708,8 @@ public abstract class Layout {
        }

        int startline = getLineForOffset(start);
        int endline = getLineForOffset(end, false);
        int endline = getLineForOffset(end);

        int top = getLineTop(startline);
        int bottom = getLineBottom(endline);

+10 −41
Original line number Diff line number Diff line
@@ -1915,11 +1915,10 @@ public class Editor {
        }

        boolean clamped = layout.shouldClampCursor(line);
        updateCursorPosition(0, top, middle, layout.getPrimaryHorizontal(offset, clamped, true));
        updateCursorPosition(0, top, middle, layout.getPrimaryHorizontal(offset, clamped));

        if (mCursorCount == 2) {
            updateCursorPosition(1, middle, bottom,
                    layout.getSecondaryHorizontal(offset, clamped, true));
            updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset, clamped));
        }
    }

@@ -4340,7 +4339,7 @@ public class Editor {
                    updateSelection(offset);
                    addPositionToTouchUpFilter(offset);
                }
                final int line = getLineForOffset(layout, offset);
                final int line = layout.getLineForOffset(offset);
                mPrevLine = line;

                mPositionX = getCursorHorizontalPosition(layout, offset) - mHotspotX
@@ -4367,15 +4366,6 @@ public class Editor {
            return (int) (getHorizontal(layout, offset) - 0.5f);
        }

        /**
         * @param layout Text layout.
         * @param offset Character offset for the cursor.
         * @return The line the cursor should be at.
         */
        int getLineForOffset(Layout layout, int offset) {
            return layout.getLineForOffset(offset);
        }

        @Override
        public void updatePosition(int parentPositionX, int parentPositionY,
                boolean parentPositionChanged, boolean parentScrolled) {
@@ -4804,7 +4794,7 @@ public class Editor {
                    || !isStartHandle() && initialOffset <= anotherHandleOffset) {
                // Handles have crossed, bound it to the first selected line and
                // adjust by word / char as normal.
                currLine = getLineForOffset(layout, anotherHandleOffset, !isStartHandle());
                currLine = layout.getLineForOffset(anotherHandleOffset);
                initialOffset = getOffsetAtCoordinate(layout, currLine, x);
            }

@@ -4876,18 +4866,14 @@ public class Editor {
            if (isExpanding) {
                // User is increasing the selection.
                int wordBoundary = isStartHandle() ? wordStart : wordEnd;
                final boolean atLineBoundary = layout.getLineStart(currLine) == offset
                        || layout.getLineEnd(currLine) == offset;
                final boolean atWordBoundary = getWordIteratorWithText().isBoundary(offset);
                final boolean snapToWord = !(atLineBoundary && atWordBoundary)
                        && (!mInWord
                final boolean snapToWord = (!mInWord
                        || (isStartHandle() ? currLine < mPrevLine : currLine > mPrevLine))
                                && atRtl == isAtRtlRun(layout, wordBoundary);
                if (snapToWord) {
                    // Sometimes words can be broken across lines (Chinese, hyphenation).
                    // We still snap to the word boundary but we only use the letters on the
                    // current line to determine if the user is far enough into the word to snap.
                    if (getLineForOffset(layout, wordBoundary) != currLine) {
                    if (layout.getLineForOffset(wordBoundary) != currLine) {
                        wordBoundary = isStartHandle()
                                ? layout.getLineStart(currLine) : layout.getLineEnd(currLine);
                    }
@@ -5035,29 +5021,12 @@ public class Editor {
        }

        private float getHorizontal(@NonNull Layout layout, int offset, boolean startHandle) {
            final int line = getLineForOffset(layout, offset);
            final int line = layout.getLineForOffset(offset);
            final int offsetToCheck = startHandle ? offset : Math.max(offset - 1, 0);
            final boolean isRtlChar = layout.isRtlCharAt(offsetToCheck);
            final boolean isRtlParagraph = layout.getParagraphDirection(line) == -1;
            return (isRtlChar == isRtlParagraph)
                    ? layout.getPrimaryHorizontal(offset, false, startHandle)
                            : layout.getSecondaryHorizontal(offset, false, startHandle);
        }

        @Override
        public int getLineForOffset(@NonNull Layout layout, int offset) {
            return getLineForOffset(layout, offset, isStartHandle());
        }

        private int getLineForOffset(@NonNull Layout layout, int offset, boolean startHandle) {
            final int line = layout.getLineForOffset(offset);
            if (!startHandle && line > 0 && layout.getLineStart(line) == offset
                    && mTextView.getText().charAt(offset - 1) != '\n') {
                // If end handle is at a line break in a paragraph, the handle should be at the
                // previous line.
                return line - 1;
            }
            return line;
                    ? layout.getPrimaryHorizontal(offset) : layout.getSecondaryHorizontal(offset);
        }

        @Override
+1 −1
Original line number Diff line number Diff line
@@ -8470,7 +8470,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        // right where it is most likely to be annoying.
        final boolean clamped = grav > 0;
        // FIXME: Is it okay to truncate this, or should we round?
        final int x = (int) layout.getPrimaryHorizontal(offset, clamped, true);
        final int x = (int) layout.getPrimaryHorizontal(offset, clamped);
        final int top = layout.getLineTop(line);
        final int bottom = layout.getLineTop(line + 1);

+0 −21
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import static android.widget.espresso.TextViewActions.dragHandle;
import static android.widget.espresso.TextViewActions.Handle;
import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
import static android.widget.espresso.TextViewAssertions.handleIsOnLine;
import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
import static android.widget.espresso.TextViewAssertions.hasSelection;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
@@ -448,26 +447,6 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
        onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn\nopqr"));
    }

    public void testSelectionHandles_multiLine_japanese() throws Exception {
        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
        final StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 100; ++i) {
            builder.append("\u3042\u3044\u3046\u3048\u304A");
            onView(withId(R.id.textview)).perform(replaceText(builder.toString()));
            final int lineEnd = textView.getLayout().getLineEnd(0);
            if (lineEnd < builder.length()) {
                break;
            }
        }
        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(3));

        final int lineEnd = textView.getLayout().getLineEnd(0);
        onHandleView(com.android.internal.R.id.selection_end_handle)
                .perform(dragHandle(textView, Handle.SELECTION_END, lineEnd, true, false));
        onHandleView(com.android.internal.R.id.selection_end_handle)
                .check(handleIsOnLine(textView, 0));
    }

    public void testSelectionHandles_multiLine_rtl() throws Exception {
        // Arabic text.
        final String text = "\u062A\u062B\u062C\n" + "\u062D\u062E\u062F\n"
+26 −64
Original line number Diff line number Diff line
@@ -331,37 +331,15 @@ public final class TextViewActions {
     */
    public static ViewAction dragHandle(TextView textView, Handle handleType, int endIndex,
            boolean primary) {
        return dragHandle(textView, handleType, endIndex, primary, true);
    }

    /**
     * Returns an action that tap then drags on the handle from the current position to endIndex on
     * the TextView.<br>
     * <br>
     * View constraints:
     * <ul>
     * <li>must be a TextView's drag-handle displayed on screen
     * <ul>
     *
     * @param textView TextView the handle is on
     * @param handleType Type of the handle
     * @param endIndex The index of the TextView's text to end the drag at
     * @param primary whether to use primary direction to get coordinate form index when endIndex is
     * at a direction boundary.
     * @param getNewLineStartPosOnLineBreak whether to use new line start coordinate on a line break
     * within a paragraph.
     */
    public static ViewAction dragHandle(TextView textView, Handle handleType, int endIndex,
            boolean primary, boolean getNewLineStartPosOnLineBreak) {
        return actionWithAssertions(
                new DragAction(
                        DragAction.Drag.TAP,
                        new CurrentHandleCoordinates(textView),
                        new HandleCoordinates(textView, handleType, endIndex, primary,
                                getNewLineStartPosOnLineBreak),
                        new HandleCoordinates(textView, handleType, endIndex, primary),
                        Press.FINGER,
                        Editor.HandleView.class));
    }

    /**
     * A provider of the x, y coordinates of the handle dragging point.
     */
@@ -424,16 +402,13 @@ public final class TextViewActions {
        private final Handle mHandleType;
        private final int mIndex;
        private final boolean mPrimary;
        private final boolean mGetNewLineStartPosOnLineBreak;
        private final String mActionDescription;

        public HandleCoordinates(TextView textView, Handle handleType, int index, boolean primary,
                boolean getNewLineStartPosOnLineBreak) {
        public HandleCoordinates(TextView textView, Handle handleType, int index, boolean primary) {
            mTextView = textView;
            mHandleType = handleType;
            mIndex = index;
            mPrimary = primary;
            mGetNewLineStartPosOnLineBreak = getNewLineStartPosOnLineBreak;
            mActionDescription = "Could not locate " + handleType.toString()
                    + " handle that points text index: " + index
                    + " (" + (primary ? "primary" : "secondary" ) + ")";
@@ -470,10 +445,9 @@ public final class TextViewActions {
            final float currentX = handleView.getHorizontal(layout, currentOffset);
            final float currentY = layout.getLineTop(currentLine);
            final float[] currentCoordinates =
                    convertToScreenCoordinates(mTextView, currentX, currentY);
                    TextCoordinates.convertToScreenCoordinates(mTextView, currentX, currentY);
            final float[] targetCoordinates =
                    (new TextCoordinates(mIndex, mPrimary, mGetNewLineStartPosOnLineBreak))
                            .calculateCoordinates(mTextView);
                    (new TextCoordinates(mIndex, mPrimary)).calculateCoordinates(mTextView);
            final Rect bounds = new Rect();
            view.getBoundsOnScreen(bounds);
            final Rect visibleDisplayBounds = new Rect();
@@ -511,27 +485,23 @@ public final class TextViewActions {

        private final int mIndex;
        private final boolean mPrimary;
        private final boolean mGetNewLineStartPosOnLineBreak;
        private final String mActionDescription;

        public TextCoordinates(int index) {
            this(index, true, true);
            this(index, true);
        }

        public TextCoordinates(int index, boolean primary, boolean getNewLineStartPosOnLineBreak) {
        public TextCoordinates(int index, boolean primary) {
            mIndex = index;
            mPrimary = primary;
            mGetNewLineStartPosOnLineBreak = getNewLineStartPosOnLineBreak;
            mActionDescription = "Could not locate text at index: " + mIndex
                    + " (" + (primary ? "primary" : "secondary" )
                    + ", mGetNewLineStartPosOnLineBreak: " + mGetNewLineStartPosOnLineBreak + ")";
                    + " (" + (primary ? "primary" : "secondary" ) + ")";
        }

        @Override
        public float[] calculateCoordinates(View view) {
            try {
                return locateTextAtIndex((TextView) view, mIndex, mPrimary,
                        mGetNewLineStartPosOnLineBreak);
                return locateTextAtIndex((TextView) view, mIndex, mPrimary);
            } catch (ClassCastException e) {
                throw new PerformException.Builder()
                        .withActionDescription(mActionDescription)
@@ -550,26 +520,17 @@ public final class TextViewActions {
        /**
         * @throws StringIndexOutOfBoundsException
         */
        private float[] locateTextAtIndex(TextView textView, int index, boolean primary,
                boolean getNewLineStartPosOnLineBreak) {
        private float[] locateTextAtIndex(TextView textView, int index, boolean primary) {
            if (index < 0 || index > textView.getText().length()) {
                throw new StringIndexOutOfBoundsException(index);
            }
            final Layout layout = textView.getLayout();

            int line = layout.getLineForOffset(index);
            if (!getNewLineStartPosOnLineBreak && line > 0 && layout.getLineStart(line) == index
                    && textView.getText().charAt(index - 1) != '\n') {
                line = line - 1;
            }
            final int line = layout.getLineForOffset(index);
            return convertToScreenCoordinates(textView,
                    (primary ? layout.getPrimaryHorizontal(index, false,
                            getNewLineStartPosOnLineBreak)
                            : layout.getSecondaryHorizontal(index, false,
                                    getNewLineStartPosOnLineBreak)),
                    (primary ? layout.getPrimaryHorizontal(index)
                            : layout.getSecondaryHorizontal(index)),
                    layout.getLineTop(line));
        }
    }

        /**
         * Convert TextView's local coordinates to on screen coordinates.
@@ -585,3 +546,4 @@ public final class TextViewActions {
                    y + textView.getTotalPaddingTop() - textView.getScrollY() + xy[1] };
        }
    }
}
Loading