UndoManager.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. /// Undo-Redo code is written using the article:
  5. /// http://www.codeproject.com/cs/design/commandpatterndemo.asp
  6. // The Command Pattern and MVC Architecture
  7. // By David Veeneman.
  8. namespace DrawTools
  9. {
  10. /// <summary>
  11. /// Class is responsible for executing Undo - Redo operations
  12. /// </summary>
  13. class UndoManager
  14. {
  15. #region Class Members
  16. GraphicsList graphicsList;
  17. List<Command> historyList;
  18. int nextUndo;
  19. #endregion Class Members
  20. #region Constructor
  21. public UndoManager(GraphicsList graphicsList)
  22. {
  23. this.graphicsList = graphicsList;
  24. ClearHistory();
  25. }
  26. #endregion Constructor
  27. #region Properties
  28. /// <summary>
  29. /// Return true if Undo operation is available
  30. /// </summary>
  31. public bool CanUndo
  32. {
  33. get
  34. {
  35. // If the NextUndo pointer is -1, no commands to undo
  36. if (nextUndo < 0 ||
  37. nextUndo > historyList.Count - 1) // precaution
  38. {
  39. return false;
  40. }
  41. return true;
  42. }
  43. }
  44. /// <summary>
  45. /// Return true if Redo operation is available
  46. /// </summary>
  47. public bool CanRedo
  48. {
  49. get
  50. {
  51. // If the NextUndo pointer points to the last item, no commands to redo
  52. if (nextUndo == historyList.Count - 1)
  53. {
  54. return false;
  55. }
  56. return true;
  57. }
  58. }
  59. #endregion Properties
  60. #region Public Functions
  61. /// <summary>
  62. /// Clear History
  63. /// </summary>
  64. public void ClearHistory()
  65. {
  66. historyList = new List<Command>();
  67. nextUndo = -1;
  68. }
  69. /// <summary>
  70. /// Add new command to history.
  71. /// Called by client after executing some action.
  72. /// </summary>
  73. /// <param name="command"></param>
  74. public void AddCommandToHistory(Command command)
  75. {
  76. // Purge history list
  77. this.TrimHistoryList();
  78. // Add command and increment undo counter
  79. historyList.Add(command);
  80. nextUndo++;
  81. }
  82. /// <summary>
  83. /// Undo
  84. /// </summary>
  85. public void Undo()
  86. {
  87. if ( ! CanUndo )
  88. {
  89. return;
  90. }
  91. // Get the Command object to be undone
  92. Command command = historyList[nextUndo];
  93. // Execute the Command object's undo method
  94. command.Undo(graphicsList);
  95. // Move the pointer up one item
  96. nextUndo--;
  97. }
  98. /// <summary>
  99. /// Redo
  100. /// </summary>
  101. public void Redo()
  102. {
  103. if ( ! CanRedo )
  104. {
  105. return;
  106. }
  107. // Get the Command object to redo
  108. int itemToRedo = nextUndo + 1;
  109. Command command = historyList[itemToRedo];
  110. // Execute the Command object
  111. command.Redo(graphicsList);
  112. // Move the undo pointer down one item
  113. nextUndo++;
  114. }
  115. #endregion Public Functions
  116. #region Private Functions
  117. private void TrimHistoryList()
  118. {
  119. // We can redo any undone command until we execute a new
  120. // command. The new command takes us off in a new direction,
  121. // which means we can no longer redo previously undone actions.
  122. // So, we purge all undone commands from the history list.*/
  123. // Exit if no items in History list
  124. if (historyList.Count == 0)
  125. {
  126. return;
  127. }
  128. // Exit if NextUndo points to last item on the list
  129. if (nextUndo == historyList.Count - 1)
  130. {
  131. return;
  132. }
  133. // Purge all items below the NextUndo pointer
  134. for (int i = historyList.Count - 1; i > nextUndo; i--)
  135. {
  136. historyList.RemoveAt(i);
  137. }
  138. }
  139. #endregion
  140. }
  141. }