Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkLimitedLinearUndo.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkLimitedLinearUndo.h"
14 #include <mitkRenderingManager.h>
15 
17 : m_UndoLimit(0)
18 {
19  // nothing to do
20 }
21 
23 {
24  // delete undo and redo list
25  this->ClearList(&m_UndoList);
26  this->ClearList(&m_RedoList);
27 }
28 
30 {
31  while (!list->empty())
32  {
33  UndoStackItem *item = list->back();
34  list->pop_back();
35  delete item;
36  }
37 }
38 
40 {
41  auto *operationEvent = dynamic_cast<OperationEvent *>(stackItem);
42  if (!operationEvent)
43  return false;
44 
45  // clear the redolist, if a new operation is saved
46  if (!m_RedoList.empty())
47  {
48  this->ClearList(&m_RedoList);
49  InvokeEvent(RedoEmptyEvent());
50  }
51 
52  if (0 != m_UndoLimit && m_UndoList.size() == m_UndoLimit)
53  {
54  auto item = m_UndoList.front();
55  m_UndoList.pop_front();
56  delete item;
57  }
58  m_UndoList.push_back(operationEvent);
59 
60  InvokeEvent(UndoNotEmptyEvent());
61 
62  return true;
63 }
64 
66 {
67  if (fine)
68  {
69  // undo one object event ID
70  return Undo();
71  }
72  else
73  {
74  // undo one group event ID
75  int oeid = FirstObjectEventIdOfCurrentGroup(
76  m_UndoList); // get the Object Event ID of the first item with a differnt Group ID (as seen from the end of stack)
77  return Undo(oeid);
78  }
79 }
80 
82 {
83  if (m_UndoList.empty())
84  return false;
85 
86  int undoObjectEventId = m_UndoList.back()->GetObjectEventId();
87  return Undo(undoObjectEventId);
88 }
89 
91 {
92  if (m_UndoList.empty())
93  return false;
94 
95  bool rc = true;
96  do
97  {
98  m_UndoList.back()->ReverseAndExecute();
99 
100  m_RedoList.push_back(m_UndoList.back()); // move to redo stack
101  m_UndoList.pop_back();
102  InvokeEvent(RedoNotEmptyEvent());
103 
104  if (m_UndoList.empty())
105  {
106  InvokeEvent(UndoEmptyEvent());
107  rc = false;
108  break;
109  }
110  } while (m_UndoList.back()->GetObjectEventId() >= oeid);
111 
112  // Update. Check Rendering Mechanism where to request updates
114  return rc;
115 }
116 
118 {
119  return Redo();
120 }
121 
123 {
124  if (m_RedoList.empty())
125  return false;
126 
127  int redoObjectEventId = m_RedoList.back()->GetObjectEventId();
128  return Redo(redoObjectEventId);
129 }
130 
132 {
133  if (m_RedoList.empty())
134  return false;
135 
136  do
137  {
138  m_RedoList.back()->ReverseAndExecute();
139 
140  m_UndoList.push_back(m_RedoList.back());
141  m_RedoList.pop_back();
142  InvokeEvent(UndoNotEmptyEvent());
143 
144  if (m_RedoList.empty())
145  {
146  InvokeEvent(RedoEmptyEvent());
147  break;
148  }
149  } while (m_RedoList.back()->GetObjectEventId() <= oeid);
150 
151  // Update. This should belong into the ExecuteOperation() of OperationActors, but it seems not to be used everywhere
153  return true;
154 }
155 
157 {
158  this->ClearList(&m_UndoList);
159  InvokeEvent(UndoEmptyEvent());
160 
161  this->ClearList(&m_RedoList);
162  InvokeEvent(RedoEmptyEvent());
163 }
164 
166 {
167  this->ClearList(&m_RedoList);
168  InvokeEvent(RedoEmptyEvent());
169 }
170 
172 {
173  return m_RedoList.empty();
174 }
175 
177 {
178  return m_UndoLimit;
179 }
180 
181 void mitk::LimitedLinearUndo::SetUndoLimit(std::size_t undoLimit)
182 {
183  if (undoLimit != m_UndoLimit)
184  {
185  if (m_UndoList.size() > undoLimit)
186  {
187  m_UndoList.erase(m_UndoList.begin(), m_UndoList.end() - undoLimit);
188  }
189  m_UndoLimit = undoLimit;
190  }
191 }
192 
194 {
195  return m_UndoList.back()->GetObjectEventId();
196 }
197 
199 {
200  return m_UndoList.back()->GetGroupEventId();
201 }
202 
204 {
205  // When/where is this function needed? In CoordinateSupplier...
206  for (auto iter = m_UndoList.rbegin(); iter != m_UndoList.rend(); ++iter)
207  {
208  auto *opEvent = dynamic_cast<OperationEvent *>(*iter);
209  if (!opEvent)
210  continue;
211 
212  if (opEvent->GetOperation() != nullptr && opEvent->GetOperation()->GetOperationType() == opType &&
213  opEvent->IsValid() && opEvent->GetDestination() == destination)
214  return opEvent;
215  }
216 
217  return nullptr;
218 }
219 
220 int mitk::LimitedLinearUndo::FirstObjectEventIdOfCurrentGroup(mitk::LimitedLinearUndo::UndoContainer &stack)
221 {
222  int currentGroupEventId = stack.back()->GetGroupEventId();
223  int firstObjectEventId = -1;
224 
225  for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter)
226  {
227  if ((*iter)->GetGroupEventId() == currentGroupEventId)
228  {
229  firstObjectEventId = (*iter)->GetObjectEventId();
230  }
231  else
232  break;
233  }
234 
235  return firstObjectEventId;
236 }
bool Redo() override
Undoes the last changes.
std::vcl_size_t GetUndoLimit() const override
Gets the limit on the size of the undo history. The undo limit determines how many items can be store...
void ClearList(UndoContainer *list)
bool Undo() override
Undoes the last changes.
void ClearRedoList() override
Clears the RedoList.
abstract class, that can be used by Undo to undo an operation.
void Clear() override
Clears UndoList and RedoList.
static RenderingManager * GetInstance()
OperationEvent * GetLastOfType(OperationActor *destination, OperationType opType) override
Returns the last specified OperationEvent in Undo-list corresponding to the given values; if nothing ...
bool RedoListEmpty() override
True, if RedoList is empty.
Represents an entry of the undo or redo stack.
bool SetOperationEvent(UndoStackItem *stackItem) override
int OperationType
Definition: mitkOperation.h:23
int GetLastGroupEventIdInList() override
Returns the GroupEventId of the top element in the OperationHistory.
std::deque< UndoStackItem * > UndoContainer
int GetLastObjectEventIdInList() override
Returns the ObjectEventId of the top element in the OperationHistory.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Represents a pair of operations: undo and the according redo.
void SetUndoLimit(std::vcl_size_t limit) override
Sets a limit on the size of the undo history. If the limit is reached, the oldest undo items will be ...