Medical Imaging Interaction Toolkit  2016.11.0
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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkLimitedLinearUndo.h"
18 #include <mitkRenderingManager.h>
19 
21 {
22  // nothing to do
23 }
24 
26 {
27  // delete undo and redo list
28  this->ClearList(&m_UndoList);
29  this->ClearList(&m_RedoList);
30 }
31 
33 {
34  while (!list->empty())
35  {
36  UndoStackItem *item = list->back();
37  list->pop_back();
38  delete item;
39  }
40 }
41 
43 {
44  OperationEvent *operationEvent = dynamic_cast<OperationEvent *>(stackItem);
45  if (!operationEvent)
46  return false;
47 
48  // clear the redolist, if a new operation is saved
49  if (!m_RedoList.empty())
50  {
51  this->ClearList(&m_RedoList);
52  InvokeEvent(RedoEmptyEvent());
53  }
54 
55  m_UndoList.push_back(operationEvent);
56 
57  InvokeEvent(UndoNotEmptyEvent());
58 
59  return true;
60 }
61 
63 {
64  if (fine)
65  {
66  // undo one object event ID
67  return Undo();
68  }
69  else
70  {
71  // undo one group event ID
72  int oeid = FirstObjectEventIdOfCurrentGroup(
73  m_UndoList); // get the Object Event ID of the first item with a differnt Group ID (as seen from the end of stack)
74  return Undo(oeid);
75  }
76 }
77 
79 {
80  if (m_UndoList.empty())
81  return false;
82 
83  int undoObjectEventId = m_UndoList.back()->GetObjectEventId();
84  return Undo(undoObjectEventId);
85 }
86 
88 {
89  if (m_UndoList.empty())
90  return false;
91 
92  bool rc = true;
93  do
94  {
95  m_UndoList.back()->ReverseAndExecute();
96 
97  m_RedoList.push_back(m_UndoList.back()); // move to redo stack
98  m_UndoList.pop_back();
99  InvokeEvent(RedoNotEmptyEvent());
100 
101  if (m_UndoList.empty())
102  {
103  InvokeEvent(UndoEmptyEvent());
104  rc = false;
105  break;
106  }
107  } while (m_UndoList.back()->GetObjectEventId() >= oeid);
108 
109  // Update. Check Rendering Mechanism where to request updates
111  return rc;
112 }
113 
115 {
116  return Redo();
117 }
118 
120 {
121  if (m_RedoList.empty())
122  return false;
123 
124  int redoObjectEventId = m_RedoList.back()->GetObjectEventId();
125  return Redo(redoObjectEventId);
126 }
127 
129 {
130  if (m_RedoList.empty())
131  return false;
132 
133  do
134  {
135  m_RedoList.back()->ReverseAndExecute();
136 
137  m_UndoList.push_back(m_RedoList.back());
138  m_RedoList.pop_back();
139  InvokeEvent(UndoNotEmptyEvent());
140 
141  if (m_RedoList.empty())
142  {
143  InvokeEvent(RedoEmptyEvent());
144  break;
145  }
146  } while (m_RedoList.back()->GetObjectEventId() <= oeid);
147 
148  // Update. This should belong into the ExecuteOperation() of OperationActors, but it seems not to be used everywhere
150  return true;
151 }
152 
154 {
155  this->ClearList(&m_UndoList);
156  InvokeEvent(UndoEmptyEvent());
157 
158  this->ClearList(&m_RedoList);
159  InvokeEvent(RedoEmptyEvent());
160 }
161 
163 {
164  this->ClearList(&m_RedoList);
165  InvokeEvent(RedoEmptyEvent());
166 }
167 
169 {
170  return m_RedoList.empty();
171 }
172 
174 {
175  return m_UndoList.back()->GetObjectEventId();
176 }
177 
179 {
180  return m_UndoList.back()->GetGroupEventId();
181 }
182 
184 {
185  // When/where is this function needed? In CoordinateSupplier...
186  for (auto iter = m_UndoList.rbegin(); iter != m_UndoList.rend(); ++iter)
187  {
188  OperationEvent *opEvent = dynamic_cast<OperationEvent *>(*iter);
189  if (!opEvent)
190  continue;
191 
192  if (opEvent->GetOperation() != nullptr && opEvent->GetOperation()->GetOperationType() == opType &&
193  opEvent->IsValid() && opEvent->GetDestination() == destination)
194  return opEvent;
195  }
196 
197  return nullptr;
198 }
199 
200 int mitk::LimitedLinearUndo::FirstObjectEventIdOfCurrentGroup(mitk::LimitedLinearUndo::UndoContainer &stack)
201 {
202  int currentGroupEventId = stack.back()->GetGroupEventId();
203  int firstObjectEventId = -1;
204 
205  for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter)
206  {
207  if ((*iter)->GetGroupEventId() == currentGroupEventId)
208  {
209  firstObjectEventId = (*iter)->GetObjectEventId();
210  }
211  else
212  break;
213  }
214 
215  return firstObjectEventId;
216 }
virtual bool Redo() override
Undoes the last changes.
void ClearList(UndoContainer *list)
virtual bool Undo() override
Undoes the last changes.
virtual void ClearRedoList() override
Clears the RedoList.
OperationActor * GetDestination()
abstract class, that can be used by Undo to undo an operation.
virtual void Clear() override
Clears UndoList and RedoList.
static RenderingManager * GetInstance()
virtual OperationEvent * GetLastOfType(OperationActor *destination, OperationType opType) override
Returns the last specified OperationEvent in Undo-list corresponding to the given values; if nothing ...
virtual bool RedoListEmpty() override
True, if RedoList is empty.
Represents an entry of the undo or redo stack.
virtual bool SetOperationEvent(UndoStackItem *stackItem) override
int OperationType
Definition: mitkOperation.h:27
virtual int GetLastGroupEventIdInList() override
Returns the GroupEventId of the top element in the OperationHistory.
std::vector< UndoStackItem * > UndoContainer
OperationType GetOperationType()
virtual 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.