/// <summary> /// Performs the code func inside an undoable period guarded by the command specified. Use this method if the code to run inside the /// undoable period is well known and can be wrapped inside a single func. The func codeToExecuteInPeriodFunc is executed once, all /// undo/redo logic is done by undo/redo-ing commands which were ran due to state changes caused by codeToExecuteInPeriodFunc. /// If you want to run a command again during redo, you should enqueue and run a normal command instead of using this method. /// To create an undoable period, you can also call BeginUndoablePeriod and EndUndoablePeriod. /// </summary> /// <param name="cmd">The CMD.</param> /// <param name="codeToExecuteInPeriodFunc">The code to execute in period func.</param> public void PerformUndoablePeriod(UndoablePeriodCommand cmd, Action codeToExecuteInPeriodFunc) { ArgumentVerifier.CantBeNull(cmd, "cmd"); ArgumentVerifier.CantBeNull(codeToExecuteInPeriodFunc, "codeToExecuteInPeriod"); // reset before/after do action as BeginUndoablePeriod will execute the command (which is empty) but will still perform the before/after actions // resetting them to null will avoid that Action beforeDoActionSafe = cmd.BeforeDoAction; Action afterDoActionSafe = cmd.AfterDoAction; cmd.BeforeDoAction = null; cmd.AfterDoAction = null; try { ThreadEnter(); BeginUndoablePeriod(cmd); // set them back. cmd.BeforeDoAction = beforeDoActionSafe; cmd.AfterDoAction = afterDoActionSafe; if (cmd.BeforeDoAction != null) { cmd.BeforeDoAction(); } codeToExecuteInPeriodFunc(); if (cmd.AfterDoAction != null) { cmd.AfterDoAction(); } EndUndoablePeriod(cmd); } finally { ThreadExit(); } }
/// <summary> /// Sets the command manager in a special mode where all subsequential commands are tracked inside an UndoablePeriodCommand which, when undone/redone /// will not destroy its command queue during undo and won't accept new commands when redone, which is useful when you want to mark a method as an /// undoable piece of code and the method creates objects, which can be a problem with a normal command calling the method because the objects created /// inside the method are re-created (so you'll get new instances) when the command is redone. If follow up commands work on the instances, redoing these /// commands as well causes a problem as they'll work on objects which aren't there. /// </summary> /// <param name="cmd">The command to use for the undoableperiod.</param> public void BeginUndoablePeriod(UndoablePeriodCommand cmd) { try { ThreadEnter(); ArgumentVerifier.CantBeNull(cmd, "cmd"); EnqueueAndRunCommand(cmd); } finally { ThreadExit(); } }
/// <summary> /// Ends the undoable period started with BeginUndoablePeriod. /// </summary> /// <param name="cmd">The command used for the undoable period.</param> public void EndUndoablePeriod(UndoablePeriodCommand cmd) { try { ThreadEnter(); ArgumentVerifier.CantBeNull(cmd, "cmd"); // the period has ended, so we've to pop the queue of the period from the stack. cmd.PopCommandQueueFromActiveStackIfRequired(); } finally { ThreadExit(); } }
/// <summary> /// Performs the code func inside an undoable period guarded by the command specified. Use this method if the code to run inside the /// undoable period is well known and can be wrapped inside a single func. The func codeToExecuteInPeriodFunc is executed once, all /// undo/redo logic is done by undo/redo-ing commands which were ran due to state changes caused by codeToExecuteInPeriodFunc. /// If you want to run a command again during redo, you should enqueue and run a normal command instead of using this method. /// To create an undoable period, you can also call BeginUndoablePeriod and EndUndoablePeriod. /// </summary> /// <param name="cmd">The CMD.</param> /// <param name="codeToExecuteInPeriodFunc">The code to execute in period func.</param> public void PerformUndoablePeriod(UndoablePeriodCommand cmd, Action codeToExecuteInPeriodFunc) { try { ThreadEnter(); ArgumentVerifier.CantBeNull(cmd, "cmd"); ArgumentVerifier.CantBeNull(codeToExecuteInPeriodFunc, "codeToExecuteInPeriod"); BeginUndoablePeriod(cmd); if (cmd.BeforeDoAction != null) { cmd.BeforeDoAction(); } codeToExecuteInPeriodFunc(); if (cmd.AfterDoAction != null) { cmd.AfterDoAction(); } EndUndoablePeriod(cmd); } finally { ThreadExit(); } }