diff --git a/common/tool/action_menu.cpp b/common/tool/action_menu.cpp index 57416304bb..e40a7d928e 100644 --- a/common/tool/action_menu.cpp +++ b/common/tool/action_menu.cpp @@ -339,10 +339,16 @@ void ACTION_MENU::updateHotKeys() static int g_last_menu_highlighted_id = 0; +// We need to store the position of the mouse when the menu was opened so it can be passed +// to the command event generated when the menu item is selected. +static VECTOR2D g_menu_open_position; + void ACTION_MENU::OnIdle( wxIdleEvent& event ) { g_last_menu_highlighted_id = 0; + g_menu_open_position.x = 0.0; + g_menu_open_position.y = 0.0; } @@ -357,6 +363,12 @@ void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent ) if( m_dirty && m_tool ) getToolManager()->RunAction( ACTIONS::updateMenu, true, this ); + wxMenu* parent = dynamic_cast( GetParent() ); + + // Don't update the position if this menu has a parent + if( !parent && m_tool ) + g_menu_open_position = getToolManager()->GetViewControls()->GetMousePosition(); + g_last_menu_highlighted_id = 0; } else if( type == wxEVT_MENU_HIGHLIGHT ) @@ -441,6 +453,12 @@ void ACTION_MENU::OnMenuEvent( wxMenuEvent& aEvent ) TOOL_MANAGER* toolMgr = m_tool->GetManager(); + // Pass the position the menu was opened from into the generated event if it is a select event + if( type == wxEVT_COMMAND_MENU_SELECTED ) + evt->SetMousePosition( g_menu_open_position ); + else + evt->SetMousePosition( getToolManager()->GetViewControls()->GetMousePosition() ); + if( g_last_menu_highlighted_id == aEvent.GetId() && !m_isContextMenu ) evt->SetHasPosition( false ); diff --git a/common/tool/tool_event.cpp b/common/tool/tool_event.cpp index ed7fdf95d0..a4bece2777 100644 --- a/common/tool/tool_event.cpp +++ b/common/tool/tool_event.cpp @@ -57,6 +57,10 @@ void TOOL_EVENT::init() m_passEvent = m_category == TC_MESSAGE || IsCancelInteractive() || IsActivate(); m_hasPosition = ( m_category == TC_MOUSE || m_category == TC_COMMAND ); + + // Cancel tool doesn't contain a position + if( IsCancel() ) + m_hasPosition = false; } @@ -173,7 +177,7 @@ const std::string TOOL_EVENT_LIST::Format() const bool TOOL_EVENT::IsClick( int aButtonMask ) const { - return m_actions == TA_MOUSE_CLICK && ( m_mouseButtons & aButtonMask ) == m_mouseButtons; + return ( m_actions & TA_MOUSE_CLICK ) && ( m_mouseButtons & aButtonMask ) == m_mouseButtons; } diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index f56f6ce372..df3f14e83e 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -283,6 +283,9 @@ bool TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow, void* aPara bool handled = false; TOOL_EVENT event = aAction.MakeEvent(); + if( event.Category() == TC_COMMAND ) + event.SetMousePosition( m_viewControls->GetCursorPosition() ); + // Allow to override the action parameter if( aParam ) event.SetParameter( aParam ); @@ -303,6 +306,20 @@ bool TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow, void* aPara } +void TOOL_MANAGER::PrimeTool( const VECTOR2D& aPosition ) +{ + int modifiers = 0; + modifiers |= wxGetKeyState( WXK_SHIFT ) ? MD_SHIFT : 0; + modifiers |= wxGetKeyState( WXK_CONTROL ) ? MD_CTRL : 0; + modifiers |= wxGetKeyState( WXK_ALT ) ? MD_ALT : 0; + + TOOL_EVENT evt( TC_MOUSE, TA_PRIME, BUT_LEFT | modifiers ); + evt.SetMousePosition( aPosition ); + + PostEvent( evt ); +} + + const std::map& TOOL_MANAGER::GetActions() { return m_actionMgr->GetActions(); @@ -320,6 +337,7 @@ bool TOOL_MANAGER::invokeTool( TOOL_BASE* aTool ) wxASSERT( aTool != NULL ); TOOL_EVENT evt( TC_COMMAND, TA_ACTIVATE, aTool->GetName() ); + evt.SetMousePosition( m_viewControls->GetCursorPosition() ); processEvent( evt ); if( TOOL_STATE* active = GetCurrentToolState() ) @@ -742,6 +760,7 @@ void TOOL_MANAGER::DispatchContextMenu( const TOOL_EVENT& aEvent ) else { TOOL_EVENT evt( TC_COMMAND, TA_CHOICE_MENU_CHOICE, -1 ); + evt.SetHasPosition( false ); evt.SetParameter( m ); dispatchInternal( evt ); } @@ -751,6 +770,7 @@ void TOOL_MANAGER::DispatchContextMenu( const TOOL_EVENT& aEvent ) // Notify the tools that menu has been closed TOOL_EVENT evt( TC_COMMAND, TA_CHOICE_MENU_CLOSED ); + evt.SetHasPosition( false ); evt.SetParameter( m ); dispatchInternal( evt ); diff --git a/include/tool/tool_event.h b/include/tool/tool_event.h index 36b70b47c9..c1fcbac5b3 100644 --- a/include/tool/tool_event.h +++ b/include/tool/tool_event.h @@ -115,6 +115,9 @@ enum TOOL_ACTIONS // Model has changed (partial update). TA_MODEL_CHANGE = 0x200000, + // Tool priming event (a special mouse click) + TA_PRIME = 0x400001, + TA_ANY = 0xffffffff }; @@ -330,6 +333,11 @@ public: return m_actions & TA_CHOICE_MENU; } + bool IsPrime() const + { + return m_actions == TA_PRIME; + } + ///> Returns information about key modifiers state (Ctrl, Alt, etc.) int Modifier( int aMask = MD_MODIFIER_MASK ) const { diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h index 14622d994c..3d65afd25e 100644 --- a/include/tool/tool_manager.h +++ b/include/tool/tool_manager.h @@ -148,6 +148,15 @@ public: const std::map& GetActions(); + /** + * Function PrimeTool() + * "Primes" a tool by sending a cursor left-click event with the mouse position set + * to the passed in position. + * + * @param aPosition is the mouse position to use in the event + */ + void PrimeTool( const VECTOR2D& aPosition ); + ///> @copydoc ACTION_MANAGER::GetHotKey() int GetHotKey( const TOOL_ACTION& aAction ); diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index a6e67b8653..12010f796f 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -568,6 +568,7 @@ void PCB_EDIT_FRAME::DoShowBoardSetupDialog( const wxString& aInitialPage, //this event causes the routing tool to reload its design rules information TOOL_EVENT toolEvent( TC_COMMAND, TA_MODEL_CHANGE, AS_ACTIVE ); + toolEvent.SetHasPosition( false ); m_toolManager->ProcessEvent( toolEvent ); OnModify();