UndoRedoStackμ μ€ν μ·¨μμ λ€μ μ€νμ νκΈ° μν΄ κ΅¬νν λμμΈ ν¨ν΄μ΄μμ.
λ€μν μννΈμ¨μ΄μμ κ°μμ λ°©λ²μΌλ‘ ꡬν λμ΄ μμ§λ§, μ λ μ‘°κΈ κ°λ¨νκ² νμν κΈ°λ₯λ§ κ΅¬ννμ¬ κ° κΈ°λ₯λ€μ μ‘μ
(Action)μΌλ‘ λλμ΄ λ³΄μμ΄μ.
κ·Έλ¦¬κ³ κ° Actionμ λ¬Άμ ActionBlock ν΄λμ€λ₯Ό λ§λ€μ΄ Sequenceλ₯Ό ꡬννλλ‘ νμ΄μ.
μ΄λ₯Ό ν΅ν΄ 볡μ‘ν Undo λλ Redo μμ
μ νλ²μ μ²λ¦¬ ν μ μμ΄μ.
public interface IUndoableAction
{
void Do();
void Undo();
}
public class ActionBlock : IUndoableAction
{
private readonly IUndoableAction[] actionSequence;
public ActionBlock(params IUndoableAction[] actionSequence)
{
this.actionSequence = actionSequence;
}
public void Do()
{
foreach (var action in actionSequence)
action.Do();
}
public void Undo()
{
foreach (var action in actionSequence.Reverse())
action.Undo();
}
public override string ToString()
{
return string.Join(",", actionSequence.Select(a => a.ToString()));
}
}
public class UndoRedoStack
{
private readonly Stack<IUndoableAction> undoStack = new Stack<IUndoableAction>();
private readonly Stack<IUndoableAction> redoStack = new Stack<IUndoableAction>();
/// <summary>
/// μλ‘μ΄ μ‘μ
μ μ
λ ₯λ°μμλ κ° IUndoableActionμ
/// Implementν ν΄λμ€μ μ‘μ
μ μννκ³ κΈ°μ‘΄μ Redo μ€νμ μ§μμ§λ€.
/// Undo λ° Redo λ©μλ μν μ Implement λ ν΄λμ€μ λ΄μ©μ μννλ€.
/// </summary>
/// <param name="action"></param>
public void Do(IUndoableAction action)
{
action.Do();
undoStack.Push(action);
redoStack.Clear();
}
public void Undo()
{
RunAction(undoStack, redoStack, f => f.Undo());
}
public void Redo()
{
RunAction(redoStack, undoStack, f => f.Do());
}
private static void RunAction(Stack<IUndoableAction> source, Stack<IUndoableAction> target, Action<IUndoableAction> undoRedo)
{
if (source.Count <= 0)
return;
var action = source.Pop();
undoRedo(action);
target.Push(action);
}
}