summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorGilles Debunne <debunne@google.com>2010-08-27 11:39:34 -0700
committerGilles Debunne <debunne@google.com>2010-09-08 09:43:46 -0700
commit468394fc6d1cb0c9078c2f98aa056860f7e0d743 (patch)
tree95a9140c4e9c30fe1221071dd9f45ff51a47cfc3 /core
parent4c7d3f28898f4e0d8e9f54537fb92948e650df7f (diff)
downloadframeworks_base-468394fc6d1cb0c9078c2f98aa056860f7e0d743.zip
frameworks_base-468394fc6d1cb0c9078c2f98aa056860f7e0d743.tar.gz
frameworks_base-468394fc6d1cb0c9078c2f98aa056860f7e0d743.tar.bz2
Text Selection: smart word detection. DO NOT MERGE.
Selecting between words selects the spaces instead of the closest word, facilitating paste insertion vs word replacement. Pasting adds/removes space before and after if needed so that pasted text is not appended to existing text. Cut and copy not available when selection is empty. Change-Id: I331413bdef341a4eceffe76fa2957f388d540b6e
Diffstat (limited to 'core')
-rw-r--r--core/java/android/widget/TextView.java98
1 files changed, 87 insertions, 11 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d0dd6cc..3428206 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5817,7 +5817,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* Return true iff there is a selection inside this text view.
*/
public boolean hasSelection() {
- return getSelectionStart() != getSelectionEnd();
+ final int selectionStart = getSelectionStart();
+ final int selectionEnd = getSelectionEnd();
+
+ return selectionStart >= 0 && selectionStart != selectionEnd;
}
/**
@@ -7005,7 +7008,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
- if (mText.length() > 0 && getSelectionStart() >= 0) {
+ if (mText.length() > 0 && hasSelection()) {
if (mText instanceof Editable && mInput != null) {
return true;
}
@@ -7019,7 +7022,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
- if (mText.length() > 0 && getSelectionStart() >= 0) {
+ if (mText.length() > 0 && hasSelection()) {
return true;
}
@@ -7140,6 +7143,49 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int minOffset = selectionModifierCursorController.getMinTouchOffset();
int maxOffset = selectionModifierCursorController.getMaxTouchOffset();
+ if (minOffset == maxOffset) {
+ int offset = Math.max(0, Math.min(minOffset, mTransformed.length()));
+
+ // Tolerance, number of charaters around tapped position
+ final int range = 1;
+ final int max = mTransformed.length() - 1;
+
+ // 'Smart' word selection: detect position between words
+ for (int i = -range; i <= range; i++) {
+ int index = offset + i;
+ if (index >= 0 && index <= max) {
+ if (Character.isSpaceChar(mTransformed.charAt(index))) {
+ // Select current space
+ selectionStart = index;
+ selectionEnd = selectionStart + 1;
+
+ // Extend selection to maximum space range
+ while (selectionStart > 0 &&
+ Character.isSpaceChar(mTransformed.charAt(selectionStart - 1))) {
+ selectionStart--;
+ }
+ while (selectionEnd < max &&
+ Character.isSpaceChar(mTransformed.charAt(selectionEnd))) {
+ selectionEnd++;
+ }
+
+ Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
+ return;
+ }
+ }
+ }
+
+ // 'Smart' word selection: detect position at beginning or end of text.
+ if (offset <= range) {
+ Selection.setSelection((Spannable) mText, 0, 0);
+ return;
+ }
+ if (offset >= (max - range)) {
+ Selection.setSelection((Spannable) mText, max + 1, max + 1);
+ return;
+ }
+ }
+
long wordLimits = getWordLimitsAt(minOffset);
if (wordLimits >= 0) {
selectionStart = (int) (wordLimits >>> 32);
@@ -7220,21 +7266,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
menu.add(0, ID_CUT, 0, com.android.internal.R.string.cut).
setOnMenuItemClickListener(handler).
setAlphabeticShortcut('x');
+ added = true;
}
if (canCopy()) {
menu.add(0, ID_COPY, 0, com.android.internal.R.string.copy).
setOnMenuItemClickListener(handler).
setAlphabeticShortcut('c');
+ added = true;
}
if (canPaste()) {
menu.add(0, ID_PASTE, 0, com.android.internal.R.string.paste).
setOnMenuItemClickListener(handler).
setAlphabeticShortcut('v');
+ added = true;
}
-
- added = true;
} else {
/*
if (!isFocused()) {
@@ -7313,11 +7360,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private boolean textIsOnlySpaces() {
final int length = mTransformed.length();
- for (int i=0; i<length; i++) {
- final char c = mTransformed.charAt(i);
- final int type = Character.getType(c);
- if (type != Character.SPACE_SEPARATOR)
+ for (int i = 0; i < length; i++) {
+ if (!Character.isSpaceChar(mTransformed.charAt(i))) {
return false;
+ }
}
return true;
}
@@ -7350,7 +7396,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Called when a context menu option for the text view is selected. Currently
* this will be one of: {@link android.R.id#selectAll},
- * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
+ * {@link android.R.id#startSelectingText},
* {@link android.R.id#cut}, {@link android.R.id#copy},
* {@link android.R.id#paste}, {@link android.R.id#copyUrl},
* or {@link android.R.id#switchInputMethod}.
@@ -7394,7 +7440,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case ID_PASTE:
CharSequence paste = clip.getText();
- if (paste != null) {
+ if (paste != null && paste.length() > 0) {
+ // Paste adds/removes spaces before or after insertion as needed.
+
+ if (Character.isSpaceChar(paste.charAt(0))) {
+ if (min > 0 && Character.isSpaceChar(mTransformed.charAt(min - 1))) {
+ // Two spaces at beginning of paste: remove one
+ ((Editable) mText).replace(min - 1, min, "");
+ min = min - 1;
+ max = max - 1;
+ }
+ } else {
+ if (min > 0 && !Character.isSpaceChar(mTransformed.charAt(min - 1))) {
+ // No space at beginning of paste: add one
+ ((Editable) mText).replace(min, min, " ");
+ min = min + 1;
+ max = max + 1;
+ }
+ }
+
+ if (Character.isSpaceChar(paste.charAt(paste.length() - 1))) {
+ if (max < mText.length() && Character.isSpaceChar(mTransformed.charAt(max))) {
+ // Two spaces at end of paste: remove one
+ ((Editable) mText).replace(max, max + 1, "");
+ }
+ } else {
+ if (max < mText.length() && !Character.isSpaceChar(mTransformed.charAt(max))) {
+ // No space at end of paste: add one
+ ((Editable) mText).replace(max, max, " ");
+ }
+ }
+
Selection.setSelection((Spannable) mText, max);
((Editable) mText).replace(min, max, paste);
stopTextSelectionMode();