Commit fb9a4c2b authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Added stacking for tools.

parent 424aa28e
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -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 )
{
	aMenu->setTool( this );
+58 −16
Original line number Diff line number Diff line
@@ -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 );

    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();

        TOOL_EVENT evt( TC_Command, TA_ActivateTool, tool->GetName() );
        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 );

    if( tool )
        InvokeTool( tool->GetId() );
        return InvokeTool( tool->GetId() );

    return false;
}


@@ -159,13 +175,18 @@ optional<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool,
void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
{
	// 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)
		if( st->pendingWait )
		{
			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
				st->wakeupEvent = aEvent;
				st->pendingWait = false;
@@ -173,16 +194,22 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
				st->cofunc->Resume();
				if( !st->cofunc->Running() )
				{
					delete st->cofunc;
					st->cofunc = NULL;
				    finishTool( st );
				}

				// 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
			// Go() method that match the event.

			if( st->transitions.size() )
			{
				BOOST_FOREACH( Transition tr, st->transitions )
@@ -201,14 +228,25 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
						
						if( !st->cofunc->Running() )
						{
							delete st->cofunc;
							st->cofunc = NULL;
						    finishTool( st );
						}
					}
				}
			}
		}
	}	
}


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;
}


@@ -218,8 +256,10 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& 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 )
		{
			st->pendingWait = true;
@@ -273,8 +313,10 @@ void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KiGfx::VIEW* aView,
	m_editFrame = aFrame;

	// 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 )
	        static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
	}
+15 −4
Original line number Diff line number Diff line
@@ -72,8 +72,8 @@ public:
     * 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
     */
    void InvokeTool( TOOL_ID aToolId );
    void InvokeTool( const std::string& aName );
    bool InvokeTool( TOOL_ID aToolId );
    bool InvokeTool( const std::string& aName );

    template <class Parameters>
        void InvokeTool( const std::string& aName, const Parameters& aToolParams );
@@ -153,20 +153,31 @@ public:
    void ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu,
                              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;
    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<std::string, ToolState*> m_toolNameIndex;
    std::map<TOOL_ID, ToolState*> m_toolIdIndex;
    std::deque<TOOL_ID> m_activeTools;

    EDA_ITEM* m_model;
    KiGfx::VIEW* m_view;
    KiGfx::VIEW_CONTROLS* m_viewControls;
    wxWindow* m_editFrame;
    bool m_passEvent;

    ToolState* m_currentTool;
};