public IAction Undo() { if (undoStack.Count() > 0) { IUndoableAction action = null; while (undoStack.Count > 0) { action = undoStack.Last(); Logger.Log(LOGKEY, "undo action: " + action.ToString()); if (BeforePerformAction != null) { var arg = new ActionEventArgs(action, ActionBehavior.Undo); BeforePerformAction(this, new ActionEventArgs(action, ActionBehavior.Undo)); if (arg.Cancel) break; } undoStack.Remove(action); action.Undo(); redoStack.Push(action); if (AfterPerformAction != null) AfterPerformAction(this, new ActionEventArgs(action, ActionBehavior.Undo)); if (!(action is ISerialUndoAction)) break; } return action; } return null; }
/* * isCanUndo attribute specifies whether the action can be undo. * sometimes an action doesn't need undo even it's a IUndoable action. * the action will not be pushed in undo stack after performed immediately. */ private void Do(IAction action, bool perform, bool isCanUndo) { Logger.Log(LOGKEY, string.Format("{0} action: {1}[{2}]", perform ? "do" : "add", action.GetType().Name, action.GetName())); if (BeforePerformAction != null) { var arg = new ActionEventArgs(action, ActionBehavior.Do); BeforePerformAction(this, arg); if (arg.Cancel) return; } if (perform) action.Do(); if (action is IUndoableAction && isCanUndo) { redoStack.Clear(); undoStack.Add(action as IUndoableAction); if(undoStack.Count() > capacity) { undoStack.RemoveRange(0, undoStack.Count() - capacity); Logger.Log(LOGKEY, "action stack full. remove " + (capacity - undoStack.Count()) + " action(s)."); } } if (AfterPerformAction != null) AfterPerformAction(this, new ActionEventArgs(action, ActionBehavior.Do)); }
public IAction Redo() { if (redoStack.Count > 0) { IUndoableAction action = null; while (redoStack.Count > 0) { action = redoStack.Pop(); Logger.Log(LOGKEY, "redo action: " + action.ToString()); if (BeforePerformAction != null) { var arg = new ActionEventArgs(action, ActionBehavior.Redo); BeforePerformAction(this, arg); if (arg.Cancel) break; } action.Do(); undoStack.Add(action); if (AfterPerformAction != null) AfterPerformAction(this, new ActionEventArgs(action, ActionBehavior.Redo)); if (!(action is ISerialUndoAction)) break; } return action; } else return null; }