diff options
| author | 2016-02-24 18:53:00 -0800 | |
|---|---|---|
| committer | 2016-03-09 06:07:01 +0000 | |
| commit | fae4578311970afadca8ee28a47e1e11df00eedd (patch) | |
| tree | 7f9f01de9fa7e65b6e984cf41305921fd486e541 | |
| parent | f52ebd119e76187366e9f9d0f388fbdef46a33c8 (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.java | 36 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/widget/TextViewActivityTest.java | 7 |
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 |