fw4spl
UndoRedoManager.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2017.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwCommand/UndoRedoManager.hpp"
8 
9 #include <fwCore/spyLog.hpp>
10 
11 namespace fwCommand
12 {
13 
14 //-----------------------------------------------------------------------------
15 
16 UndoRedoManager::UndoRedoManager(size_t maxMemory, size_t maxCommands) :
17  m_maxMemory(maxMemory),
18  m_maxCommands(maxCommands == 0 ? 1 : maxCommands),
19  m_usedMemory(0),
20  m_commandIndex(-1)
21 {
22  SLM_ASSERT("The number of commands must be greater than 0", maxCommands > 0);
23 }
24 
25 //-----------------------------------------------------------------------------
26 
27 bool UndoRedoManager::enqueue(ICommand::sptr cmd)
28 {
29  if(m_maxMemory == 0)
30  {
31  SLM_WARN("Cannot add a command because maxMemory is 0.");
32  return false;
33  }
34 
35  if(cmd->getSize() > m_maxMemory)
36  {
37  SLM_WARN("The current command is bigger than the maximum history size");
38  return false;
39  }
40 
41  // Remove all commands following the current history point.
42  if(!m_commandQueue.empty())
43  {
44  for(std::int64_t i = m_commandQueue.size() - 1; i > m_commandIndex; --i)
45  {
46  m_usedMemory -= m_commandQueue[i]->getSize();
47  m_commandQueue.pop_back();
48  }
49  }
50 
51  // Remove the oldest command if we reached the maximum number of commands.
52  if(m_maxCommands == m_commandQueue.size())
53  {
54  popFront();
55  }
56 
57  // Remove the oldest commands if we reached the maximum history size.
58  while(m_usedMemory + cmd->getSize() > m_maxMemory)
59  {
60  popFront();
61  }
62 
63  m_commandQueue.push_back(cmd);
64  m_usedMemory += cmd->getSize();
65  m_commandIndex = static_cast<std::int64_t>(m_commandQueue.size() - 1);
66 
67  return true;
68 }
69 
70 //-----------------------------------------------------------------------------
71 
73 {
74  bool success = false;
75 
76  if(m_commandIndex != m_commandQueue.size() - 1)
77  {
78  m_commandIndex++;
79  success = m_commandQueue[m_commandIndex]->redo();
80  }
81 
82  return success;
83 }
84 
85 //-----------------------------------------------------------------------------
86 
88 {
89  bool success = false;
90 
91  if(m_commandIndex > -1)
92  {
93  success = m_commandQueue[m_commandIndex]->undo();
94  m_commandIndex--;
95  }
96 
97  return success;
98 }
99 
100 //-----------------------------------------------------------------------------
101 
103 {
104  return m_commandIndex > -1;
105 }
106 
107 //-----------------------------------------------------------------------------
108 
110 {
111  return (m_commandIndex != this->getCommandCount() - 1) && (this->getCommandCount() > 0);
112 }
113 
114 //-----------------------------------------------------------------------------
115 
117 {
118  m_commandQueue.clear();
119  m_commandIndex = -1;
120  m_usedMemory = 0;
121 }
122 
123 //-----------------------------------------------------------------------------
124 
126 {
127  return m_commandQueue.size();
128 }
129 
130 //-----------------------------------------------------------------------------
131 
132 void UndoRedoManager::setCommandCount(size_t cmdCount)
133 {
134  this->clear();
135  m_maxCommands = cmdCount;
136 }
137 
138 //-----------------------------------------------------------------------------
139 
141 {
142  return m_usedMemory;
143 }
144 
145 //-----------------------------------------------------------------------------
146 
147 void UndoRedoManager::setHistorySize(size_t histSize)
148 {
149  this->clear();
150  m_maxMemory = histSize;
151 }
152 
153 //-----------------------------------------------------------------------------
154 
155 void UndoRedoManager::popFront()
156 {
157  CommandHistoryType::iterator it = m_commandQueue.begin();
158 
159  m_usedMemory -= (*it)->getSize();
160  m_commandQueue.pop_front();
161 }
162 
163 //-----------------------------------------------------------------------------
164 
165 } // namespace fwCommand
FWCOMMAND_API size_t getHistorySize() const
Returns the amount of memory used by the history.
FWCOMMAND_API bool canUndo() const
Return true if we can undo.
FWCOMMAND_API bool enqueue(ICommand::sptr cmd)
Push a command to the history.
FWCOMMAND_API size_t getCommandCount() const
Get the number of enqueued commands.
FWCOMMAND_API UndoRedoManager(size_t maxMemory=std::numeric_limits< size_t >::max(), size_t maxCommands=std::numeric_limits< size_t >::max())
Default constructor.
#define SLM_WARN(message)
Definition: spyLog.hpp:261
FWCOMMAND_API void setCommandCount(size_t cmdCount)
Set the maximum number of enqueued commands.
FWCOMMAND_API bool undo()
Execute the previous command if any.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
The namespace fwCommand contains classes describing and managing commands.
Definition: ICommand.hpp:15
FWCOMMAND_API bool canRedo() const
Return true if we can redo.
FWCOMMAND_API bool redo()
Execute the next command if any.
FWCOMMAND_API void clear()
Remove all commands in history.
This file defines SpyLog macros. These macros are used to log messages to a file or to the console du...
FWCOMMAND_API void setHistorySize(size_t histSize)
Set the maximum amount of memory used by the history.