UndoManager.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using PixiEditor.Models.DataHolders;
  4. namespace PixiEditor.Models.Controllers
  5. {
  6. public static class UndoManager
  7. {
  8. private static bool lastChangeWasUndo;
  9. public static Stack<Change> UndoStack { get; set; } = new Stack<Change>();
  10. public static Stack<Change> RedoStack { get; set; } = new Stack<Change>();
  11. public static bool CanUndo => UndoStack.Count > 0;
  12. public static bool CanRedo => RedoStack.Count > 0;
  13. public static object MainRoot { get; set; }
  14. /// <summary>
  15. /// Sets object(root) in which undo properties are stored.
  16. /// </summary>
  17. /// <param name="root">Parent object.</param>
  18. public static void SetMainRoot(object root)
  19. {
  20. MainRoot = root;
  21. }
  22. /// <summary>
  23. /// Adds property change to UndoStack.
  24. /// </summary>
  25. public static void AddUndoChange(Change change)
  26. {
  27. lastChangeWasUndo = false;
  28. // Clears RedoStack if last move wasn't redo or undo and if redo stack is greater than 0.
  29. if (lastChangeWasUndo == false && RedoStack.Count > 0)
  30. {
  31. RedoStack.Clear();
  32. }
  33. change.Root ??= MainRoot;
  34. UndoStack.Push(change);
  35. }
  36. /// <summary>
  37. /// Sets top property in UndoStack to Old Value.
  38. /// </summary>
  39. public static void Undo()
  40. {
  41. lastChangeWasUndo = true;
  42. Change change = UndoStack.Pop();
  43. if (change.ReverseProcess == null)
  44. {
  45. SetPropertyValue(change.Root, change.Property, change.OldValue);
  46. }
  47. else
  48. {
  49. change.ReverseProcess(change.ReverseProcessArguments);
  50. }
  51. RedoStack.Push(change);
  52. }
  53. /// <summary>
  54. /// Sets top property from RedoStack to old value.
  55. /// </summary>
  56. public static void Redo()
  57. {
  58. lastChangeWasUndo = true;
  59. Change change = RedoStack.Pop();
  60. if (change.Process == null)
  61. {
  62. SetPropertyValue(change.Root, change.Property, change.NewValue);
  63. }
  64. else
  65. {
  66. change.Process(change.ProcessArguments);
  67. }
  68. UndoStack.Push(change);
  69. }
  70. private static void SetPropertyValue(object target, string propName, object value)
  71. {
  72. string[] bits = propName.Split('.');
  73. for (int i = 0; i < bits.Length - 1; i++)
  74. {
  75. System.Reflection.PropertyInfo propertyToGet = target.GetType().GetProperty(bits[i]);
  76. target = propertyToGet.GetValue(target, null);
  77. }
  78. System.Reflection.PropertyInfo propertyToSet = target.GetType().GetProperty(bits.Last());
  79. propertyToSet.SetValue(target, value, null);
  80. }
  81. }
  82. }