2023-04-15 19:07:01 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Windows.Ink;
|
|
|
|
|
|
|
|
|
|
namespace Ink_Canvas.Helpers
|
|
|
|
|
{
|
|
|
|
|
public class TimeMachine
|
|
|
|
|
{
|
|
|
|
|
private readonly List<TimeMachineHistory> _currentStrokeHistory = new List<TimeMachineHistory>();
|
2023-04-21 20:44:01 +08:00
|
|
|
|
|
2023-04-15 19:07:01 +08:00
|
|
|
|
private int _currentIndex = -1;
|
2023-04-21 20:44:01 +08:00
|
|
|
|
|
2023-04-15 19:07:01 +08:00
|
|
|
|
public delegate void OnUndoStateChange(bool status);
|
2023-04-21 20:44:01 +08:00
|
|
|
|
|
2023-04-15 19:07:01 +08:00
|
|
|
|
public event OnUndoStateChange OnUndoStateChanged;
|
|
|
|
|
|
|
|
|
|
public delegate void OnRedoStateChange(bool status);
|
2023-04-21 20:44:01 +08:00
|
|
|
|
|
2023-04-15 19:07:01 +08:00
|
|
|
|
public event OnRedoStateChange OnRedoStateChanged;
|
2023-04-21 20:44:01 +08:00
|
|
|
|
|
2023-04-15 19:07:01 +08:00
|
|
|
|
public void CommitStrokeUserInputHistory(StrokeCollection stroke)
|
|
|
|
|
{
|
2023-04-16 15:27:07 +08:00
|
|
|
|
if (_currentIndex + 1 < _currentStrokeHistory.Count)
|
|
|
|
|
{
|
2023-04-21 20:44:01 +08:00
|
|
|
|
_currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
|
2023-04-16 15:27:07 +08:00
|
|
|
|
}
|
2023-04-15 19:07:01 +08:00
|
|
|
|
_currentStrokeHistory.Add(new TimeMachineHistory(stroke, TimeMachineHistoryType.UserInput, false));
|
|
|
|
|
_currentIndex = _currentStrokeHistory.Count - 1;
|
2023-04-22 10:50:50 +08:00
|
|
|
|
NotifyUndoRedoState();
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
2023-04-21 20:44:01 +08:00
|
|
|
|
|
2023-04-15 19:07:01 +08:00
|
|
|
|
public void CommitStrokeShapeHistory(StrokeCollection strokeToBeReplaced, StrokeCollection generatedStroke)
|
|
|
|
|
{
|
2023-04-16 15:27:07 +08:00
|
|
|
|
if (_currentIndex + 1 < _currentStrokeHistory.Count)
|
|
|
|
|
{
|
2023-04-21 20:44:01 +08:00
|
|
|
|
_currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
|
2023-04-16 15:27:07 +08:00
|
|
|
|
}
|
2023-04-15 19:07:01 +08:00
|
|
|
|
_currentStrokeHistory.Add(new TimeMachineHistory(generatedStroke,
|
|
|
|
|
TimeMachineHistoryType.ShapeRecognition,
|
|
|
|
|
false,
|
|
|
|
|
strokeToBeReplaced));
|
|
|
|
|
_currentIndex = _currentStrokeHistory.Count - 1;
|
2023-04-22 10:50:50 +08:00
|
|
|
|
NotifyUndoRedoState();
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-04-21 20:44:01 +08:00
|
|
|
|
public void CommitStrokeEraseHistory(StrokeCollection stroke, StrokeCollection sourceStroke = null)
|
2023-04-15 19:07:01 +08:00
|
|
|
|
{
|
2023-04-16 15:27:07 +08:00
|
|
|
|
if (_currentIndex + 1 < _currentStrokeHistory.Count)
|
|
|
|
|
{
|
2023-04-21 20:44:01 +08:00
|
|
|
|
_currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
|
2023-04-16 15:27:07 +08:00
|
|
|
|
}
|
2023-04-21 20:44:01 +08:00
|
|
|
|
_currentStrokeHistory.Add(new TimeMachineHistory(stroke, TimeMachineHistoryType.Clear, true, sourceStroke));
|
2023-04-15 19:07:01 +08:00
|
|
|
|
_currentIndex = _currentStrokeHistory.Count - 1;
|
2023-04-22 10:50:50 +08:00
|
|
|
|
NotifyUndoRedoState();
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ClearStrokeHistory()
|
|
|
|
|
{
|
|
|
|
|
_currentStrokeHistory.Clear();
|
|
|
|
|
_currentIndex = -1;
|
2023-04-22 10:50:50 +08:00
|
|
|
|
NotifyUndoRedoState();
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
|
|
|
|
public TimeMachineHistory Undo()
|
|
|
|
|
{
|
|
|
|
|
var item = _currentStrokeHistory[_currentIndex];
|
2023-04-19 22:34:49 +08:00
|
|
|
|
item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
|
2023-04-15 19:07:01 +08:00
|
|
|
|
_currentIndex--;
|
|
|
|
|
OnUndoStateChanged?.Invoke(_currentIndex > -1);
|
|
|
|
|
OnRedoStateChanged?.Invoke(_currentStrokeHistory.Count - _currentIndex - 1 > 0);
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TimeMachineHistory Redo()
|
|
|
|
|
{
|
|
|
|
|
var item = _currentStrokeHistory[++_currentIndex];
|
2023-04-19 22:34:49 +08:00
|
|
|
|
item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
|
2023-04-22 10:50:50 +08:00
|
|
|
|
NotifyUndoRedoState();
|
2023-04-15 19:07:01 +08:00
|
|
|
|
return item;
|
|
|
|
|
}
|
2023-04-16 15:27:07 +08:00
|
|
|
|
public TimeMachineHistory[] ExportTimeMachineHistory()
|
2023-04-15 19:07:01 +08:00
|
|
|
|
{
|
2023-04-16 15:27:07 +08:00
|
|
|
|
if (_currentIndex + 1 < _currentStrokeHistory.Count)
|
|
|
|
|
{
|
2023-04-21 20:44:01 +08:00
|
|
|
|
_currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
|
2023-04-16 15:27:07 +08:00
|
|
|
|
}
|
|
|
|
|
return _currentStrokeHistory.ToArray();
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
2023-04-16 15:27:07 +08:00
|
|
|
|
|
|
|
|
|
public bool ImportTimeMachineHistory(TimeMachineHistory[] sourceHistory)
|
2023-04-15 19:07:01 +08:00
|
|
|
|
{
|
2023-04-16 15:27:07 +08:00
|
|
|
|
_currentStrokeHistory.Clear();
|
|
|
|
|
_currentStrokeHistory.AddRange(sourceHistory);
|
|
|
|
|
_currentIndex = _currentStrokeHistory.Count - 1;
|
2023-04-22 10:50:50 +08:00
|
|
|
|
NotifyUndoRedoState();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
private void NotifyUndoRedoState()
|
|
|
|
|
{
|
2023-04-16 15:27:07 +08:00
|
|
|
|
OnUndoStateChanged?.Invoke(_currentIndex > -1);
|
|
|
|
|
OnRedoStateChanged?.Invoke(_currentStrokeHistory.Count - _currentIndex - 1 > 0);
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class TimeMachineHistory
|
|
|
|
|
{
|
|
|
|
|
public TimeMachineHistoryType CommitType;
|
2023-04-19 22:34:49 +08:00
|
|
|
|
public bool StrokeHasBeenCleared;
|
2023-04-15 19:07:01 +08:00
|
|
|
|
public StrokeCollection CurrentStroke;
|
2023-04-19 22:34:49 +08:00
|
|
|
|
public StrokeCollection ReplacedStroke;
|
|
|
|
|
public TimeMachineHistory(StrokeCollection currentStroke, TimeMachineHistoryType commitType, bool strokeHasBeenCleared)
|
2023-04-15 19:07:01 +08:00
|
|
|
|
{
|
|
|
|
|
CommitType = commitType;
|
|
|
|
|
CurrentStroke = currentStroke;
|
2023-04-19 22:34:49 +08:00
|
|
|
|
StrokeHasBeenCleared = strokeHasBeenCleared;
|
|
|
|
|
ReplacedStroke = null;
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
2023-04-21 20:44:01 +08:00
|
|
|
|
public TimeMachineHistory(StrokeCollection currentStroke, TimeMachineHistoryType commitType, bool strokeHasBeenCleared, StrokeCollection replacedStroke)
|
2023-04-15 19:07:01 +08:00
|
|
|
|
{
|
|
|
|
|
CommitType = commitType;
|
|
|
|
|
CurrentStroke = currentStroke;
|
2023-04-19 22:34:49 +08:00
|
|
|
|
StrokeHasBeenCleared = strokeHasBeenCleared;
|
|
|
|
|
ReplacedStroke = replacedStroke;
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum TimeMachineHistoryType
|
|
|
|
|
{
|
|
|
|
|
UserInput,
|
2023-04-16 00:08:52 +08:00
|
|
|
|
ShapeRecognition,
|
|
|
|
|
Clear
|
2023-04-15 19:07:01 +08:00
|
|
|
|
}
|
|
|
|
|
}
|