Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.