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

Commit c7053c65 authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Implement paragraph cursor movement and selection extension

Bug: 240624037
Test: atest BaseMovementMethodTest SelectionParagraphTest
Change-Id: I75161fc88975736fe26395959bafba661c590f66
parent bc2135bc
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -45244,6 +45244,8 @@ package android.text {
    method public static boolean extendRight(android.text.Spannable, android.text.Layout);
    method public static final void extendSelection(android.text.Spannable, int);
    method public static boolean extendToLeftEdge(android.text.Spannable, android.text.Layout);
    method public static boolean extendToParagraphEnd(@NonNull android.text.Spannable);
    method public static boolean extendToParagraphStart(@NonNull android.text.Spannable);
    method public static boolean extendToRightEdge(android.text.Spannable, android.text.Layout);
    method public static boolean extendUp(android.text.Spannable, android.text.Layout);
    method public static final int getSelectionEnd(CharSequence);
@@ -45252,6 +45254,8 @@ package android.text {
    method public static boolean moveLeft(android.text.Spannable, android.text.Layout);
    method public static boolean moveRight(android.text.Spannable, android.text.Layout);
    method public static boolean moveToLeftEdge(android.text.Spannable, android.text.Layout);
    method public static boolean moveToParagraphEnd(@NonNull android.text.Spannable, @NonNull android.text.Layout);
    method public static boolean moveToParagraphStart(@NonNull android.text.Spannable, @NonNull android.text.Layout);
    method public static boolean moveToRightEdge(android.text.Spannable, android.text.Layout);
    method public static boolean moveUp(android.text.Spannable, android.text.Layout);
    method public static final void removeSelection(android.text.Spannable);
@@ -45700,6 +45704,7 @@ package android.text.method {
    method protected boolean left(android.widget.TextView, android.text.Spannable);
    method protected boolean lineEnd(android.widget.TextView, android.text.Spannable);
    method protected boolean lineStart(android.widget.TextView, android.text.Spannable);
    method public boolean nextParagraph(@NonNull android.widget.TextView, @NonNull android.text.Spannable);
    method public boolean onGenericMotionEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
    method public boolean onKeyDown(android.widget.TextView, android.text.Spannable, int, android.view.KeyEvent);
    method public boolean onKeyOther(android.widget.TextView, android.text.Spannable, android.view.KeyEvent);
@@ -45709,6 +45714,7 @@ package android.text.method {
    method public boolean onTrackballEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
    method protected boolean pageDown(android.widget.TextView, android.text.Spannable);
    method protected boolean pageUp(android.widget.TextView, android.text.Spannable);
    method public boolean previousParagraph(@NonNull android.widget.TextView, @NonNull android.text.Spannable);
    method protected boolean right(android.widget.TextView, android.text.Spannable);
    method protected boolean top(android.widget.TextView, android.text.Spannable);
    method protected boolean up(android.widget.TextView, android.text.Spannable);
+95 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.text;

import android.annotation.NonNull;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;

@@ -346,6 +347,100 @@ public class Selection {
        return false;
    }

    private static final char PARAGRAPH_SEPARATOR = '\n';

    /**
     * Move the cusrot to the closest paragraph start offset.
     *
     * @param text the spannable text
     * @param layout layout to be used for drawing.
     * @return true if the cursor is moved, otherwise false.
     */
    public static boolean moveToParagraphStart(@NonNull Spannable text, @NonNull Layout layout) {
        int start = getSelectionStart(text);
        int end = getSelectionEnd(text);

        if (start != end) {
            setSelection(text, chooseHorizontal(layout, -1, start, end));
            return true;
        } else {
            int to = TextUtils.lastIndexOf(text, PARAGRAPH_SEPARATOR, start - 1);
            if (to == -1) {
                to = 0;  // If not found, use the document start offset as a paragraph start.
            }
            if (to != end) {
                setSelection(text, to);
                return true;
            }
        }
        return false;
    }

    /**
     * Move the cursor to the closest paragraph end offset.
     *
     * @param text the spannable text
     * @param layout layout to be used for drawing.
     * @return true if the cursor is moved, otherwise false.
     */
    public static boolean moveToParagraphEnd(@NonNull Spannable text, @NonNull Layout layout) {
        int start = getSelectionStart(text);
        int end = getSelectionEnd(text);

        if (start != end) {
            setSelection(text, chooseHorizontal(layout, 1, start, end));
            return true;
        } else {
            int to = TextUtils.indexOf(text, PARAGRAPH_SEPARATOR, end + 1);
            if (to == -1) {
                to = text.length();
            }
            if (to != end) {
                setSelection(text, to);
                return true;
            }
        }
        return false;
    }

    /**
     * Extend the selection to the closest paragraph start offset.
     *
     * @param text the spannable text
     * @return true if the selection is extended, otherwise false
     */
    public static boolean extendToParagraphStart(@NonNull Spannable text) {
        int end = getSelectionEnd(text);
        int to = TextUtils.lastIndexOf(text, PARAGRAPH_SEPARATOR, end - 1);
        if (to == -1) {
            to = 0;  // If not found, use the document start offset as a paragraph start.
        }
        if (to != end) {
            extendSelection(text, to);
            return true;
        }
        return false;
    }

    /**
     * Extend the selection to the closest paragraph end offset.
     *
     * @param text the spannable text
     * @return true if the selection is extended, otherwise false
     */
    public static boolean extendToParagraphEnd(@NonNull Spannable text) {
        int end = getSelectionEnd(text);
        int to = TextUtils.indexOf(text, PARAGRAPH_SEPARATOR, end + 1);
        if (to == -1) {
            to = text.length();
        }
        if (to != end) {
            extendSelection(text, to);
            return true;
        }
        return false;
    }

    /**
     * Move the selection end to the buffer offset physically above
     * the current selection end.
+21 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.text.method;

import android.annotation.NonNull;
import android.graphics.Rect;
import android.text.Layout;
import android.text.Selection;
@@ -221,6 +222,26 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme
        return lineEnd(widget, buffer);
    }

    @Override
    public boolean previousParagraph(@NonNull TextView widget, @NonNull Spannable buffer) {
        final Layout layout = widget.getLayout();
        if (isSelecting(buffer)) {
            return Selection.extendToParagraphStart(buffer);
        } else {
            return Selection.moveToParagraphStart(buffer, layout);
        }
    }

    @Override
    public boolean nextParagraph(@NonNull TextView widget, @NonNull  Spannable buffer) {
        final Layout layout = widget.getLayout();
        if (isSelecting(buffer)) {
            return Selection.extendToParagraphEnd(buffer);
        } else {
            return Selection.moveToParagraphEnd(buffer, layout);
        }
    }

    @Override
    public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
        int initialScrollX = -1;
+29 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.text.method;

import android.annotation.NonNull;
import android.text.Layout;
import android.text.Spannable;
import android.view.InputDevice;
@@ -190,6 +191,9 @@ public class BaseMovementMethod implements MovementMethod {
                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
                        KeyEvent.META_ALT_ON)) {
                    return top(widget, buffer);
                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
                        KeyEvent.META_CTRL_ON)) {
                    return previousParagraph(widget, buffer);
                }
                break;

@@ -199,6 +203,9 @@ public class BaseMovementMethod implements MovementMethod {
                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
                        KeyEvent.META_ALT_ON)) {
                    return bottom(widget, buffer);
                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
                        KeyEvent.META_CTRL_ON)) {
                    return nextParagraph(widget, buffer);
                }
                break;

@@ -399,6 +406,28 @@ public class BaseMovementMethod implements MovementMethod {
        return false;
    }

    /**
     * Performs a previous paragraph movement action.
     *
     * @param widget the text view
     * @param buffer the text buffer
     * @return true if the event was handled, otherwise false.
     */
    public boolean previousParagraph(@NonNull TextView widget, @NonNull Spannable buffer) {
        return false;
    }

    /**
     * Performs a next paragraph movement action.
     *
     * @param widget the text view
     * @param buffer the text buffer
     * @return true if the event was handled, otherwise false.
     */
    public boolean nextParagraph(@NonNull TextView widget, @NonNull Spannable buffer) {
        return false;
    }

    private int getTopLine(TextView widget) {
        return widget.getLayout().getLineForVertical(widget.getScrollY());
    }