00001 /*========================================================================= 00002 00003 Program: Medical Imaging & Interaction Toolkit 00004 Language: C++ 00005 Date: $Date$ 00006 Version: $Revision$ 00007 00008 Copyright (c) German Cancer Research Center, Division of Medical and 00009 Biological Informatics. All rights reserved. 00010 See MITKCopyright.txt or https://www.mitk.org/copyright.html for details. 00011 00012 This software is distributed WITHOUT ANY WARRANTY; without even 00013 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00014 PURPOSE. See the above copyright notices for more information. 00015 00016 =========================================================================*/ 00017 00018 00019 #ifndef OPERATIONEVENT_H_HEADER_INCLUDED_C16E83FC 00020 #define OPERATIONEVENT_H_HEADER_INCLUDED_C16E83FC 00021 00022 #include "mitkCommon.h" 00023 #include "mitkOperation.h" 00024 #include "mitkOperationActor.h" 00025 #include "mitkUndoModel.h" 00026 #include <string> 00027 #include <list> 00028 00029 namespace mitk { 00030 00031 //##Documentation 00032 //## @brief Represents an entry of the undo or redo stack. 00033 //## 00034 //## This basic entry includes a textual description of the item and a pair of IDs. Static 00035 //## member functions handle creation and incrementing of these IDs. 00036 //## 00037 //## The ObjectEventID is increased by the global EventMapper for most of the events (see 00038 //## code for details). Incrementation of the IDs is done in two steps. First the 00039 //## EventMapper sets a flag via (possibly multiple calls of) IncCurrObjectEventID(), then 00040 //## ExecuteIncrement() does the actual incementation. 00041 //## 00042 //## The GroupEventID is intended for logical grouping of several related Operations. 00043 //## Currently this is used only by PointSetInteractor. How this is done and when to use 00044 //## GroupEventIDs is still undocumented. 00045 //## @ingroup Undo 00046 class MITK_CORE_EXPORT UndoStackItem 00047 { 00048 public: 00049 UndoStackItem(std::string description = ""); 00050 00051 virtual ~UndoStackItem(); 00052 00053 //##Documentation 00054 //## @brief For combining operations in groups 00055 //## 00056 //## This ID is used in the undo mechanism. 00057 //## For separation of the seperate operations 00058 //## If the GroupEventId of two OperationEvents is equal, 00059 //## then they share one group and will be undone in case of Undo(fine==false) 00060 static int GetCurrGroupEventId(); 00061 00062 //##Documentation 00063 //## @brief For combining operations in Objects 00064 //## 00065 //## This ID is used in the Undo-Mechanism. 00066 //## For separation of the seperate operations 00067 //## If the ObjectEventId of two OperationEvents is equal, 00068 //## then they share one Object and will be undone in all cases of Undo(true and false). 00069 //## they shal not be seperated, because they were produced to realize one object-change. 00070 //## for example: OE_statechange and OE_addlastpoint 00071 static int GetCurrObjectEventId(); 00072 00073 //##Documentation 00074 //## @brief Returns the GroupEventId for this object 00075 int GetGroupEventId(); 00076 00077 //##Documentation 00078 //## @brief Returns the ObjectEventId for this object 00079 int GetObjectEventId(); 00080 00081 //##Documentation 00082 //## @brief Returns the textual description of this object 00083 std::string GetDescription(); 00084 00085 virtual void ReverseOperations(); 00086 virtual void ReverseAndExecute(); 00087 00088 //##Documentation 00089 //## @brief Sets the current ObjectEventId to be incremended when ExecuteIncrement is called 00090 //## For example if a button click generates operations the ObjectEventId has to be incremented to be able to undo the operations. 00091 //## Difference between ObjectEventId and GroupEventId: The ObjectEventId capsulates all operations caused by one event. 00092 //## A GroupEventId capsulates several ObjectEventIds so that several operations caused by several events can be undone with one Undo call. 00093 static void IncCurrObjectEventId(); 00094 00095 //##Documentation 00096 //## @brief Sets the current GroupEventId to be incremended when ExecuteIncrement is called 00097 //## For example if a button click generates operations the GroupEventId has to be incremented to be able to undo the operations. 00098 //## Difference between ObjectEventId and GroupEventId: The ObjectEventId capsulates all operations caused by one event. 00099 //## A GroupEventId capsulates several ObjectEventIds so that several operations caused by several events can be undone with one Undo call. 00100 static void IncCurrGroupEventId(); 00101 00102 //##Documentation 00103 //## @brief Executes the incrementation of objectEventId and groupEventId if they are set to be incremented 00104 static void ExecuteIncrement(); 00105 00106 protected: 00107 //##Documentation 00108 //## @brief true, if operation and undooperation have been swaped/changed 00109 bool m_Reversed; 00110 00111 private: 00112 static int m_CurrObjectEventId; 00113 00114 static int m_CurrGroupEventId; 00115 00116 static bool m_IncrObjectEventId; 00117 00118 static bool m_IncrGroupEventId; 00119 00120 int m_ObjectEventId; 00121 00122 int m_GroupEventId; 00123 00124 std::string m_Description; 00125 00126 UndoStackItem(UndoStackItem&); // hide copy constructor 00127 void operator=(const UndoStackItem&); // hide operator= 00128 00129 }; 00130 00131 //##Documentation 00132 //## @brief Represents a pair of operations: undo and the according redo. 00133 //## 00134 //## Additionally to the base class UndoStackItem, which only provides a description of an 00135 //## item, OperationEvent does the actual accounting of the undo/redo stack. This class 00136 //## holds two Operation objects (operation and its inverse operation) and the corresponding 00137 //## OperationActor. The operations may be swapped by the 00138 //## undo models, when an OperationEvent is moved from their undo to their redo 00139 //## stack or vice versa. 00140 //## 00141 //## Note, that memory management of operation and undooperation is done by this class. 00142 //## Memory of both objects is freed in the destructor. For this, the method IsValid() is needed which holds 00143 //## information of the state of m_Destination. In case the object referenced by m_Destination is already deleted, 00144 //## isValid() returns false. 00145 //## In more detail if the destination happens to be an itk::Object (often the case), OperationEvent is informed as soon 00146 //## as the object is deleted - from this moment on the OperationEvent gets invalid. You should 00147 //## check this flag before you call anything on destination 00148 //## 00149 //## @ingroup Undo 00150 class MITK_CORE_EXPORT OperationEvent : public UndoStackItem 00151 { 00152 public: 00153 //## @brief default constructor 00154 OperationEvent(OperationActor* destination, Operation* operation, Operation* undoOperation, std::string description = "" ); 00155 00156 //## @brief default destructor 00157 //## 00158 //## removes observers if destination is valid 00159 //## and frees memory referenced by m_Operation and m_UndoOperation 00160 virtual ~OperationEvent(); 00161 00162 //## @brief Returns the operation 00163 Operation* GetOperation(); 00164 00165 //## @brief Returns the destination of the operations 00166 OperationActor* GetDestination(); 00167 00168 friend class UndoModel; 00169 00170 //## @brief Swaps the two operations and sets a flag, 00171 //## that it has been swapped and doOp is undoOp and undoOp is doOp 00172 virtual void ReverseOperations(); 00173 00174 //##reverses and executes both operations (used, when moved from undo to redo stack) 00175 virtual void ReverseAndExecute(); 00176 00177 //## @brief returns true if the destination still is present 00178 //## and false if it already has been deleted 00179 virtual bool IsValid(); 00180 00181 protected: 00182 00183 void OnObjectDeleted(); 00184 00185 private: 00186 00187 // Has to be observed for itk::DeleteEvents. 00188 // When destination is deleted, this stack item is invalid! 00189 OperationActor* m_Destination; 00190 00191 //## reference to the operation 00192 Operation* m_Operation; 00193 00194 //## reference to the undo operation 00195 Operation* m_UndoOperation; 00196 00197 //## hide copy constructor 00198 OperationEvent(OperationEvent&); 00199 //## hide operator= 00200 void operator=(const OperationEvent&); 00201 00202 //observertag used to listen to m_Destination 00203 unsigned long m_DeleteTag; 00204 00205 //## stores if destination is valid or already has been freed 00206 bool m_Invalid; 00207 }; 00208 00209 } //namespace mitk 00210 00211 #endif /* OPERATIONEVENT_H_HEADER_INCLUDED_C16E83FC */