Browse Source

Remove timer from undo helper, improve u/r for textbox

pull/6024/head
Deadpikle 5 years ago
parent
commit
ca4dee94fd
  1. 35
      src/Avalonia.Controls/TextBox.cs
  2. 9
      src/Avalonia.Controls/Utils/UndoRedoHelper.cs

35
src/Avalonia.Controls/TextBox.cs

@ -174,6 +174,10 @@ namespace Avalonia.Controls
private string _newLine = Environment.NewLine; private string _newLine = Environment.NewLine;
private static readonly string[] invalidCharacters = new String[1] { "\u007f" }; private static readonly string[] invalidCharacters = new String[1] { "\u007f" };
private int _selectedTextChangesMadeSinceLastUndoSnapshot;
private bool _hasDoneSnapshotOnce;
private const int _maxCharsBeforeUndoSnapshot = 7;
static TextBox() static TextBox()
{ {
FocusableProperty.OverrideDefaultValue(typeof(TextBox), true); FocusableProperty.OverrideDefaultValue(typeof(TextBox), true);
@ -202,7 +206,8 @@ namespace Avalonia.Controls
horizontalScrollBarVisibility, horizontalScrollBarVisibility,
BindingPriority.Style); BindingPriority.Style);
_undoRedoHelper = new UndoRedoHelper<UndoRedoState>(this); _undoRedoHelper = new UndoRedoHelper<UndoRedoState>(this);
_selectedTextChangesMadeSinceLastUndoSnapshot = 0;
_hasDoneSnapshotOnce = false;
UpdatePseudoclasses(); UpdatePseudoclasses();
} }
@ -331,6 +336,7 @@ namespace Avalonia.Controls
if (SetAndRaise(TextProperty, ref _text, value) && IsUndoEnabled && !_isUndoingRedoing) if (SetAndRaise(TextProperty, ref _text, value) && IsUndoEnabled && !_isUndoingRedoing)
{ {
_undoRedoHelper.Clear(); _undoRedoHelper.Clear();
SnapshotUndoRedo(); // so we always have an initial state
} }
} }
} }
@ -341,7 +347,6 @@ namespace Avalonia.Controls
get { return GetSelection(); } get { return GetSelection(); }
set set
{ {
SnapshotUndoRedo();
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{ {
DeleteSelection(); DeleteSelection();
@ -350,7 +355,6 @@ namespace Avalonia.Controls
{ {
HandleTextInput(value); HandleTextInput(value);
} }
SnapshotUndoRedo();
} }
} }
@ -485,6 +489,8 @@ namespace Avalonia.Controls
// https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.textboxbase.isundoenabled: // https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.textboxbase.isundoenabled:
// "Setting UndoLimit clears the undo queue." // "Setting UndoLimit clears the undo queue."
_undoRedoHelper.Clear(); _undoRedoHelper.Clear();
_selectedTextChangesMadeSinceLastUndoSnapshot = 0;
_hasDoneSnapshotOnce = false;
} }
} }
@ -515,6 +521,8 @@ namespace Avalonia.Controls
// Therefore, if you disable undo and then re-enable it, undo commands still do not work // Therefore, if you disable undo and then re-enable it, undo commands still do not work
// because the undo stack was emptied when you disabled undo." // because the undo stack was emptied when you disabled undo."
_undoRedoHelper.Clear(); _undoRedoHelper.Clear();
_selectedTextChangesMadeSinceLastUndoSnapshot = 0;
_hasDoneSnapshotOnce = false;
} }
} }
@ -584,6 +592,8 @@ namespace Avalonia.Controls
{ {
return; return;
} }
_selectedTextChangesMadeSinceLastUndoSnapshot++;
SnapshotUndoRedo(ignoreChangeCount: false);
string text = Text ?? string.Empty; string text = Text ?? string.Empty;
int caretIndex = CaretIndex; int caretIndex = CaretIndex;
@ -696,6 +706,7 @@ namespace Avalonia.Controls
{ {
try try
{ {
SnapshotUndoRedo();
_isUndoingRedoing = true; _isUndoingRedoing = true;
_undoRedoHelper.Undo(); _undoRedoHelper.Undo();
} }
@ -830,7 +841,6 @@ namespace Avalonia.Controls
CaretIndex -= removedCharacters; CaretIndex -= removedCharacters;
ClearSelection(); ClearSelection();
} }
SnapshotUndoRedo();
handled = true; handled = true;
break; break;
@ -858,7 +868,6 @@ namespace Avalonia.Controls
SetTextInternal(text.Substring(0, caretIndex) + SetTextInternal(text.Substring(0, caretIndex) +
text.Substring(caretIndex + removedCharacters)); text.Substring(caretIndex + removedCharacters));
} }
SnapshotUndoRedo();
handled = true; handled = true;
break; break;
@ -868,7 +877,6 @@ namespace Avalonia.Controls
{ {
SnapshotUndoRedo(); SnapshotUndoRedo();
HandleTextInput(NewLine); HandleTextInput(NewLine);
SnapshotUndoRedo();
handled = true; handled = true;
} }
@ -879,7 +887,6 @@ namespace Avalonia.Controls
{ {
SnapshotUndoRedo(); SnapshotUndoRedo();
HandleTextInput("\t"); HandleTextInput("\t");
SnapshotUndoRedo();
handled = true; handled = true;
} }
else else
@ -889,6 +896,10 @@ namespace Avalonia.Controls
break; break;
case Key.Space:
SnapshotUndoRedo(); // always snapshot in between words
break;
default: default:
handled = false; handled = false;
break; break;
@ -1306,11 +1317,19 @@ namespace Avalonia.Controls
} }
} }
private void SnapshotUndoRedo() private void SnapshotUndoRedo(bool ignoreChangeCount = true)
{ {
if (IsUndoEnabled) if (IsUndoEnabled)
{
if (ignoreChangeCount ||
!_hasDoneSnapshotOnce ||
(!ignoreChangeCount &&
_selectedTextChangesMadeSinceLastUndoSnapshot >= _maxCharsBeforeUndoSnapshot))
{ {
_undoRedoHelper.Snapshot(); _undoRedoHelper.Snapshot();
_selectedTextChangesMadeSinceLastUndoSnapshot = 0;
_hasDoneSnapshotOnce = true;
}
} }
} }
} }

9
src/Avalonia.Controls/Utils/UndoRedoHelper.cs

@ -7,7 +7,7 @@ using Avalonia.Utilities;
namespace Avalonia.Controls.Utils namespace Avalonia.Controls.Utils
{ {
class UndoRedoHelper<TState> : WeakTimer.IWeakTimerSubscriber where TState : struct, IEquatable<TState> class UndoRedoHelper<TState>
{ {
private readonly IUndoRedoHost _host; private readonly IUndoRedoHost _host;
@ -31,7 +31,6 @@ namespace Avalonia.Controls.Utils
public UndoRedoHelper(IUndoRedoHost host) public UndoRedoHelper(IUndoRedoHost host)
{ {
_host = host; _host = host;
WeakTimer.StartWeakTimer(this, TimeSpan.FromSeconds(1));
} }
public void Undo() public void Undo()
@ -103,11 +102,5 @@ namespace Avalonia.Controls.Utils
_states.Clear(); _states.Clear();
_currentNode = null; _currentNode = null;
} }
bool WeakTimer.IWeakTimerSubscriber.Tick()
{
Snapshot();
return true;
}
} }
} }

Loading…
Cancel
Save