From 99e5625ca63810a9a81710772136244b66b9eed7 Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Mon, 6 Apr 2020 17:34:56 -0400 Subject: [PATCH 1/4] Add failing test for cut not working with undo/redo --- .../TextBoxTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 6bb3d55799..557c3920cc 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -554,6 +554,28 @@ namespace Avalonia.Controls.UnitTests } } + + [Fact] + public void Cut_Allows_Undo() + { + using (UnitTestApplication.Start(Services)) + { + var target = new TextBox + { + Template = CreateTemplate(), + Text = "0123" + }; + target.SelectionStart = 1; + target.SelectionEnd = 3; + + RaiseKeyEvent(target, Key.X, KeyModifiers.Control); // cut + Assert.True(target.Text == "03"); + + RaiseKeyEvent(target, Key.Z, KeyModifiers.Control); // undo + Assert.True(target.Text == "0123"); + } + } + private static TestServices FocusServices => TestServices.MockThreadingInterface.With( focusManager: new FocusManager(), keyboardDevice: () => new KeyboardDevice(), From d8f74b7e41737f0fe703f5f2f8e3d9d861f48d6f Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Mon, 6 Apr 2020 17:48:12 -0400 Subject: [PATCH 2/4] Cut now triggers an undo --- src/Avalonia.Controls/TextBox.cs | 2 ++ tests/Avalonia.Controls.UnitTests/TextBoxTests.cs | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 680d7e7d2b..02e34675fe 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -473,8 +473,10 @@ namespace Avalonia.Controls { if (!IsPasswordBox) { + _undoRedoHelper.Snapshot(); Copy(); DeleteSelection(); + _undoRedoHelper.Snapshot(); } handled = true; diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 557c3920cc..362ef53461 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -1,10 +1,12 @@ using System; using System.Reactive.Linq; +using System.Threading.Tasks; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Input; +using Avalonia.Input.Platform; using Avalonia.Media; using Avalonia.Platform; using Avalonia.UnitTests; @@ -567,6 +569,8 @@ namespace Avalonia.Controls.UnitTests }; target.SelectionStart = 1; target.SelectionEnd = 3; + AvaloniaLocator.CurrentMutable + .Bind().ToSingleton(); RaiseKeyEvent(target, Key.X, KeyModifiers.Control); // cut Assert.True(target.Text == "03"); @@ -638,5 +642,14 @@ namespace Avalonia.Controls.UnitTests set { _bar = value; RaisePropertyChanged(); } } } + + private class ClipboardStub : IClipboard // in order to get tests working that use the clipboard + { + public Task GetTextAsync() => Task.FromResult(""); + + public Task SetTextAsync(string text) => Task.CompletedTask; + + public Task ClearAsync() => Task.CompletedTask; + } } } From 3885a69ab156b42edaf409af4b1b9205cad9405d Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Mon, 6 Apr 2020 18:03:35 -0400 Subject: [PATCH 3/4] Add more failing tests for other keys --- .../TextBoxTests.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 362ef53461..d2f62cde04 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -556,25 +556,29 @@ namespace Avalonia.Controls.UnitTests } } - - [Fact] - public void Cut_Allows_Undo() + [Theory] + [InlineData(Key.X, KeyModifiers.Control)] + [InlineData(Key.Back, KeyModifiers.None)] + [InlineData(Key.Delete, KeyModifiers.None)] + [InlineData(Key.Tab, KeyModifiers.None)] + [InlineData(Key.Enter, KeyModifiers.None)] + public void Keys_Allow_Undo(Key key, KeyModifiers modifiers) { using (UnitTestApplication.Start(Services)) { var target = new TextBox { Template = CreateTemplate(), - Text = "0123" + Text = "0123", + AcceptsReturn = true, + AcceptsTab = true }; target.SelectionStart = 1; target.SelectionEnd = 3; AvaloniaLocator.CurrentMutable .Bind().ToSingleton(); - RaiseKeyEvent(target, Key.X, KeyModifiers.Control); // cut - Assert.True(target.Text == "03"); - + RaiseKeyEvent(target, key, modifiers); RaiseKeyEvent(target, Key.Z, KeyModifiers.Control); // undo Assert.True(target.Text == "0123"); } From 9463e278a545eeb9c213b086565c0da370dbbef1 Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Mon, 6 Apr 2020 18:03:54 -0400 Subject: [PATCH 4/4] Fix undo not available for multiple key types --- src/Avalonia.Controls/TextBox.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 02e34675fe..06624c555f 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -602,6 +602,7 @@ namespace Avalonia.Controls break; case Key.Back: + _undoRedoHelper.Snapshot(); if (hasWholeWordModifiers && SelectionStart == SelectionEnd) { SetSelectionForControlBackspace(); @@ -625,11 +626,13 @@ namespace Avalonia.Controls CaretIndex -= removedCharacters; SelectionStart = SelectionEnd = CaretIndex; } + _undoRedoHelper.Snapshot(); handled = true; break; case Key.Delete: + _undoRedoHelper.Snapshot(); if (hasWholeWordModifiers && SelectionStart == SelectionEnd) { SetSelectionForControlDelete(); @@ -651,6 +654,7 @@ namespace Avalonia.Controls SetTextInternal(text.Substring(0, caretIndex) + text.Substring(caretIndex + removedCharacters)); } + _undoRedoHelper.Snapshot(); handled = true; break; @@ -658,7 +662,9 @@ namespace Avalonia.Controls case Key.Enter: if (AcceptsReturn) { + _undoRedoHelper.Snapshot(); HandleTextInput(NewLine); + _undoRedoHelper.Snapshot(); handled = true; } @@ -667,7 +673,9 @@ namespace Avalonia.Controls case Key.Tab: if (AcceptsTab) { + _undoRedoHelper.Snapshot(); HandleTextInput("\t"); + _undoRedoHelper.Snapshot(); handled = true; } else