diff --git a/cvpcb/components_listbox.cpp b/cvpcb/components_listbox.cpp index f8a97191d1..66be98a6b2 100644 --- a/cvpcb/components_listbox.cpp +++ b/cvpcb/components_listbox.cpp @@ -26,6 +26,7 @@ */ #include +#include #include #include @@ -111,21 +112,12 @@ void COMPONENTS_LISTBOX::SetSelection( int index, bool State ) void COMPONENTS_LISTBOX::OnChar( wxKeyEvent& event ) { + wxLogTrace( kicadTraceKeyEvent, "COMPONENTS_LISTBOX::OnChar %s", dump( event ) ); + int key = event.GetKeyCode(); switch( key ) { - case WXK_TAB: - case WXK_RIGHT: - case WXK_NUMPAD_RIGHT: - GetParent()->ChangeFocus( true ); - return; - - case WXK_LEFT: - case WXK_NUMPAD_LEFT: - GetParent()->ChangeFocus( false ); - return; - case WXK_HOME: case WXK_END: case WXK_UP: diff --git a/cvpcb/cvpcb_mainframe.cpp b/cvpcb/cvpcb_mainframe.cpp index 32254a9d2f..dc8cd00691 100644 --- a/cvpcb/cvpcb_mainframe.cpp +++ b/cvpcb/cvpcb_mainframe.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -189,19 +190,10 @@ CVPCB_MAINFRAME::CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent ) : m_initialized = true; // Connect Events - m_footprintListBox->Connect( wxEVT_RIGHT_DOWN, - wxMouseEventHandler( CVPCB_MAINFRAME::OnFootprintRightClick ), - NULL, this ); - m_compListBox->Connect( wxEVT_RIGHT_DOWN, - wxMouseEventHandler( CVPCB_MAINFRAME::OnComponentRightClick ), - NULL, this ); + setupEventHandlers(); - // Use Bind for this one to allow the lambda expression - m_saveAndContinue->Bind( wxEVT_COMMAND_BUTTON_CLICKED, - [this]( wxCommandEvent& ) - { - this->GetToolManager()->RunAction( CVPCB_ACTIONS::saveAssociations ); - } ); + // Start the main processing loop + m_toolManager->InvokeTool( "cvpcb.Control" ); // Ensure the toolbars are sync'd properly so the filtering options display correct SyncToolbars(); @@ -210,10 +202,7 @@ CVPCB_MAINFRAME::CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent ) : CVPCB_MAINFRAME::~CVPCB_MAINFRAME() { - // Disconnect Events - m_footprintListBox->Disconnect( wxEVT_RIGHT_DOWN, - wxMouseEventHandler( CVPCB_MAINFRAME::OnFootprintRightClick ), - NULL, this ); + // No events to disconnect since they are using lambdas as the handlers m_auimgr.UnInit(); } @@ -222,8 +211,10 @@ CVPCB_MAINFRAME::~CVPCB_MAINFRAME() void CVPCB_MAINFRAME::setupTools() { // Create the manager + m_actions = new CVPCB_ACTIONS(); m_toolManager = new TOOL_MANAGER; m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, this ); + m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, m_actions ); // Register tools m_toolManager->RegisterTool( new COMMON_CONTROL ); @@ -243,6 +234,34 @@ void CVPCB_MAINFRAME::setupTools() m_footprintContextMenu->Add( CVPCB_ACTIONS::showFootprintViewer ); } +void CVPCB_MAINFRAME::setupEventHandlers() +{ + // Connect the handlers to launch the context menus in the listboxes + m_footprintListBox->Bind( wxEVT_RIGHT_DOWN, + [this]( wxMouseEvent& ) + { + PopupMenu( m_footprintContextMenu ); + } ); + + m_compListBox->Bind( wxEVT_RIGHT_DOWN, + [this]( wxMouseEvent& ) + { + PopupMenu( m_componentContextMenu ); + } ); + + // Connect the handler for the save button + m_saveAndContinue->Bind( wxEVT_COMMAND_BUTTON_CLICKED, + [this]( wxCommandEvent& ) + { + this->GetToolManager()->RunAction( CVPCB_ACTIONS::saveAssociations ); + } ); + + // Attach the events to the tool dispatcher + Bind( wxEVT_TOOL, &TOOL_DISPATCHER::DispatchWxCommand, m_toolDispatcher ); + Bind( wxEVT_CHAR, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher ); + Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher ); +} + void CVPCB_MAINFRAME::LoadSettings( wxConfigBase* aCfg ) { EDA_BASE_FRAME::LoadSettings( aCfg ); @@ -297,31 +316,6 @@ void CVPCB_MAINFRAME::OnCloseWindow( wxCloseEvent& Event ) } -void CVPCB_MAINFRAME::ChangeFocus( bool aMoveRight ) -{ - wxWindow* hasFocus = wxWindow::FindFocus(); - - if( aMoveRight ) - { - if( hasFocus == m_libListBox ) - m_compListBox->SetFocus(); - else if( hasFocus == m_compListBox ) - m_footprintListBox->SetFocus(); - else if( hasFocus == m_footprintListBox ) - m_libListBox->SetFocus(); - } - else - { - if( hasFocus == m_libListBox ) - m_footprintListBox->SetFocus(); - else if( hasFocus == m_compListBox ) - m_libListBox->SetFocus(); - else if( hasFocus == m_footprintListBox ) - m_compListBox->SetFocus(); - } -} - - void CVPCB_MAINFRAME::OnOK( wxCommandEvent& aEvent ) { SaveFootprintAssociation( false ); @@ -453,18 +447,6 @@ bool CVPCB_MAINFRAME::OpenProjectFiles( const std::vector& aFileSet, i } -void CVPCB_MAINFRAME::OnComponentRightClick( wxMouseEvent& event ) -{ - PopupMenu( m_componentContextMenu ); -} - - -void CVPCB_MAINFRAME::OnFootprintRightClick( wxMouseEvent& event ) -{ - PopupMenu( m_footprintContextMenu ); -} - - void CVPCB_MAINFRAME::OnSelectComponent( wxListEvent& event ) { if( m_skipComponentSelect ) @@ -954,6 +936,54 @@ DISPLAY_FOOTPRINTS_FRAME* CVPCB_MAINFRAME::GetFootprintViewerFrame() } +CVPCB_MAINFRAME::CONTROL_TYPE CVPCB_MAINFRAME::GetFocusedControl() +{ + if( m_libListBox->HasFocus() ) + return CVPCB_MAINFRAME::CONTROL_LIBRARY; + else if( m_compListBox->HasFocus() ) + return CVPCB_MAINFRAME::CONTROL_COMPONENT; + else if( m_footprintListBox->HasFocus() ) + return CVPCB_MAINFRAME::CONTROL_FOOTPRINT; + + return CVPCB_MAINFRAME::CONTROL_NONE; +} + + +wxControl* CVPCB_MAINFRAME::GetFocusedControlObject() +{ + if( m_libListBox->HasFocus() ) + return m_libListBox; + else if( m_compListBox->HasFocus() ) + return m_compListBox; + else if( m_footprintListBox->HasFocus() ) + return m_footprintListBox; + + return nullptr; +} + + +void CVPCB_MAINFRAME::SetFocusedControl( CVPCB_MAINFRAME::CONTROL_TYPE aLB ) +{ + switch( aLB ) + { + case CVPCB_MAINFRAME::CONTROL_LIBRARY: + m_libListBox->SetFocus(); + break; + + case CVPCB_MAINFRAME::CONTROL_COMPONENT: + m_compListBox->SetFocus(); + break; + + case CVPCB_MAINFRAME::CONTROL_FOOTPRINT: + m_footprintListBox->SetFocus(); + break; + + default: + break; + } +} + + wxString CVPCB_MAINFRAME::GetSelectedFootprint() { // returns the LIB_ID of the selected footprint in footprint listview diff --git a/cvpcb/cvpcb_mainframe.h b/cvpcb/cvpcb_mainframe.h index ba88530d36..faac613e83 100644 --- a/cvpcb/cvpcb_mainframe.h +++ b/cvpcb/cvpcb_mainframe.h @@ -104,6 +104,26 @@ public: FILTER_TOGGLE ///< Toggle the filter state }; + /** + * The type of the controls present in the application + */ + enum CONTROL_TYPE + { + CONTROL_NONE, ///< No controls have focus + CONTROL_LIBRARY, ///< Library listbox + CONTROL_COMPONENT, ///< Component listbox + CONTROL_FOOTPRINT ///< Footprint listbox + }; + + /** + * Directions to rotate the focus through the listboxes is + */ + enum FOCUS_DIR + { + CHANGE_FOCUS_RIGHT, + CHANGE_FOCUS_LEFT + }; + /** * Directions to move when selecting items */ @@ -118,6 +138,27 @@ public: */ DISPLAY_FOOTPRINTS_FRAME* GetFootprintViewerFrame(); + /** + * Find out which control currently has focus. + * + * @return the contorl that currently has focus + */ + CVPCB_MAINFRAME::CONTROL_TYPE GetFocusedControl(); + + /** + * Get a pointer to the currently focused control + * + * @return the control that currently has focus + */ + wxControl* GetFocusedControlObject(); + + /** + * Set the focus to a specific control. + * + * @param aControl the contorl to set focus to + */ + void SetFocusedControl( CVPCB_MAINFRAME::CONTROL_TYPE aControl ); + /** * Function OnSelectComponent * Called when clicking on a component in component list window @@ -137,12 +178,6 @@ public: void ReCreateMenuBar() override; void ShowChangedLanguage() override; - void ChangeFocus( bool aMoveRight ); - - void OnComponentRightClick( wxMouseEvent& event ); - - void OnFootprintRightClick( wxMouseEvent& event ); - /** * Called by the automatic association button * Read *.equ files to try to find corresponding footprint @@ -347,6 +382,11 @@ private: */ void setupTools(); + /** + * Setup event handlers + */ + void setupEventHandlers(); + /** * read the .equ files and populate the list of equvalents * @param aList the list to populate @@ -358,6 +398,9 @@ private: void refreshAfterComponentSearch (COMPONENT* component); + // Tool dispatcher + TOOL_DISPATCHER* m_toolDispatcher; + // Context menus for the list boxes ACTION_MENU* m_footprintContextMenu; ACTION_MENU* m_componentContextMenu; diff --git a/cvpcb/footprints_listbox.cpp b/cvpcb/footprints_listbox.cpp index c15fc2e368..d90e79c036 100644 --- a/cvpcb/footprints_listbox.cpp +++ b/cvpcb/footprints_listbox.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -233,21 +234,12 @@ void FOOTPRINTS_LISTBOX::OnLeftDClick( wxListEvent& event ) void FOOTPRINTS_LISTBOX::OnChar( wxKeyEvent& event ) { + wxLogTrace( kicadTraceKeyEvent, "FOOTPRINTS_LISTBOX::OnChar %s", dump( event ) ); + int key = event.GetKeyCode(); switch( key ) { - case WXK_TAB: - case WXK_RIGHT: - case WXK_NUMPAD_RIGHT: - GetParent()->ChangeFocus( true ); - return; - - case WXK_LEFT: - case WXK_NUMPAD_LEFT: - GetParent()->ChangeFocus( false ); - return; - case WXK_HOME: case WXK_END: case WXK_UP: diff --git a/cvpcb/library_listbox.cpp b/cvpcb/library_listbox.cpp index e771f978ac..2bfe913a7b 100644 --- a/cvpcb/library_listbox.cpp +++ b/cvpcb/library_listbox.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -144,21 +145,12 @@ END_EVENT_TABLE() void LIBRARY_LISTBOX::OnChar( wxKeyEvent& event ) { + wxLogTrace( kicadTraceKeyEvent, "LIBRARY_LISTBOX::OnChar %s", dump( event ) ); + int key = event.GetKeyCode(); switch( key ) { - case WXK_TAB: - case WXK_RIGHT: - case WXK_NUMPAD_RIGHT: - GetParent()->ChangeFocus( true ); - return; - - case WXK_LEFT: - case WXK_NUMPAD_LEFT: - GetParent()->ChangeFocus( false ); - return; - case WXK_HOME: case WXK_END: case WXK_UP: diff --git a/cvpcb/tools/cvpcb_actions.cpp b/cvpcb/tools/cvpcb_actions.cpp index 4efaa5f374..d74761a2de 100644 --- a/cvpcb/tools/cvpcb_actions.cpp +++ b/cvpcb/tools/cvpcb_actions.cpp @@ -41,6 +41,12 @@ TOOL_ACTION CVPCB_ACTIONS::selectionActivate( "cvpcb.InteractiveSelection", AS_G "", NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere +TOOL_ACTION CVPCB_ACTIONS::controlActivate( "cvpcb.Control", AS_GLOBAL, + 0, "", + "", + "", + NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere + // Action to show the footprint viewer window TOOL_ACTION CVPCB_ACTIONS::showFootprintViewer( "cvpcb.Control.ShowFootprintViewer", AS_GLOBAL, @@ -64,6 +70,21 @@ TOOL_ACTION CVPCB_ACTIONS::saveAssociations( "cvpcb.Control.SaveAssocations", AS _( "Save footprint associations in schematic symbol footprint fields" ), save_xpm ); +// Actions to navigate the display +TOOL_ACTION CVPCB_ACTIONS::changeFocusRight( "cvpcb.Control.changeFocusRight", AS_GLOBAL, + WXK_TAB, "", + "", + "", + nullptr, AF_NONE, + (void*) CVPCB_MAINFRAME::CHANGE_FOCUS_RIGHT ); + +TOOL_ACTION CVPCB_ACTIONS::changeFocusLeft( "cvpcb.Control.changeFocusLeft", AS_GLOBAL, + MD_SHIFT + WXK_TAB, "", + "", + "", + nullptr, AF_NONE, + (void*) CVPCB_MAINFRAME::CHANGE_FOCUS_LEFT ); + // Actions to navigate the component list TOOL_ACTION CVPCB_ACTIONS::gotoNextNA( "cvpcb.Control.GotoNextNA", AS_GLOBAL, 0, "", @@ -82,7 +103,7 @@ TOOL_ACTION CVPCB_ACTIONS::gotoPreviousNA( "cvpcb.Control.GotoPreviousNA", AS_GL // Actions to modify component associations TOOL_ACTION CVPCB_ACTIONS::associate( "cvpcb.Control.Associate", AS_GLOBAL, - 0, "", + WXK_RETURN, "", _( "Associate footprint" ), _( "Associate selected footprint with selected components" ), auto_associe_xpm ); diff --git a/cvpcb/tools/cvpcb_actions.h b/cvpcb/tools/cvpcb_actions.h index 4921b31308..e6ce0bbace 100644 --- a/cvpcb/tools/cvpcb_actions.h +++ b/cvpcb/tools/cvpcb_actions.h @@ -42,9 +42,13 @@ class TOOL_MANAGER; class CVPCB_ACTIONS : public ACTIONS { public: - // Selection Tool - /// Activation of the selection tool + /// Activation actions static TOOL_ACTION selectionActivate; + static TOOL_ACTION controlActivate; + + /// Window control actions + static TOOL_ACTION changeFocusRight; + static TOOL_ACTION changeFocusLeft; /// Open the footprint viewer static TOOL_ACTION showFootprintViewer; diff --git a/cvpcb/tools/cvpcb_control.cpp b/cvpcb/tools/cvpcb_control.cpp index f5964467a6..1fa158c344 100644 --- a/cvpcb/tools/cvpcb_control.cpp +++ b/cvpcb/tools/cvpcb_control.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,113 @@ void CVPCB_CONTROL::Reset( RESET_REASON aReason ) } +int CVPCB_CONTROL::Main( const TOOL_EVENT& aEvent ) +{ + // Main loop: keep receiving events + while( TOOL_EVENT* evt = Wait() ) + { + bool handled = false; + + // The escape key maps to the cancel event, which is used to close the window + if( evt->IsCancel() ) + { + wxCloseEvent dummy; + m_frame->OnCloseWindow( dummy ); + handled = true; + } + else if( evt->IsKeyPressed() ) + { + switch( evt->KeyCode() ) + { + // The right arrow moves focus to the focusable object to the right + case WXK_RIGHT: + m_toolMgr->RunAction( CVPCB_ACTIONS::changeFocusRight ); + handled = true; + break; + + // The left arrow moves focus to the focusable object to the left + case WXK_LEFT: + m_toolMgr->RunAction( CVPCB_ACTIONS::changeFocusLeft ); + handled = true; + break; + + default: + // Let every other key continue processing to the controls of the window + break; + } + } + + if( !handled ) + evt->SetPassEvent(); + } + + // This tool is supposed to be active forever + wxASSERT( false ); + + return 0; +} + + +int CVPCB_CONTROL::ChangeFocus( const TOOL_EVENT& aEvent ) +{ + int tmp = aEvent.Parameter(); + CVPCB_MAINFRAME::FOCUS_DIR dir = + static_cast( tmp ); + + switch( dir ) + { + case CVPCB_MAINFRAME::CHANGE_FOCUS_RIGHT: + switch( m_frame->GetFocusedControl() ) + { + case CVPCB_MAINFRAME::CONTROL_LIBRARY: + m_frame->SetFocusedControl( CVPCB_MAINFRAME::CONTROL_COMPONENT ); + break; + + case CVPCB_MAINFRAME::CONTROL_COMPONENT: + m_frame->SetFocusedControl( CVPCB_MAINFRAME::CONTROL_FOOTPRINT ); + break; + + case CVPCB_MAINFRAME::CONTROL_FOOTPRINT: + m_frame->SetFocusedControl( CVPCB_MAINFRAME::CONTROL_LIBRARY ); + break; + + case CVPCB_MAINFRAME::CONTROL_NONE: + default: + break; + } + + break; + + case CVPCB_MAINFRAME::CHANGE_FOCUS_LEFT: + switch( m_frame->GetFocusedControl() ) + { + case CVPCB_MAINFRAME::CONTROL_LIBRARY: + m_frame->SetFocusedControl( CVPCB_MAINFRAME::CONTROL_FOOTPRINT ); + break; + + case CVPCB_MAINFRAME::CONTROL_COMPONENT: + m_frame->SetFocusedControl( CVPCB_MAINFRAME::CONTROL_LIBRARY ); + break; + + case CVPCB_MAINFRAME::CONTROL_FOOTPRINT: + m_frame->SetFocusedControl( CVPCB_MAINFRAME::CONTROL_COMPONENT ); + break; + + case CVPCB_MAINFRAME::CONTROL_NONE: + default: + break; + } + + break; + + default: + break; + } + + return 0; +} + + int CVPCB_CONTROL::ShowFootprintViewer( const TOOL_EVENT& aEvent ) { @@ -280,8 +388,11 @@ int CVPCB_CONTROL::UpdateMenu( const TOOL_EVENT& aEvent ) void CVPCB_CONTROL::setTransitions() { - // Update the menu + // Control actions Go( &CVPCB_CONTROL::UpdateMenu, ACTIONS::updateMenu.MakeEvent() ); + Go( &CVPCB_CONTROL::Main, CVPCB_ACTIONS::controlActivate.MakeEvent() ); + Go( &CVPCB_CONTROL::ChangeFocus, CVPCB_ACTIONS::changeFocusRight.MakeEvent() ); + Go( &CVPCB_CONTROL::ChangeFocus, CVPCB_ACTIONS::changeFocusLeft.MakeEvent() ); // Run the footprint viewer Go( &CVPCB_CONTROL::ShowFootprintViewer, CVPCB_ACTIONS::showFootprintViewer.MakeEvent() ); diff --git a/cvpcb/tools/cvpcb_control.h b/cvpcb/tools/cvpcb_control.h index 10e7c553ef..ab7939a85e 100644 --- a/cvpcb/tools/cvpcb_control.h +++ b/cvpcb/tools/cvpcb_control.h @@ -41,6 +41,21 @@ public: /// @copydoc TOOL_INTERACTIVE::Reset() void Reset( RESET_REASON aReason ) override; + /** + * Main processing loop for the CVPCB window. This function will constantly loop and + * to process various actions taken in the window. + * + * @param aEvent is the event generated by the tool framework + */ + int Main( const TOOL_EVENT& aEvent ); + + /** + * Rotate focus in the CVPCB window + * + * @param aEvent is the event generated by the tool framework + */ + int ChangeFocus( const TOOL_EVENT& aEvent ); + /** * Undo the footprint associations most recently done. *