123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- /*
- * Copyright (C) =USTC= Fu Li
- *
- * Author : Fu Li
- * Create : 2005-3-6
- * Home : http://www.crazy-bit.com/
- * Mail : crazybit@263.net
- * History :
- */
- #ifndef __FOO_PCL_INTERFACE_UNDO_MANAGER_H__
- #define __FOO_PCL_INTERFACE_UNDO_MANAGER_H__
- #include <assert.h>
- #include <deque>
- template<class T> class PCL_Interface_Undo ;
- //=============================================================================
- /**
- * Undo/Redo manage.
- */
- template<class T>
- class PCL_Interface_Undo
- {
- public:
- /**
- * @name Basic Undo/Redo operation.
- * you must implement <B>PCL_Implement_Undo/PCL_Implement_Redo</B> in your subclass.
- */
- //@{
- bool IsUndoEnable() const {return !m_UndoList.empty();}
- bool IsRedoEnable() const {return !m_RedoList.empty();}
- void Undo()
- {
- if (IsUndoEnable())
- {
- T * p = m_UndoList.back() ; // get the latest undo-command
- this->PCL_Implement_Undo (p) ;
- m_UndoList.pop_back() ;
- m_RedoList.push_front(p) ;
- }
- }
- void Redo()
- {
- if (IsRedoEnable())
- {
- T * p = m_RedoList.front() ; // get the first redo-command
- this->PCL_Implement_Redo (p) ;
- m_RedoList.pop_front() ;
- m_UndoList.push_back(p) ;
- }
- }
- //@}
- /**
- * @name Clear operation.
- * clear command object in list.
- */
- //@{
- void ClearRedoList()
- {
- while (IsRedoEnable())
- {
- T * p = m_RedoList.back() ;
- m_RedoList.pop_back() ;
- delete p ;
- }
- }
- void ClearUndoList()
- {
- while (IsUndoEnable())
- {
- T * p = m_UndoList.back() ;
- m_UndoList.pop_back() ;
- delete p ;
- }
- }
- //@}
- /**
- * @name Undo max level.
- * if the undo level ==0, it means undo disable.
- */
- //@{
- int GetUndoLevel() const {return m_nUndoLevel;}
- /** it will delete overflowed command. */
- void SetUndoLevel (int nLevel)
- {
- if (nLevel < 0)
- {
- assert(false); return;
- }
- m_nUndoLevel = nLevel ; // >=0
- // calculate current number of command in list
- int nRemove = (int)(m_UndoList.size() + m_RedoList.size()) - m_nUndoLevel ;
- if (nRemove <= 0)
- return ;
- // first : delete command from Redo-list back
- while (!m_RedoList.empty() && (nRemove > 0))
- {
- T * p = m_RedoList.back() ;
- m_RedoList.pop_back() ;
- delete p ; nRemove-- ;
- }
- // then : delete command from Undo-list front
- while (!m_UndoList.empty() && (nRemove > 0))
- {
- T * p = m_UndoList.front() ;
- m_UndoList.pop_front() ;
- delete p ; nRemove-- ;
- }
- }
- //@}
- protected:
- /// Undo's implementation.
- /// @param : pCmd is the last command in undo-list.
- virtual void PCL_Implement_Undo (T* pCmd) =0 ;
- /// Redo's implementation.
- /// @param : pCmd is the first command in redo-list.
- virtual void PCL_Implement_Redo (T* pCmd) =0 ;
- /**
- * Add a command object into undo-list.
- * 1) it will clear redo-list. <BR>
- * 2) if the undo list is full, it will delete oldest undo command.
- */
- bool AddCommand (T* pCmd)
- {
- if ((m_nUndoLevel <= 0) || !pCmd)
- {
- assert(false); return false;
- }
- // clear redo-list, ennnnnnn. this behavior like a bintree.
- ClearRedoList() ;
- // single command
- assert ((int)m_UndoList.size() <= m_nUndoLevel) ;
- if ((int)m_UndoList.size() >= m_nUndoLevel) // never '>'
- {
- T * p = m_UndoList.front() ;
- m_UndoList.pop_front() ;
- delete p ;
- }
- // add to undo list
- m_UndoList.push_back (pCmd) ;
- return true ;
- }
- T* GetLatestUndoCommand() const {return IsUndoEnable() ? m_UndoList.back() : 0;}
- /**
- * @name Constructor.
- * constructor/destructor.
- */
- //@{
- PCL_Interface_Undo (int nUndoLevel = 20) : m_nUndoLevel(nUndoLevel) {}
- virtual ~PCL_Interface_Undo()
- {
- ClearRedoList() ;
- ClearUndoList() ;
- }
- //@}
- private:
- std::deque<T*> m_UndoList ;
- std::deque<T*> m_RedoList ;
- // the level of undo operation. the ZERO means disable undo
- int m_nUndoLevel ;
- };
- //=============================================================================
- // inline implement
- //=============================================================================
- #endif
|