Loading common/tool/tool_manager.cpp +115 −46 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include <map> #include <map> #include <deque> #include <deque> #include <stack> #include <algorithm> #include <boost/foreach.hpp> #include <boost/foreach.hpp> #include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp> Loading @@ -51,6 +53,32 @@ using boost::optional; /// Struct describing the current execution state of a TOOL /// Struct describing the current execution state of a TOOL struct TOOL_MANAGER::TOOL_STATE struct TOOL_MANAGER::TOOL_STATE { { TOOL_STATE( TOOL_BASE* aTool ) : theTool( aTool ) { clear(); } TOOL_STATE( const TOOL_STATE& aState ) { theTool = aState.theTool; idle = aState.idle; pendingWait = aState.pendingWait; pendingContextMenu = aState.pendingContextMenu; contextMenu = aState.contextMenu; contextMenuTrigger = aState.contextMenuTrigger; cofunc = aState.cofunc; wakeupEvent = aState.wakeupEvent; waitEvents = aState.waitEvents; transitions = aState.transitions; // do not copy stateStack } ~TOOL_STATE() { assert( stateStack.empty() ); } /// The tool itself /// The tool itself TOOL_BASE* theTool; TOOL_BASE* theTool; Loading Loading @@ -83,6 +111,21 @@ struct TOOL_MANAGER::TOOL_STATE /// upon the event reception /// upon the event reception std::vector<TRANSITION> transitions; std::vector<TRANSITION> transitions; void operator=( const TOOL_STATE& aState ) { theTool = aState.theTool; idle = aState.idle; pendingWait = aState.pendingWait; pendingContextMenu = aState.pendingContextMenu; contextMenu = aState.contextMenu; contextMenuTrigger = aState.contextMenuTrigger; cofunc = aState.cofunc; wakeupEvent = aState.wakeupEvent; waitEvents = aState.waitEvents; transitions = aState.transitions; // do not copy stateStack } bool operator==( const TOOL_MANAGER::TOOL_STATE& aRhs ) const bool operator==( const TOOL_MANAGER::TOOL_STATE& aRhs ) const { { return aRhs.theTool == this->theTool; return aRhs.theTool == this->theTool; Loading @@ -92,6 +135,48 @@ struct TOOL_MANAGER::TOOL_STATE { { return aRhs.theTool != this->theTool; return aRhs.theTool != this->theTool; } } void Push() { stateStack.push( *this ); clear(); } bool Pop() { delete cofunc; if( !stateStack.empty() ) { *this = stateStack.top(); stateStack.pop(); return true; } else { cofunc = NULL; return false; } } private: ///> Stack preserving previous states of a TOOL. std::stack<TOOL_STATE> stateStack; ///> Restores the initial state. void clear() { idle = true; pendingWait = false; pendingContextMenu = false; cofunc = NULL; contextMenu = NULL; contextMenuTrigger = CMENU_OFF; transitions.clear(); } }; }; Loading @@ -118,7 +203,6 @@ TOOL_MANAGER::~TOOL_MANAGER() delete it->first; // delete the tool itself delete it->first; // delete the tool itself } } m_toolState.clear(); delete m_actionMgr; delete m_actionMgr; } } Loading @@ -132,13 +216,7 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) wxASSERT_MSG( m_toolTypes.find( typeid( *aTool ).name() ) == m_toolTypes.end(), wxASSERT_MSG( m_toolTypes.find( typeid( *aTool ).name() ) == m_toolTypes.end(), wxT( "Adding two tools of the same type may result in unexpected behaviour.") ); wxT( "Adding two tools of the same type may result in unexpected behaviour.") ); TOOL_STATE* st = new TOOL_STATE; TOOL_STATE* st = new TOOL_STATE( aTool ); st->theTool = aTool; st->pendingWait = false; st->pendingContextMenu = false; st->cofunc = NULL; st->contextMenuTrigger = CMENU_OFF; m_toolState[aTool] = st; m_toolState[aTool] = st; m_toolNameIndex[aTool->GetName()] = st; m_toolNameIndex[aTool->GetName()] = st; Loading Loading @@ -378,26 +456,23 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) } } BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) { // the tool scheduled next state(s) by calling Go() if( !st->pendingWait ) { { // no state handler in progress - check if there are any transitions (defined by // no state handler in progress - check if there are any transitions (defined by // Go() method that match the event. // Go() method that match the event. if( st->transitions.size() ) if( !st->pendingWait && !st->transitions.empty() ) { { BOOST_FOREACH( TRANSITION& tr, st->transitions ) BOOST_FOREACH( TRANSITION& tr, st->transitions ) { { if( tr.first.Matches( aEvent ) ) if( tr.first.Matches( aEvent ) ) { { // no tool context allocated yet? Create one. if( st->cofunc ) st->Push(); // as the state changes, the transition table has to be set up again // as the state changes, the transition table has to be set up again st->transitions.clear(); st->transitions.clear(); // no tool context allocated yet? Create one. if( !st->cofunc ) st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second ); st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second ); else st->cofunc->SetEntry( tr.second ); // got match? Run the handler. // got match? Run the handler. st->cofunc->Call( aEvent ); st->cofunc->Call( aEvent ); Loading @@ -412,7 +487,6 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) } } } } } } } bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent ) bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent ) Loading Loading @@ -451,20 +525,15 @@ bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent ) void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) { { std::deque<TOOL_ID>::iterator it, itEnd; if( !aState->Pop() ) // if there are no other contexts saved on the stack // Find the tool and deactivate it for( it = m_activeTools.begin(), itEnd = m_activeTools.end(); it != itEnd; ++it ) { if( aState == m_toolIdIndex[*it] ) { { m_activeTools.erase( it ); // find the tool and deactivate it break; std::deque<TOOL_ID>::iterator tool = std::find( m_activeTools.begin(), m_activeTools.end(), } aState->theTool->GetId() ); } delete aState->cofunc; if( tool != m_activeTools.end() ) aState->cofunc = NULL; m_activeTools.erase( tool ); } } } Loading Loading
common/tool/tool_manager.cpp +115 −46 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include <map> #include <map> #include <deque> #include <deque> #include <stack> #include <algorithm> #include <boost/foreach.hpp> #include <boost/foreach.hpp> #include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp> Loading @@ -51,6 +53,32 @@ using boost::optional; /// Struct describing the current execution state of a TOOL /// Struct describing the current execution state of a TOOL struct TOOL_MANAGER::TOOL_STATE struct TOOL_MANAGER::TOOL_STATE { { TOOL_STATE( TOOL_BASE* aTool ) : theTool( aTool ) { clear(); } TOOL_STATE( const TOOL_STATE& aState ) { theTool = aState.theTool; idle = aState.idle; pendingWait = aState.pendingWait; pendingContextMenu = aState.pendingContextMenu; contextMenu = aState.contextMenu; contextMenuTrigger = aState.contextMenuTrigger; cofunc = aState.cofunc; wakeupEvent = aState.wakeupEvent; waitEvents = aState.waitEvents; transitions = aState.transitions; // do not copy stateStack } ~TOOL_STATE() { assert( stateStack.empty() ); } /// The tool itself /// The tool itself TOOL_BASE* theTool; TOOL_BASE* theTool; Loading Loading @@ -83,6 +111,21 @@ struct TOOL_MANAGER::TOOL_STATE /// upon the event reception /// upon the event reception std::vector<TRANSITION> transitions; std::vector<TRANSITION> transitions; void operator=( const TOOL_STATE& aState ) { theTool = aState.theTool; idle = aState.idle; pendingWait = aState.pendingWait; pendingContextMenu = aState.pendingContextMenu; contextMenu = aState.contextMenu; contextMenuTrigger = aState.contextMenuTrigger; cofunc = aState.cofunc; wakeupEvent = aState.wakeupEvent; waitEvents = aState.waitEvents; transitions = aState.transitions; // do not copy stateStack } bool operator==( const TOOL_MANAGER::TOOL_STATE& aRhs ) const bool operator==( const TOOL_MANAGER::TOOL_STATE& aRhs ) const { { return aRhs.theTool == this->theTool; return aRhs.theTool == this->theTool; Loading @@ -92,6 +135,48 @@ struct TOOL_MANAGER::TOOL_STATE { { return aRhs.theTool != this->theTool; return aRhs.theTool != this->theTool; } } void Push() { stateStack.push( *this ); clear(); } bool Pop() { delete cofunc; if( !stateStack.empty() ) { *this = stateStack.top(); stateStack.pop(); return true; } else { cofunc = NULL; return false; } } private: ///> Stack preserving previous states of a TOOL. std::stack<TOOL_STATE> stateStack; ///> Restores the initial state. void clear() { idle = true; pendingWait = false; pendingContextMenu = false; cofunc = NULL; contextMenu = NULL; contextMenuTrigger = CMENU_OFF; transitions.clear(); } }; }; Loading @@ -118,7 +203,6 @@ TOOL_MANAGER::~TOOL_MANAGER() delete it->first; // delete the tool itself delete it->first; // delete the tool itself } } m_toolState.clear(); delete m_actionMgr; delete m_actionMgr; } } Loading @@ -132,13 +216,7 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) wxASSERT_MSG( m_toolTypes.find( typeid( *aTool ).name() ) == m_toolTypes.end(), wxASSERT_MSG( m_toolTypes.find( typeid( *aTool ).name() ) == m_toolTypes.end(), wxT( "Adding two tools of the same type may result in unexpected behaviour.") ); wxT( "Adding two tools of the same type may result in unexpected behaviour.") ); TOOL_STATE* st = new TOOL_STATE; TOOL_STATE* st = new TOOL_STATE( aTool ); st->theTool = aTool; st->pendingWait = false; st->pendingContextMenu = false; st->cofunc = NULL; st->contextMenuTrigger = CMENU_OFF; m_toolState[aTool] = st; m_toolState[aTool] = st; m_toolNameIndex[aTool->GetName()] = st; m_toolNameIndex[aTool->GetName()] = st; Loading Loading @@ -378,26 +456,23 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) } } BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) { // the tool scheduled next state(s) by calling Go() if( !st->pendingWait ) { { // no state handler in progress - check if there are any transitions (defined by // no state handler in progress - check if there are any transitions (defined by // Go() method that match the event. // Go() method that match the event. if( st->transitions.size() ) if( !st->pendingWait && !st->transitions.empty() ) { { BOOST_FOREACH( TRANSITION& tr, st->transitions ) BOOST_FOREACH( TRANSITION& tr, st->transitions ) { { if( tr.first.Matches( aEvent ) ) if( tr.first.Matches( aEvent ) ) { { // no tool context allocated yet? Create one. if( st->cofunc ) st->Push(); // as the state changes, the transition table has to be set up again // as the state changes, the transition table has to be set up again st->transitions.clear(); st->transitions.clear(); // no tool context allocated yet? Create one. if( !st->cofunc ) st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second ); st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second ); else st->cofunc->SetEntry( tr.second ); // got match? Run the handler. // got match? Run the handler. st->cofunc->Call( aEvent ); st->cofunc->Call( aEvent ); Loading @@ -412,7 +487,6 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) } } } } } } } bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent ) bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent ) Loading Loading @@ -451,20 +525,15 @@ bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent ) void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) { { std::deque<TOOL_ID>::iterator it, itEnd; if( !aState->Pop() ) // if there are no other contexts saved on the stack // Find the tool and deactivate it for( it = m_activeTools.begin(), itEnd = m_activeTools.end(); it != itEnd; ++it ) { if( aState == m_toolIdIndex[*it] ) { { m_activeTools.erase( it ); // find the tool and deactivate it break; std::deque<TOOL_ID>::iterator tool = std::find( m_activeTools.begin(), m_activeTools.end(), } aState->theTool->GetId() ); } delete aState->cofunc; if( tool != m_activeTools.end() ) aState->cofunc = NULL; m_activeTools.erase( tool ); } } } Loading