Commit fb9a4c2b authored by Maciej Suminski's avatar Maciej Suminski

Added stacking for tools.

parent 424aa28e
...@@ -56,11 +56,6 @@ void TOOL_INTERACTIVE::goInternal( TOOL_STATE_FUNC& aState, const TOOL_EVENT_LIS ...@@ -56,11 +56,6 @@ void TOOL_INTERACTIVE::goInternal( TOOL_STATE_FUNC& aState, const TOOL_EVENT_LIS
} }
void TOOL_INTERACTIVE::Reset()
{
}
void TOOL_INTERACTIVE::SetContextMenu( CONTEXT_MENU* aMenu, TOOL_ContextMenuTrigger aTrigger ) void TOOL_INTERACTIVE::SetContextMenu( CONTEXT_MENU* aMenu, TOOL_ContextMenuTrigger aTrigger )
{ {
aMenu->setTool( this ); aMenu->setTool( this );
......
...@@ -92,24 +92,40 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) ...@@ -92,24 +92,40 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool )
} }
void TOOL_MANAGER::InvokeTool( TOOL_ID aToolId ) bool TOOL_MANAGER::InvokeTool( TOOL_ID aToolId )
{ {
TOOL_BASE* tool = FindTool( aToolId ); TOOL_BASE* tool = FindTool( aToolId );
if( tool && tool->GetType() == TOOL_Interactive ) if( tool && tool->GetType() == TOOL_Interactive )
{
// If the tool is already active, do not invoke it again
if( m_toolIdIndex[aToolId]->idle == false )
return false;
m_toolIdIndex[aToolId]->idle = false;
static_cast<TOOL_INTERACTIVE*>( tool )->Reset(); static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
TOOL_EVENT evt( TC_Command, TA_ActivateTool, tool->GetName() ); TOOL_EVENT evt( TC_Command, TA_ActivateTool, tool->GetName() );
ProcessEvent( evt ); ProcessEvent( evt );
// Save the tool on the front of the processing queue
m_activeTools.push_front( aToolId );
return true;
}
return false;
} }
void TOOL_MANAGER::InvokeTool( const std::string& aName ) bool TOOL_MANAGER::InvokeTool( const std::string& aName )
{ {
TOOL_BASE* tool = FindTool( aName ); TOOL_BASE* tool = FindTool( aName );
if( tool ) if( tool )
InvokeTool( tool->GetId() ); return InvokeTool( tool->GetId() );
return false;
} }
...@@ -159,13 +175,18 @@ optional<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool, ...@@ -159,13 +175,18 @@ optional<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool,
void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
{ {
// iterate over all registered tools // iterate over all registered tools
BOOST_FOREACH( ToolState* st, m_toolState | boost::adaptors::map_values ) BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
{ {
ToolState* st = m_toolIdIndex[toolId];
// the tool state handler is waiting for events (i.e. called Wait() method) // the tool state handler is waiting for events (i.e. called Wait() method)
if( st->pendingWait ) if( st->pendingWait )
{ {
if( st->waitEvents.Matches( aEvent ) ) if( st->waitEvents.Matches( aEvent ) )
{ {
// By default, already processed events are not passed further
m_passEvent = false;
// got matching event? clear wait list and wake up the coroutine // got matching event? clear wait list and wake up the coroutine
st->wakeupEvent = aEvent; st->wakeupEvent = aEvent;
st->pendingWait = false; st->pendingWait = false;
...@@ -173,16 +194,22 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) ...@@ -173,16 +194,22 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
st->cofunc->Resume(); st->cofunc->Resume();
if( !st->cofunc->Running() ) if( !st->cofunc->Running() )
{ {
delete st->cofunc; finishTool( st );
st->cofunc = NULL;
} }
// The tool requested to stop propagating event to other tools
if( !m_passEvent )
break;
} }
} }
else }
BOOST_FOREACH( ToolState* st, m_toolState | boost::adaptors::map_values )
{
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->transitions.size() )
{ {
BOOST_FOREACH( Transition tr, st->transitions ) BOOST_FOREACH( Transition tr, st->transitions )
...@@ -201,8 +228,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) ...@@ -201,8 +228,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
if( !st->cofunc->Running() ) if( !st->cofunc->Running() )
{ {
delete st->cofunc; finishTool( st );
st->cofunc = NULL;
} }
} }
} }
...@@ -212,14 +238,28 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) ...@@ -212,14 +238,28 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
} }
void TOOL_MANAGER::finishTool( ToolState* aState )
{
wxASSERT( m_activeTools.front() == aState->theTool->GetId() );
aState->idle = true;
m_activeTools.erase( m_activeTools.begin() );
delete aState->cofunc;
aState->cofunc = NULL;
}
bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
{ {
wxLogDebug( "event: %s", aEvent.Format().c_str() ); wxLogDebug( "event: %s", aEvent.Format().c_str() );
dispatchInternal( aEvent ); dispatchInternal( aEvent );
BOOST_FOREACH( ToolState* st, m_toolState | boost::adaptors::map_values ) BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
{ {
ToolState* st = m_toolIdIndex[toolId];
if( st->contextMenuTrigger == CMENU_NOW ) if( st->contextMenuTrigger == CMENU_NOW )
{ {
st->pendingWait = true; st->pendingWait = true;
...@@ -273,8 +313,10 @@ void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KiGfx::VIEW* aView, ...@@ -273,8 +313,10 @@ void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KiGfx::VIEW* aView,
m_editFrame = aFrame; m_editFrame = aFrame;
// Reset state of the registered tools // Reset state of the registered tools
BOOST_FOREACH( TOOL_BASE* tool, m_toolState | boost::adaptors::map_keys ) BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
{ {
TOOL_BASE* tool = m_toolIdIndex[toolId]->theTool;
if( tool->GetType() == TOOL_Interactive ) if( tool->GetType() == TOOL_Interactive )
static_cast<TOOL_INTERACTIVE*>( tool )->Reset(); static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
} }
......
...@@ -72,8 +72,8 @@ public: ...@@ -72,8 +72,8 @@ public:
* Calls a tool by sending a tool activation event to tool of given ID or name. * Calls a tool by sending a tool activation event to tool of given ID or name.
* An user-defined parameter object can be also passed * An user-defined parameter object can be also passed
*/ */
void InvokeTool( TOOL_ID aToolId ); bool InvokeTool( TOOL_ID aToolId );
void InvokeTool( const std::string& aName ); bool InvokeTool( const std::string& aName );
template <class Parameters> template <class Parameters>
void InvokeTool( const std::string& aName, const Parameters& aToolParams ); void InvokeTool( const std::string& aName, const Parameters& aToolParams );
...@@ -153,20 +153,31 @@ public: ...@@ -153,20 +153,31 @@ public:
void ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu, void ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu,
TOOL_ContextMenuTrigger aTrigger ); TOOL_ContextMenuTrigger aTrigger );
private: /**
void dispatchInternal( TOOL_EVENT& aEvent ); * Allows a tool pass the already handled event to be passed to the next tool on the stack.
*/
void PassEvent()
{
m_passEvent = true;
}
private:
struct ToolState; struct ToolState;
typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> Transition; typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> Transition;
void dispatchInternal( TOOL_EVENT& aEvent );
void finishTool( ToolState* aState );
std::map<TOOL_BASE*, ToolState*> m_toolState; std::map<TOOL_BASE*, ToolState*> m_toolState;
std::map<std::string, ToolState*> m_toolNameIndex; std::map<std::string, ToolState*> m_toolNameIndex;
std::map<TOOL_ID, ToolState*> m_toolIdIndex; std::map<TOOL_ID, ToolState*> m_toolIdIndex;
std::deque<TOOL_ID> m_activeTools;
EDA_ITEM* m_model; EDA_ITEM* m_model;
KiGfx::VIEW* m_view; KiGfx::VIEW* m_view;
KiGfx::VIEW_CONTROLS* m_viewControls; KiGfx::VIEW_CONTROLS* m_viewControls;
wxWindow* m_editFrame; wxWindow* m_editFrame;
bool m_passEvent;
ToolState* m_currentTool; ToolState* m_currentTool;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment