|
|
@ -8,20 +8,19 @@ using Avalonia.Utilities; |
|
|
|
|
|
|
|
|
namespace Avalonia.Controls.Utils |
|
|
namespace Avalonia.Controls.Utils |
|
|
{ |
|
|
{ |
|
|
class UndoRedoHelper<TState> : WeakTimer.IWeakTimerSubscriber where TState : IEquatable<TState> |
|
|
class UndoRedoHelper<TState> : WeakTimer.IWeakTimerSubscriber where TState : struct, IEquatable<TState> |
|
|
{ |
|
|
{ |
|
|
private readonly IUndoRedoHost _host; |
|
|
private readonly IUndoRedoHost _host; |
|
|
|
|
|
|
|
|
public interface IUndoRedoHost |
|
|
public interface IUndoRedoHost |
|
|
{ |
|
|
{ |
|
|
TState UndoRedoState { get; set; } |
|
|
TState UndoRedoState { get; set; } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private readonly LinkedList<TState> _states = new LinkedList<TState>(); |
|
|
private readonly LinkedList<TState> _states = new LinkedList<TState>(); |
|
|
|
|
|
|
|
|
[NotNull] |
|
|
|
|
|
private LinkedListNode<TState> _currentNode; |
|
|
private LinkedListNode<TState> _currentNode; |
|
|
|
|
|
|
|
|
public int Limit { get; set; } = 10; |
|
|
public int Limit { get; set; } = 10; |
|
|
@ -29,24 +28,31 @@ namespace Avalonia.Controls.Utils |
|
|
public UndoRedoHelper(IUndoRedoHost host) |
|
|
public UndoRedoHelper(IUndoRedoHost host) |
|
|
{ |
|
|
{ |
|
|
_host = host; |
|
|
_host = host; |
|
|
_states.AddFirst(_host.UndoRedoState); |
|
|
WeakTimer.StartWeakTimer(this, TimeSpan.FromSeconds(1)); |
|
|
_currentNode = _states.First; |
|
|
|
|
|
WeakTimer.StartWeakTimer(this, new TimeSpan(0, 0, 1)); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void Undo() |
|
|
public void Undo() |
|
|
{ |
|
|
{ |
|
|
if (_currentNode?.Previous != null) |
|
|
if (_currentNode?.Previous != null) |
|
|
{ |
|
|
{ |
|
|
_currentNode = _currentNode.Previous; |
|
|
_currentNode = _currentNode.Previous; |
|
|
} |
|
|
_host.UndoRedoState = _currentNode.Value; |
|
|
|
|
|
} |
|
|
_host.UndoRedoState = _currentNode.Value; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public bool IsLastState => _currentNode.Next == null; |
|
|
public bool IsLastState => _currentNode != null && _currentNode.Next == null; |
|
|
|
|
|
|
|
|
|
|
|
public bool TryGetLastState(out TState _state) |
|
|
|
|
|
{ |
|
|
|
|
|
_state = default(TState); |
|
|
|
|
|
if (!IsLastState) |
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
_state = _currentNode.Value; |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public bool HasState => _currentNode != null; |
|
|
public void UpdateLastState(TState state) |
|
|
public void UpdateLastState(TState state) |
|
|
{ |
|
|
{ |
|
|
_states.Last.Value = state; |
|
|
_states.Last.Value = state; |
|
|
@ -57,34 +63,31 @@ namespace Avalonia.Controls.Utils |
|
|
_states.Last.Value = _host.UndoRedoState; |
|
|
_states.Last.Value = _host.UndoRedoState; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public TState LastState => _currentNode.Value; |
|
|
|
|
|
|
|
|
|
|
|
public void DiscardRedo() |
|
|
public void DiscardRedo() |
|
|
{ |
|
|
{ |
|
|
//Linked list sucks, so we are doing this
|
|
|
while (_currentNode?.Next != null) |
|
|
while (_currentNode.Next != null) |
|
|
|
|
|
_states.Remove(_currentNode.Next); |
|
|
_states.Remove(_currentNode.Next); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void Redo() |
|
|
public void Redo() |
|
|
{ |
|
|
{ |
|
|
if (_currentNode?.Next != null) { |
|
|
if (_currentNode?.Next != null) |
|
|
_currentNode = _currentNode.Next; |
|
|
{ |
|
|
} |
|
|
_currentNode = _currentNode.Next; |
|
|
|
|
|
_host.UndoRedoState = _currentNode.Value; |
|
|
_host.UndoRedoState = _currentNode.Value; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void Snapshot() |
|
|
public void Snapshot() |
|
|
{ |
|
|
{ |
|
|
var current = _host.UndoRedoState; |
|
|
var current = _host.UndoRedoState; |
|
|
if (!_currentNode.Value.Equals(current)) |
|
|
if (_currentNode == null || !_currentNode.Value.Equals(current)) |
|
|
{ |
|
|
{ |
|
|
if(_currentNode.Next != null) |
|
|
if (_currentNode?.Next != null) |
|
|
DiscardRedo(); |
|
|
DiscardRedo(); |
|
|
_states.AddLast(current); |
|
|
_states.AddLast(current); |
|
|
_currentNode = _states.Last; |
|
|
_currentNode = _states.Last; |
|
|
if(_states.Count > Limit) |
|
|
if (_states.Count > Limit) |
|
|
_states.RemoveFirst(); |
|
|
_states.RemoveFirst(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|