UndoRedoList.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. // The Command & Conquer Map Editor and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Linq;
  17. using System.Text;
  18. using System.Threading.Tasks;
  19. namespace MobiusEditor.Utility
  20. {
  21. public class UndoRedoList<T>
  22. {
  23. private const int DefaultMaxUndoRedo = 50;
  24. private readonly List<(Action<T> Undo, Action<T> Redo)> undoRedoActions = new List<(Action<T> Undo, Action<T> Redo)>();
  25. private readonly int maxUndoRedo;
  26. private int undoRedoPosition = 0;
  27. public event EventHandler<EventArgs> Tracked;
  28. public event EventHandler<EventArgs> Undone;
  29. public event EventHandler<EventArgs> Redone;
  30. public bool CanUndo => undoRedoPosition > 0;
  31. public bool CanRedo => undoRedoActions.Count > undoRedoPosition;
  32. public UndoRedoList(int maxUndoRedo)
  33. {
  34. this.maxUndoRedo = maxUndoRedo;
  35. }
  36. public UndoRedoList()
  37. : this(DefaultMaxUndoRedo)
  38. {
  39. }
  40. public void Clear()
  41. {
  42. undoRedoActions.Clear();
  43. undoRedoPosition = 0;
  44. OnTracked();
  45. }
  46. public void Track(Action<T> undo, Action<T> redo)
  47. {
  48. if (undoRedoActions.Count > undoRedoPosition)
  49. {
  50. undoRedoActions.RemoveRange(undoRedoPosition, undoRedoActions.Count - undoRedoPosition);
  51. }
  52. undoRedoActions.Add((undo, redo));
  53. if (undoRedoActions.Count > maxUndoRedo)
  54. {
  55. undoRedoActions.RemoveRange(0, undoRedoActions.Count - maxUndoRedo);
  56. }
  57. undoRedoPosition = undoRedoActions.Count;
  58. OnTracked();
  59. }
  60. public void Undo(T context)
  61. {
  62. if (!CanUndo)
  63. {
  64. throw new InvalidOperationException();
  65. }
  66. undoRedoPosition--;
  67. undoRedoActions[undoRedoPosition].Undo(context);
  68. OnUndone();
  69. }
  70. public void Redo(T context)
  71. {
  72. if (!CanRedo)
  73. {
  74. throw new InvalidOperationException();
  75. }
  76. undoRedoActions[undoRedoPosition].Redo(context);
  77. undoRedoPosition++;
  78. OnRedone();
  79. }
  80. protected virtual void OnTracked()
  81. {
  82. Tracked?.Invoke(this, new EventArgs());
  83. }
  84. protected virtual void OnUndone()
  85. {
  86. Undone?.Invoke(this, new EventArgs());
  87. }
  88. protected virtual void OnRedone()
  89. {
  90. Redone?.Invoke(this, new EventArgs());
  91. }
  92. }
  93. }