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

Commit d3938821 authored by Roozbeh Pournader's avatar Roozbeh Pournader Committed by Android (Google) Code Review
Browse files

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

parents 7040f573 7557a5a0
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