199 lines
4.9 KiB
C#
199 lines
4.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
|
|
namespace CPF.ReoGrid.Common
|
|
{
|
|
internal sealed class ActionManager
|
|
{
|
|
public List<IUndoableAction> UndoStack
|
|
{
|
|
get
|
|
{
|
|
return this.undoStack;
|
|
}
|
|
}
|
|
|
|
public Stack<IUndoableAction> RedoStack
|
|
{
|
|
get
|
|
{
|
|
return this.redoStack;
|
|
}
|
|
}
|
|
|
|
public void DoAction(IAction action)
|
|
{
|
|
this.DoAction(action, true);
|
|
}
|
|
|
|
public void AddAction(IAction action)
|
|
{
|
|
this.DoAction(action, false);
|
|
}
|
|
|
|
private void DoAction(IAction action, bool perform)
|
|
{
|
|
this.Do(action, perform, action is IUndoableAction);
|
|
}
|
|
|
|
private void Do(IAction action, bool perform, bool isCanUndo)
|
|
{
|
|
Logger.Log(ActionManager.LOGKEY, string.Format("{0} action: {1}[{2}]", perform ? "do" : "add", action.GetType().Name, action.GetName()));
|
|
bool flag = this.BeforePerformAction != null;
|
|
if (flag)
|
|
{
|
|
ActionEventArgs actionEventArgs = new ActionEventArgs(action, ActionBehavior.Do);
|
|
this.BeforePerformAction(this, actionEventArgs);
|
|
bool cancel = actionEventArgs.Cancel;
|
|
if (cancel)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
if (perform)
|
|
{
|
|
action.Do();
|
|
}
|
|
bool flag2 = action is IUndoableAction && isCanUndo;
|
|
if (flag2)
|
|
{
|
|
this.redoStack.Clear();
|
|
this.undoStack.Add(action as IUndoableAction);
|
|
bool flag3 = this.undoStack.Count<IUndoableAction>() > this.capacity;
|
|
if (flag3)
|
|
{
|
|
int count = this.undoStack.Count<IUndoableAction>() - this.capacity;
|
|
this.undoStack.RemoveRange(0, count);
|
|
Logger.Log(ActionManager.LOGKEY, "action stack full. remove " + count.ToString() + " action(s).");
|
|
}
|
|
}
|
|
EventHandler<ActionEventArgs> afterPerformAction = this.AfterPerformAction;
|
|
if (afterPerformAction != null)
|
|
{
|
|
afterPerformAction(this, new ActionEventArgs(action, ActionBehavior.Do));
|
|
}
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
this.redoStack.Clear();
|
|
this.undoStack.Clear();
|
|
}
|
|
|
|
public bool CanUndo()
|
|
{
|
|
return this.undoStack.Count > 0;
|
|
}
|
|
|
|
public bool CanRedo()
|
|
{
|
|
return this.redoStack.Count<IUndoableAction>() > 0;
|
|
}
|
|
|
|
public IAction Undo()
|
|
{
|
|
bool flag = this.undoStack.Count<IUndoableAction>() > 0;
|
|
IAction result;
|
|
if (flag)
|
|
{
|
|
IUndoableAction undoableAction = null;
|
|
while (this.undoStack.Count > 0)
|
|
{
|
|
undoableAction = this.undoStack.Last<IUndoableAction>();
|
|
Logger.Log(ActionManager.LOGKEY, "undo action: " + undoableAction.ToString());
|
|
bool flag2 = this.BeforePerformAction != null;
|
|
if (flag2)
|
|
{
|
|
ActionEventArgs actionEventArgs = new ActionEventArgs(undoableAction, ActionBehavior.Undo);
|
|
this.BeforePerformAction(this, new ActionEventArgs(undoableAction, ActionBehavior.Undo));
|
|
bool cancel = actionEventArgs.Cancel;
|
|
if (cancel)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
this.undoStack.Remove(undoableAction);
|
|
undoableAction.Undo();
|
|
this.redoStack.Push(undoableAction);
|
|
EventHandler<ActionEventArgs> afterPerformAction = this.AfterPerformAction;
|
|
if (afterPerformAction != null)
|
|
{
|
|
afterPerformAction(this, new ActionEventArgs(undoableAction, ActionBehavior.Undo));
|
|
}
|
|
bool flag3 = !(undoableAction is ISerialUndoAction);
|
|
if (flag3)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
result = undoableAction;
|
|
}
|
|
else
|
|
{
|
|
result = null;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public IAction Redo()
|
|
{
|
|
bool flag = this.redoStack.Count > 0;
|
|
IAction result;
|
|
if (flag)
|
|
{
|
|
IUndoableAction undoableAction = null;
|
|
while (this.redoStack.Count > 0)
|
|
{
|
|
undoableAction = this.redoStack.Pop();
|
|
Logger.Log(ActionManager.LOGKEY, "redo action: " + undoableAction.ToString());
|
|
bool flag2 = this.BeforePerformAction != null;
|
|
if (flag2)
|
|
{
|
|
ActionEventArgs actionEventArgs = new ActionEventArgs(undoableAction, ActionBehavior.Redo);
|
|
this.BeforePerformAction(this, actionEventArgs);
|
|
bool cancel = actionEventArgs.Cancel;
|
|
if (cancel)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
undoableAction.Redo();
|
|
this.undoStack.Add(undoableAction);
|
|
EventHandler<ActionEventArgs> afterPerformAction = this.AfterPerformAction;
|
|
if (afterPerformAction != null)
|
|
{
|
|
afterPerformAction(this, new ActionEventArgs(undoableAction, ActionBehavior.Redo));
|
|
}
|
|
bool flag3 = !(undoableAction is ISerialUndoAction);
|
|
if (flag3)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
result = undoableAction;
|
|
}
|
|
else
|
|
{
|
|
result = null;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
public event EventHandler<ActionEventArgs> BeforePerformAction;
|
|
|
|
//[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
public event EventHandler<ActionEventArgs> AfterPerformAction;
|
|
|
|
private static readonly string LOGKEY = "actionmanager";
|
|
|
|
private List<IUndoableAction> undoStack = new List<IUndoableAction>();
|
|
|
|
private Stack<IUndoableAction> redoStack = new Stack<IUndoableAction>();
|
|
|
|
private int capacity = 30;
|
|
}
|
|
}
|