Merge "Delete gesture: remove extra whitespace around deleted text"
This commit is contained in:
@@ -93,7 +93,9 @@ public class TextUtils {
|
||||
private static final String ELLIPSIS_NORMAL = "\u2026"; // HORIZONTAL ELLIPSIS (…)
|
||||
private static final String ELLIPSIS_TWO_DOTS = "\u2025"; // TWO DOT LEADER (‥)
|
||||
|
||||
private static final int LINE_FEED_CODE_POINT = 10;
|
||||
/** @hide */
|
||||
public static final int LINE_FEED_CODE_POINT = 10;
|
||||
|
||||
private static final int NBSP_CODE_POINT = 160;
|
||||
|
||||
/**
|
||||
@@ -2335,10 +2337,28 @@ public class TextUtils {
|
||||
|| codePoint == LINE_FEED_CODE_POINT;
|
||||
}
|
||||
|
||||
private static boolean isWhiteSpace(int codePoint) {
|
||||
/** @hide */
|
||||
public static boolean isWhitespace(int codePoint) {
|
||||
return Character.isWhitespace(codePoint) || codePoint == NBSP_CODE_POINT;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static boolean isWhitespaceExceptNewline(int codePoint) {
|
||||
return isWhitespace(codePoint) && !isNewline(codePoint);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static boolean isPunctuation(int codePoint) {
|
||||
int type = Character.getType(codePoint);
|
||||
return type == Character.CONNECTOR_PUNCTUATION
|
||||
|| type == Character.DASH_PUNCTUATION
|
||||
|| type == Character.END_PUNCTUATION
|
||||
|| type == Character.FINAL_QUOTE_PUNCTUATION
|
||||
|| type == Character.INITIAL_QUOTE_PUNCTUATION
|
||||
|| type == Character.OTHER_PUNCTUATION
|
||||
|| type == Character.START_PUNCTUATION;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Nullable
|
||||
public static String withoutPrefix(@Nullable String prefix, @Nullable String str) {
|
||||
@@ -2430,7 +2450,7 @@ public class TextUtils {
|
||||
gettingCleaned.removeRange(offset, offset + codePointLen);
|
||||
} else if (type == Character.CONTROL && !isNewline) {
|
||||
gettingCleaned.removeRange(offset, offset + codePointLen);
|
||||
} else if (trim && !isWhiteSpace(codePoint)) {
|
||||
} else if (trim && !isWhitespace(codePoint)) {
|
||||
// This is only executed if the code point is not removed
|
||||
if (firstNonWhiteSpace == -1) {
|
||||
firstNonWhiteSpace = offset;
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.icu.text.BreakIterator;
|
||||
import android.os.Build;
|
||||
import android.text.CharSequenceCharacterIterator;
|
||||
import android.text.Selection;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -275,9 +276,9 @@ public class WordIterator implements Selection.PositionIterator {
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>offset</code> is within a group of punctuation as defined
|
||||
* by {@link #isPunctuation(int)}, returns the index of the first character
|
||||
* of that group, otherwise returns BreakIterator.DONE.
|
||||
* If <code>offset</code> is within a group of punctuation as defined by {@link
|
||||
* TextUtils#isPunctuation(int)}, returns the index of the first character of that group,
|
||||
* otherwise returns BreakIterator.DONE.
|
||||
*
|
||||
* @param offset the offset to search from.
|
||||
*/
|
||||
@@ -292,9 +293,9 @@ public class WordIterator implements Selection.PositionIterator {
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>offset</code> is within a group of punctuation as defined
|
||||
* by {@link #isPunctuation(int)}, returns the index of the last character
|
||||
* of that group plus one, otherwise returns BreakIterator.DONE.
|
||||
* If <code>offset</code> is within a group of punctuation as defined by {@link
|
||||
* TextUtils#isPunctuation(int)}, returns the index of the last character of that group plus
|
||||
* one, otherwise returns BreakIterator.DONE.
|
||||
*
|
||||
* @param offset the offset to search from.
|
||||
*/
|
||||
@@ -309,8 +310,8 @@ public class WordIterator implements Selection.PositionIterator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the provided offset is after a punctuation character
|
||||
* as defined by {@link #isPunctuation(int)}.
|
||||
* Indicates if the provided offset is after a punctuation character as defined by {@link
|
||||
* TextUtils#isPunctuation(int)}.
|
||||
*
|
||||
* @param offset the offset to check from.
|
||||
* @return Whether the offset is after a punctuation character.
|
||||
@@ -319,14 +320,14 @@ public class WordIterator implements Selection.PositionIterator {
|
||||
public boolean isAfterPunctuation(int offset) {
|
||||
if (mStart < offset && offset <= mEnd) {
|
||||
final int codePoint = Character.codePointBefore(mCharSeq, offset);
|
||||
return isPunctuation(codePoint);
|
||||
return TextUtils.isPunctuation(codePoint);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the provided offset is at a punctuation character
|
||||
* as defined by {@link #isPunctuation(int)}.
|
||||
* Indicates if the provided offset is at a punctuation character as defined by {@link
|
||||
* TextUtils#isPunctuation(int)}.
|
||||
*
|
||||
* @param offset the offset to check from.
|
||||
* @return Whether the offset is at a punctuation character.
|
||||
@@ -335,7 +336,7 @@ public class WordIterator implements Selection.PositionIterator {
|
||||
public boolean isOnPunctuation(int offset) {
|
||||
if (mStart <= offset && offset < mEnd) {
|
||||
final int codePoint = Character.codePointAt(mCharSeq, offset);
|
||||
return isPunctuation(codePoint);
|
||||
return TextUtils.isPunctuation(codePoint);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -369,17 +370,6 @@ public class WordIterator implements Selection.PositionIterator {
|
||||
return !isOnPunctuation(offset) && isAfterPunctuation(offset);
|
||||
}
|
||||
|
||||
private static boolean isPunctuation(int cp) {
|
||||
final int type = Character.getType(cp);
|
||||
return (type == Character.CONNECTOR_PUNCTUATION
|
||||
|| type == Character.DASH_PUNCTUATION
|
||||
|| type == Character.END_PUNCTUATION
|
||||
|| type == Character.FINAL_QUOTE_PUNCTUATION
|
||||
|| type == Character.INITIAL_QUOTE_PUNCTUATION
|
||||
|| type == Character.OTHER_PUNCTUATION
|
||||
|| type == Character.START_PUNCTUATION);
|
||||
}
|
||||
|
||||
private boolean isAfterLetterOrDigit(int offset) {
|
||||
if (mStart < offset && offset <= mEnd) {
|
||||
final int codePoint = Character.codePointBefore(mCharSeq, offset);
|
||||
|
||||
@@ -9330,9 +9330,58 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
if (range == null) {
|
||||
return handleGestureFailure(gesture);
|
||||
}
|
||||
getEditableText().delete(range[0], range[1]);
|
||||
Selection.setSelection(getEditableText(), range[0]);
|
||||
// TODO(b/243983058): Delete extra spaces.
|
||||
int start = range[0];
|
||||
int end = range[1];
|
||||
|
||||
// For word granularity, adjust the start and end offsets to remove extra whitespace around
|
||||
// the deleted text.
|
||||
if (gesture.getGranularity() == HandwritingGesture.GRANULARITY_WORD) {
|
||||
// If the deleted text is at the start of the text, the behavior is the same as the case
|
||||
// where the deleted text follows a new line character.
|
||||
int codePointBeforeStart = start > 0
|
||||
? Character.codePointBefore(mText, start) : TextUtils.LINE_FEED_CODE_POINT;
|
||||
// If the deleted text is at the end of the text, the behavior is the same as the case
|
||||
// where the deleted text precedes a new line character.
|
||||
int codePointAtEnd = end < mText.length()
|
||||
? Character.codePointAt(mText, end) : TextUtils.LINE_FEED_CODE_POINT;
|
||||
if (TextUtils.isWhitespaceExceptNewline(codePointBeforeStart)
|
||||
&& (TextUtils.isWhitespace(codePointAtEnd)
|
||||
|| TextUtils.isPunctuation(codePointAtEnd))) {
|
||||
// Remove whitespace (except new lines) before the deleted text, in these cases:
|
||||
// - There is whitespace following the deleted text
|
||||
// e.g. "one [deleted] three" -> "one | three" -> "one| three"
|
||||
// - There is punctuation following the deleted text
|
||||
// e.g. "one [deleted]!" -> "one |!" -> "one|!"
|
||||
// - There is a new line following the deleted text
|
||||
// e.g. "one [deleted]\n" -> "one |\n" -> "one|\n"
|
||||
// - The deleted text is at the end of the text
|
||||
// e.g. "one [deleted]" -> "one |" -> "one|"
|
||||
// (The pipe | indicates the cursor position.)
|
||||
while (start > 0 && TextUtils.isWhitespaceExceptNewline(codePointBeforeStart)) {
|
||||
start -= Character.charCount(codePointBeforeStart);
|
||||
codePointBeforeStart = Character.codePointBefore(mText, start);
|
||||
}
|
||||
} else if (TextUtils.isWhitespaceExceptNewline(codePointAtEnd)
|
||||
&& (TextUtils.isWhitespace(codePointBeforeStart)
|
||||
|| TextUtils.isPunctuation(codePointBeforeStart))) {
|
||||
// Remove whitespace (except new lines) after the deleted text, in these cases:
|
||||
// - There is punctuation preceding the deleted text
|
||||
// e.g. "([deleted] two)" -> "(| two)" -> "(|two)"
|
||||
// - There is a new line preceding the deleted text
|
||||
// e.g. "\n[deleted] two" -> "\n| two" -> "\n|two"
|
||||
// - The deleted text is at the start of the text
|
||||
// e.g. "[deleted] two" -> "| two" -> "|two"
|
||||
// (The pipe | indicates the cursor position.)
|
||||
while (end < mText.length()
|
||||
&& TextUtils.isWhitespaceExceptNewline(codePointAtEnd)) {
|
||||
end += Character.charCount(codePointAtEnd);
|
||||
codePointAtEnd = Character.codePointAt(mText, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getEditableText().delete(start, end);
|
||||
Selection.setSelection(getEditableText(), start);
|
||||
return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user