using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Input;
namespace InkCanvasForClass.IccInkCanvas {
///
/// 时光机代码,基于 Ink Canvas 项目修改
///
public class TimeMachine
{
private readonly List _currentStrokeHistory = new List();
private int _currentIndex = -1;
public delegate void OnUndoRedoStateChanged(TimeMachine timeMachine);
public event OnUndoRedoStateChanged UndoRedoStateChanged;
///
/// 提交历史记录的通用方法
///
/// TimeMachineHistory
private void CommitHistory(TimeMachineHistory history) {
Trace.WriteLine("History Commited");
// 删除当前索引后的所有记录
if (_currentIndex + 1 < _currentStrokeHistory.Count)
_currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
// 添加历史记录
_currentStrokeHistory.Add(history);
_currentIndex = _currentStrokeHistory.Count - 1;
// 通知撤销和重做的状态变化
NotifyUndoRedoState();
}
///
/// 提交由用户绘制的墨迹添加到历史记录
///
///
public void CommitStrokeUserInputHistory(StrokeCollection stroke) {
var history = new TimeMachineHistory(stroke, TimeMachineHistoryType.UserInput, false);
CommitHistory(history);
}
///
/// 提交由墨迹纠正替换的墨迹添加到历史记录
///
///
///
public void CommitStrokeShapeHistory(StrokeCollection strokeToBeReplaced, StrokeCollection generatedStroke) {
var history = new TimeMachineHistory(generatedStroke, TimeMachineHistoryType.ShapeRecognition, false, strokeToBeReplaced);
CommitHistory(history);
}
///
/// 提交墨迹点变更到历史记录,Dictionary中每一项的Key对应一条墨迹的引用,Value为元组,第一个是变化前,第二个变化后
///
///
public void CommitStylusPointsHistory(Dictionary> stylusPointDictionary) {
var history = new TimeMachineHistory(stylusPointDictionary, TimeMachineHistoryType.StylusPoints);
CommitHistory(history);
}
///
/// 提交墨迹的墨迹属性变更到历史记录
///
///
public void CommitStrokeDrawingAttributesHistory(Dictionary> drawingAttributes) {
var history = new TimeMachineHistory(drawingAttributes, TimeMachineHistoryType.DrawingAttributes);
CommitHistory(history);
}
///
/// 提交墨迹擦被擦除的变更到历史记录中
///
///
///
public void CommitStrokeEraseHistory(StrokeCollection stroke, StrokeCollection sourceStroke = null) {
var history = new TimeMachineHistory(stroke, TimeMachineHistoryType.Erased, true, sourceStroke);
CommitHistory(history);
}
///
/// 清空所有历史记录
///
public void ClearHistory()
{
_currentStrokeHistory.Clear();
_currentIndex = -1;
NotifyUndoRedoState();
}
///
/// 撤销
///
///
public TimeMachineHistory Undo(bool doNotNotifyStateUpdate = false) {
if (!(_currentIndex > -1)) return null;
// 如果当前的墨迹是被创建了,就修改为指示被清除
var item = _currentStrokeHistory[_currentIndex];
item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
var index = Math.Min(Math.Max(_currentIndex - 1, -1), _currentStrokeHistory.Count - 1);
_currentIndex = index;
if (!doNotNotifyStateUpdate) NotifyUndoRedoState();
return item;
}
///
/// 撤销,指定步长
///
///
///
public TimeMachineHistory[] Undo(int steps = 1) {
var histories = new List();
for (int i = 0; i < steps; i++) {
var item = Undo(true);
if (item != null) histories.Add(item);
}
NotifyUndoRedoState();
return histories.ToArray();
}
///
/// 重做
///
///
public TimeMachineHistory Redo(bool doNotNotifyStateUpdate = false) {
if (!(_currentStrokeHistory.Count - _currentIndex - 1 > 0)) return null;
var index = Math.Min(Math.Max(_currentIndex + 1, -1), _currentStrokeHistory.Count - 1);
// 如果当前的墨迹是被清除了,就修改为指示已创建
var item = _currentStrokeHistory[index];
item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
_currentIndex = index;
if (!doNotNotifyStateUpdate) NotifyUndoRedoState();
return item;
}
///
/// 重做,指定步长
///
///
///
public TimeMachineHistory[] Redo(int steps = 1) {
var histories = new List();
for (int i = 0; i < steps; i++) {
var item = Redo(true);
if (item != null) histories.Add(item);
}
NotifyUndoRedoState();
return histories.ToArray();
}
public TimeMachineHistory[] ExportTimeMachineHistory()
{
if (_currentIndex + 1 < _currentStrokeHistory.Count)
{
_currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
}
return _currentStrokeHistory.ToArray();
}
public bool ImportTimeMachineHistory(TimeMachineHistory[] sourceHistory)
{
_currentStrokeHistory.Clear();
_currentStrokeHistory.AddRange(sourceHistory);
_currentIndex = _currentStrokeHistory.Count - 1;
NotifyUndoRedoState();
return true;
}
private void NotifyUndoRedoState() {
Application.Current.Dispatcher.InvokeAsync(() => {
UndoRedoStateChanged?.Invoke(this);
});
}
public bool CanUndo => _currentIndex > -1;
public bool CanRedo => _currentStrokeHistory.Count - _currentIndex - 1 > 0;
public int CurrentHistoriesCount => _currentStrokeHistory.Count;
}
public class TimeMachineHistory
{
public TimeMachineHistoryType CommitType;
public bool StrokeHasBeenCleared = false;
public StrokeCollection CurrentStroke;
public StrokeCollection ReplacedStroke;
// Tuple的 Value1 是初始值 ; Value 2 是改变值
public Dictionary> StylusPointsDictionary;
public Dictionary> DrawingAttributes;
public TimeMachineHistory(StrokeCollection currentStroke, TimeMachineHistoryType commitType, bool strokeHasBeenCleared)
{
CommitType = commitType;
CurrentStroke = currentStroke;
StrokeHasBeenCleared = strokeHasBeenCleared;
ReplacedStroke = null;
}
public TimeMachineHistory(Dictionary> stylusPointDictionary, TimeMachineHistoryType commitType)
{
CommitType = commitType;
StylusPointsDictionary = stylusPointDictionary;
}
public TimeMachineHistory(Dictionary> drawingAttributes, TimeMachineHistoryType commitType)
{
CommitType = commitType;
DrawingAttributes = drawingAttributes;
}
public TimeMachineHistory(StrokeCollection currentStroke, TimeMachineHistoryType commitType, bool strokeHasBeenCleared, StrokeCollection replacedStroke)
{
CommitType = commitType;
CurrentStroke = currentStroke;
StrokeHasBeenCleared = strokeHasBeenCleared;
ReplacedStroke = replacedStroke;
}
}
public enum TimeMachineHistoryType
{
UserInput,
ShapeRecognition,
Erased,
StylusPoints,
DrawingAttributes
}
}