Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkStateMachine.h"
00019 #include "mitkStateTransitionOperation.h"
00020 #include "mitkInteractionConst.h"
00021 #include "mitkInteractor.h"
00022 #include "mitkTransition.h"
00023 #include "mitkOperationEvent.h"
00024 #include "mitkStateEvent.h"
00025 #include "mitkAction.h"
00026 #include "mitkUndoController.h"
00027 #include <itkMacro.h>
00028 #include "mitkGlobalInteraction.h"
00029 #include <mbilog.h>
00030
00031
00038 mitk::StateMachine::StateMachine(const char * type)
00039 : m_UndoController(NULL), m_Type("")
00040 {
00041 if(type!=NULL)
00042 {
00043 m_Type = type;
00044
00045
00046 this->InitializeStartStates(1);
00047 }
00048
00049 if (!m_UndoController)
00050 {
00051 m_UndoController = new UndoController(UndoController::VERBOSE_LIMITEDLINEARUNDO);
00052
00056 m_UndoEnabled = true;
00057 }
00058
00059 m_TimeStep = 0;
00060 }
00061
00062 mitk::StateMachine::~StateMachine()
00063 {
00064
00065 for ( mitk::StateMachine::ActionFunctionsMapType::iterator iter = m_ActionFunctionsMap.begin();
00066 iter != m_ActionFunctionsMap.end();
00067 ++iter )
00068 {
00069 delete iter->second;
00070 }
00071
00072 delete m_UndoController;
00073 }
00074
00075 std::string mitk::StateMachine::GetType() const
00076 {
00077 return m_Type;
00078 }
00079
00080 const mitk::State* mitk::StateMachine::GetCurrentState(unsigned int timeStep) const
00081 {
00082 if (m_CurrentStateVector.size() > timeStep)
00083 return m_CurrentStateVector[timeStep].GetPointer();
00084 return NULL;
00085 }
00086
00087 void mitk::StateMachine::ResetStatemachineToStartState(unsigned int timeStep)
00088 {
00089 mitk::State* startState = mitk::GlobalInteraction::GetInstance()->GetStartState((const char *)(&m_Type[0]));
00090
00091 if ( m_UndoEnabled )
00092 {
00093
00094 StateTransitionOperation* doOp = new StateTransitionOperation(OpSTATECHANGE, startState, timeStep);
00095 StateTransitionOperation* undoOp = new StateTransitionOperation(OpSTATECHANGE, m_CurrentStateVector[timeStep], timeStep);
00096 OperationEvent *operationEvent = new OperationEvent(((mitk::OperationActor*)(this)), doOp, undoOp);
00097 m_UndoController->SetOperationEvent(operationEvent);
00098 }
00099
00100 m_CurrentStateVector[timeStep] = startState;
00101
00102 }
00103
00104 bool mitk::StateMachine::HandleEvent(StateEvent const* stateEvent)
00105 {
00106 if (stateEvent == NULL)
00107 return false;
00108
00109 if (m_CurrentStateVector.empty())
00110 {
00111 STATEMACHINE_ERROR << "Error in mitkStateMachine.cpp: StateMachine not initialized!\n";
00112 return false;
00113 }
00114
00115 if (m_TimeStep >= m_CurrentStateVector.size())
00116 {
00117 STATEMACHINE_ERROR << "Error in mitkStateMachine.cpp: StateMachine not initialized for this time step!\n";
00118 return false;
00119 }
00120
00121 if (m_CurrentStateVector[m_TimeStep].IsNull())
00122 {
00123 STATEMACHINE_ERROR << "Error in mitkStateMachine.cpp: StateMachine not initialized with the right temporal information!\n";
00124 return false;
00125 }
00126
00127
00128 const Transition *tempTransition = m_CurrentStateVector[m_TimeStep]->GetTransition(stateEvent->GetId());
00129 if (tempTransition == NULL)
00130 {
00131 return false;
00132 }
00133
00134
00135 State *tempNextState = tempTransition->GetNextState();
00136 if (tempNextState == NULL)
00137 {
00138 STATEMACHINE_ERROR << "Error in mitkStateMachine.cpp: StateMachinePattern not defined correctly!\n";
00139 return false;
00140 }
00141
00142
00143 if ( m_CurrentStateVector[m_TimeStep]->GetId() != tempNextState->GetId() )
00144 {
00145 if ( m_UndoEnabled )
00146 {
00147
00148 StateTransitionOperation* doOp = new StateTransitionOperation(OpSTATECHANGE, tempNextState, m_TimeStep);
00149 StateTransitionOperation* undoOp = new StateTransitionOperation(OpSTATECHANGE, m_CurrentStateVector[m_TimeStep], m_TimeStep);
00150 OperationEvent *operationEvent = new OperationEvent(((mitk::OperationActor*)(this)), doOp, undoOp);
00151 m_UndoController->SetOperationEvent(operationEvent);
00152 }
00153
00154 STATEMACHINE_DEBUG("StateChange")<<this->GetType()<<" from " << m_CurrentStateVector[m_TimeStep]->GetId()
00155 << " " << m_CurrentStateVector[m_TimeStep]->GetName()
00156 <<" to " << tempNextState->GetId() <<" "<<tempNextState->GetName();
00157
00158
00159 m_CurrentStateVector[m_TimeStep] = tempNextState;
00160 }
00161
00162 mitk::Transition::ActionVectorIterator actionIdIterator = tempTransition->GetActionBeginIterator();
00163 mitk::Transition::ActionVectorConstIterator actionIdIteratorEnd = tempTransition->GetActionEndIterator();
00164 bool ok = true;
00165
00166 while ( actionIdIterator != actionIdIteratorEnd )
00167 {
00168 if ( !ExecuteAction(*actionIdIterator, stateEvent) )
00169 {
00170 ok = false;
00171 }
00172 actionIdIterator++;
00173 }
00174 return ok;
00175 }
00176
00177 void mitk::StateMachine::EnableUndo(bool enable)
00178 {
00179 m_UndoEnabled = enable;
00180 }
00181
00182 void mitk::StateMachine::IncCurrGroupEventId()
00183 {
00184 mitk::OperationEvent::IncCurrGroupEventId();
00185 }
00186
00188 bool mitk::StateMachine::ExecuteAction(Action* action, StateEvent const* stateEvent)
00189 {
00190 if (!action) return false;
00191
00192 int actionId = action->GetActionId();
00193
00194 TStateMachineFunctor* actionFunction = m_ActionFunctionsMap[actionId];
00195 if (!actionFunction) return false;
00196
00197 bool retVal = actionFunction->DoAction(action, stateEvent);
00198 return retVal;
00199 }
00200
00201 void mitk::StateMachine::AddActionFunction(int action, mitk::TStateMachineFunctor* functor)
00202 {
00203 if (!functor) return;
00204
00205
00206 delete m_ActionFunctionsMap[action];
00207
00208 m_ActionFunctionsMap[action] = functor;
00209 }
00210
00211
00212 void mitk::StateMachine::ExecuteOperation(Operation* operation)
00213 {
00214 switch (operation->GetOperationType())
00215 {
00216 case OpNOTHING:
00217 break;
00218 case OpSTATECHANGE:
00219 {
00220 mitk::StateTransitionOperation* stateTransOp = dynamic_cast<mitk::StateTransitionOperation *>(operation);
00221 if (stateTransOp == NULL)
00222 {
00223 STATEMACHINE_WARN<<"Error! see mitkStateMachine.cpp";
00224 return;
00225 }
00226 unsigned int time = stateTransOp->GetTime();
00227 m_CurrentStateVector[time] = stateTransOp->GetState();
00228 }
00229 break;
00230 case OpTIMECHANGE:
00231 {
00232 mitk::StateTransitionOperation* stateTransOp = dynamic_cast<mitk::StateTransitionOperation *>(operation);
00233 if (stateTransOp == NULL)
00234 {
00235 STATEMACHINE_WARN<<"Error! see mitkStateMachine.cpp";
00236 return;
00237 }
00238 m_TimeStep = stateTransOp->GetTime();
00239 }
00240 break;
00241 case OpDELETE:
00242 {
00243
00244
00245
00246 }
00247 case OpUNDELETE:
00248 {
00249
00250
00251
00252 mitk::StateTransitionOperation* stateTransOp = dynamic_cast<mitk::StateTransitionOperation *>(operation);
00253 if (stateTransOp != NULL)
00254 {
00255 unsigned int time = stateTransOp->GetTime();
00256 m_CurrentStateVector[time] = stateTransOp->GetState();
00257 }
00258 }
00259 default:
00260 ;
00261 }
00262 }
00263
00264 void mitk::StateMachine::InitializeStartStates(unsigned int timeSteps)
00265 {
00266
00267 State::Pointer startState = mitk::GlobalInteraction::GetInstance()->GetStartState(m_Type.c_str());
00268
00269 if (startState.IsNull())
00270 {
00271 STATEMACHINE_FATAL << "Fatal Error in mitkStateMachine.cpp: Initialization of statemachine unsuccessfull! Initialize GlobalInteraction!\n";
00272 }
00273
00274
00275 m_CurrentStateVector.clear();
00276
00277 for (unsigned int i = 0; i < timeSteps; i++)
00278 m_CurrentStateVector.push_back(startState);
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288 void mitk::StateMachine::ExpandStartStateVector(unsigned int timeSteps)
00289 {
00290 unsigned int oldSize = m_CurrentStateVector.size();
00291
00292 if ( timeSteps > oldSize )
00293 {
00294 State::Pointer startState = mitk::GlobalInteraction::GetInstance()->GetStartState(m_Type.c_str());
00295 for ( unsigned int i = oldSize; i < timeSteps; ++i )
00296 m_CurrentStateVector.insert(m_CurrentStateVector.end(), startState);
00297 }
00298 }
00299
00300 void mitk::StateMachine::UpdateTimeStep(unsigned int timeStep)
00301 {
00302
00303 if (timeStep == m_TimeStep)
00304 return;
00305
00306
00307 StateTransitionOperation* doOp = new StateTransitionOperation(OpTIMECHANGE, NULL, timeStep);
00308 if ( m_UndoEnabled )
00309 {
00310 StateTransitionOperation* undoOp = new StateTransitionOperation(OpTIMECHANGE, NULL, m_TimeStep);
00311 OperationEvent *operationEvent = new OperationEvent(((mitk::OperationActor*)(this)), doOp, undoOp);
00312 m_UndoController->SetOperationEvent(operationEvent);
00313 }
00314 this->ExecuteOperation(doOp);
00315 }
00316