summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Keisuke Kuroyanagi <ksk@google.com> 2016-02-24 18:53:00 -0800
committer Keisuke Kuroyanagi <ksk@google.com> 2016-03-09 06:07:01 +0000
commitfae4578311970afadca8ee28a47e1e11df00eedd (patch)
tree7f9f01de9fa7e65b6e984cf41305921fd486e541
parentf52ebd119e76187366e9f9d0f388fbdef46a33c8 (diff)
Make drag&drop be atomic for undo/redo.
For undo/redo, drag&drop is recorded as a 2 operations, paste and delete. This CL makes drag&drop be atomic operation to be properly undoed/redoed. Bug: 27268820 Change-Id: Ia38d663f046c2c65f348985934f5cfa054b0437e
-rw-r--r--core/java/android/widget/Editor.java36
-rw-r--r--core/tests/coretests/src/android/widget/TextViewActivityTest.java7
2 files changed, 31 insertions, 12 deletions
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 406dc2b2baa9..69591371aa35 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2395,17 +2395,22 @@ public class Editor {
dragSourceEnd += shift;
}
- // Delete original selection
- mTextView.deleteText_internal(dragSourceStart, dragSourceEnd);
-
- // Make sure we do not leave two adjacent spaces.
- final int prevCharIdx = Math.max(0, dragSourceStart - 1);
- final int nextCharIdx = Math.min(mTextView.getText().length(), dragSourceStart + 1);
- if (nextCharIdx > prevCharIdx + 1) {
- CharSequence t = mTextView.getTransformedText(prevCharIdx, nextCharIdx);
- if (Character.isSpaceChar(t.charAt(0)) && Character.isSpaceChar(t.charAt(1))) {
- mTextView.deleteText_internal(prevCharIdx, prevCharIdx + 1);
+ mUndoInputFilter.setForceMerge(true);
+ try {
+ // Delete original selection
+ mTextView.deleteText_internal(dragSourceStart, dragSourceEnd);
+
+ // Make sure we do not leave two adjacent spaces.
+ final int prevCharIdx = Math.max(0, dragSourceStart - 1);
+ final int nextCharIdx = Math.min(mTextView.getText().length(), dragSourceStart + 1);
+ if (nextCharIdx > prevCharIdx + 1) {
+ CharSequence t = mTextView.getTransformedText(prevCharIdx, nextCharIdx);
+ if (Character.isSpaceChar(t.charAt(0)) && Character.isSpaceChar(t.charAt(1))) {
+ mTextView.deleteText_internal(prevCharIdx, prevCharIdx + 1);
+ }
}
+ } finally {
+ mUndoInputFilter.setForceMerge(false);
}
}
}
@@ -5497,6 +5502,9 @@ public class Editor {
// rotates the screen during composition.
private boolean mHasComposition;
+ // Whether to merge events into one operation.
+ private boolean mForceMerge;
+
public UndoInputFilter(Editor editor) {
mEditor = editor;
}
@@ -5511,6 +5519,10 @@ public class Editor {
mHasComposition = parcel.readInt() != 0;
}
+ public void setForceMerge(boolean forceMerge) {
+ mForceMerge = forceMerge;
+ }
+
/**
* Signals that a user-triggered edit is starting.
*/
@@ -5570,7 +5582,7 @@ public class Editor {
// Otherwise the user inserted the composition.
String newText = TextUtils.substring(source, start, end);
EditOperation edit = new EditOperation(mEditor, "", dstart, newText);
- recordEdit(edit, false /* forceMerge */);
+ recordEdit(edit, mForceMerge);
return true;
}
@@ -5584,7 +5596,7 @@ public class Editor {
// the initial input filters run (e.g. a credit card formatter that adds spaces to a
// string). This results in multiple filter() calls for what the user considers to be
// a single operation. Always undo the whole set of changes in one step.
- final boolean forceMerge = isInTextWatcher();
+ final boolean forceMerge = mForceMerge || isInTextWatcher();
// Build a new operation with all the information from this edit.
String newText = TextUtils.substring(source, start, end);
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 5dae4a878bf4..844eadbae692 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -44,6 +44,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText;
import com.android.frameworks.coretests.R;
+import android.support.test.espresso.action.EspressoKey;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.KeyEvent;
@@ -172,6 +173,12 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
onView(withId(R.id.textview)).check(hasSelection(""));
assertNoSelectionHandles();
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length()));
+
+ // Test undo returns to the original state.
+ onView(withId(R.id.textview)).perform(pressKey(
+ (new EspressoKey.Builder()).withCtrlPressed(true).withKeyCode(KeyEvent.KEYCODE_Z)
+ .build()));
+ onView(withId(R.id.textview)).check(matches(withText(text)));
}
@SmallTest