UndoRedoList.cs (3417B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // The Command & Conquer Map Editor and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // The Command & Conquer Map Editor and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 using System; 16 using System.Collections.Generic; 17 using System.Linq; 18 using System.Text; 19 using System.Threading.Tasks; 20 21 namespace MobiusEditor.Utility 22 { 23 public class UndoRedoList<T> 24 { 25 private const int DefaultMaxUndoRedo = 50; 26 27 private readonly List<(Action<T> Undo, Action<T> Redo)> undoRedoActions = new List<(Action<T> Undo, Action<T> Redo)>(); 28 private readonly int maxUndoRedo; 29 private int undoRedoPosition = 0; 30 31 public event EventHandler<EventArgs> Tracked; 32 public event EventHandler<EventArgs> Undone; 33 public event EventHandler<EventArgs> Redone; 34 35 public bool CanUndo => undoRedoPosition > 0; 36 37 public bool CanRedo => undoRedoActions.Count > undoRedoPosition; 38 39 public UndoRedoList(int maxUndoRedo) 40 { 41 this.maxUndoRedo = maxUndoRedo; 42 } 43 44 public UndoRedoList() 45 : this(DefaultMaxUndoRedo) 46 { 47 } 48 49 public void Clear() 50 { 51 undoRedoActions.Clear(); 52 undoRedoPosition = 0; 53 OnTracked(); 54 } 55 56 public void Track(Action<T> undo, Action<T> redo) 57 { 58 if (undoRedoActions.Count > undoRedoPosition) 59 { 60 undoRedoActions.RemoveRange(undoRedoPosition, undoRedoActions.Count - undoRedoPosition); 61 } 62 63 undoRedoActions.Add((undo, redo)); 64 65 if (undoRedoActions.Count > maxUndoRedo) 66 { 67 undoRedoActions.RemoveRange(0, undoRedoActions.Count - maxUndoRedo); 68 } 69 70 undoRedoPosition = undoRedoActions.Count; 71 OnTracked(); 72 } 73 74 public void Undo(T context) 75 { 76 if (!CanUndo) 77 { 78 throw new InvalidOperationException(); 79 } 80 81 undoRedoPosition--; 82 undoRedoActions[undoRedoPosition].Undo(context); 83 OnUndone(); 84 } 85 86 public void Redo(T context) 87 { 88 if (!CanRedo) 89 { 90 throw new InvalidOperationException(); 91 } 92 93 undoRedoActions[undoRedoPosition].Redo(context); 94 undoRedoPosition++; 95 OnRedone(); 96 } 97 98 protected virtual void OnTracked() 99 { 100 Tracked?.Invoke(this, new EventArgs()); 101 } 102 103 protected virtual void OnUndone() 104 { 105 Undone?.Invoke(this, new EventArgs()); 106 } 107 108 protected virtual void OnRedone() 109 { 110 Redone?.Invoke(this, new EventArgs()); 111 } 112 } 113 }