PCL_interface_undo.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright (C) =USTC= Fu Li
  3. *
  4. * Author : Fu Li
  5. * Create : 2005-3-6
  6. * Home : http://www.crazy-bit.com/
  7. * Mail : crazybit@263.net
  8. * History :
  9. */
  10. #ifndef __FOO_PCL_INTERFACE_UNDO_MANAGER_H__
  11. #define __FOO_PCL_INTERFACE_UNDO_MANAGER_H__
  12. #include <assert.h>
  13. #include <deque>
  14. template<class T> class PCL_Interface_Undo ;
  15. //=============================================================================
  16. /**
  17. * Undo/Redo manage.
  18. */
  19. template<class T>
  20. class PCL_Interface_Undo
  21. {
  22. public:
  23. /**
  24. * @name Basic Undo/Redo operation.
  25. * you must implement <B>PCL_Implement_Undo/PCL_Implement_Redo</B> in your subclass.
  26. */
  27. //@{
  28. bool IsUndoEnable() const {return !m_UndoList.empty();}
  29. bool IsRedoEnable() const {return !m_RedoList.empty();}
  30. void Undo()
  31. {
  32. if (IsUndoEnable())
  33. {
  34. T * p = m_UndoList.back() ; // get the latest undo-command
  35. this->PCL_Implement_Undo (p) ;
  36. m_UndoList.pop_back() ;
  37. m_RedoList.push_front(p) ;
  38. }
  39. }
  40. void Redo()
  41. {
  42. if (IsRedoEnable())
  43. {
  44. T * p = m_RedoList.front() ; // get the first redo-command
  45. this->PCL_Implement_Redo (p) ;
  46. m_RedoList.pop_front() ;
  47. m_UndoList.push_back(p) ;
  48. }
  49. }
  50. //@}
  51. /**
  52. * @name Clear operation.
  53. * clear command object in list.
  54. */
  55. //@{
  56. void ClearRedoList()
  57. {
  58. while (IsRedoEnable())
  59. {
  60. T * p = m_RedoList.back() ;
  61. m_RedoList.pop_back() ;
  62. delete p ;
  63. }
  64. }
  65. void ClearUndoList()
  66. {
  67. while (IsUndoEnable())
  68. {
  69. T * p = m_UndoList.back() ;
  70. m_UndoList.pop_back() ;
  71. delete p ;
  72. }
  73. }
  74. //@}
  75. /**
  76. * @name Undo max level.
  77. * if the undo level ==0, it means undo disable.
  78. */
  79. //@{
  80. int GetUndoLevel() const {return m_nUndoLevel;}
  81. /** it will delete overflowed command. */
  82. void SetUndoLevel (int nLevel)
  83. {
  84. if (nLevel < 0)
  85. {
  86. assert(false); return;
  87. }
  88. m_nUndoLevel = nLevel ; // >=0
  89. // calculate current number of command in list
  90. int nRemove = (int)(m_UndoList.size() + m_RedoList.size()) - m_nUndoLevel ;
  91. if (nRemove <= 0)
  92. return ;
  93. // first : delete command from Redo-list back
  94. while (!m_RedoList.empty() && (nRemove > 0))
  95. {
  96. T * p = m_RedoList.back() ;
  97. m_RedoList.pop_back() ;
  98. delete p ; nRemove-- ;
  99. }
  100. // then : delete command from Undo-list front
  101. while (!m_UndoList.empty() && (nRemove > 0))
  102. {
  103. T * p = m_UndoList.front() ;
  104. m_UndoList.pop_front() ;
  105. delete p ; nRemove-- ;
  106. }
  107. }
  108. //@}
  109. protected:
  110. /// Undo's implementation.
  111. /// @param : pCmd is the last command in undo-list.
  112. virtual void PCL_Implement_Undo (T* pCmd) =0 ;
  113. /// Redo's implementation.
  114. /// @param : pCmd is the first command in redo-list.
  115. virtual void PCL_Implement_Redo (T* pCmd) =0 ;
  116. /**
  117. * Add a command object into undo-list.
  118. * 1) it will clear redo-list. <BR>
  119. * 2) if the undo list is full, it will delete oldest undo command.
  120. */
  121. bool AddCommand (T* pCmd)
  122. {
  123. if ((m_nUndoLevel <= 0) || !pCmd)
  124. {
  125. assert(false); return false;
  126. }
  127. // clear redo-list, ennnnnnn. this behavior like a bintree.
  128. ClearRedoList() ;
  129. // single command
  130. assert ((int)m_UndoList.size() <= m_nUndoLevel) ;
  131. if ((int)m_UndoList.size() >= m_nUndoLevel) // never '>'
  132. {
  133. T * p = m_UndoList.front() ;
  134. m_UndoList.pop_front() ;
  135. delete p ;
  136. }
  137. // add to undo list
  138. m_UndoList.push_back (pCmd) ;
  139. return true ;
  140. }
  141. T* GetLatestUndoCommand() const {return IsUndoEnable() ? m_UndoList.back() : 0;}
  142. /**
  143. * @name Constructor.
  144. * constructor/destructor.
  145. */
  146. //@{
  147. PCL_Interface_Undo (int nUndoLevel = 20) : m_nUndoLevel(nUndoLevel) {}
  148. virtual ~PCL_Interface_Undo()
  149. {
  150. ClearRedoList() ;
  151. ClearUndoList() ;
  152. }
  153. //@}
  154. private:
  155. std::deque<T*> m_UndoList ;
  156. std::deque<T*> m_RedoList ;
  157. // the level of undo operation. the ZERO means disable undo
  158. int m_nUndoLevel ;
  159. };
  160. //=============================================================================
  161. // inline implement
  162. //=============================================================================
  163. #endif