diff --git a/include/widgets/footprint_preview_widget.h b/include/widgets/footprint_preview_widget.h index 49ec5edc96..b576813eee 100644 --- a/include/widgets/footprint_preview_widget.h +++ b/include/widgets/footprint_preview_widget.h @@ -86,6 +86,8 @@ public: */ void RefreshAll(); + FOOTPRINT_PREVIEW_PANEL_BASE* GetPreviewPanel() { return m_prev_panel; } + protected: FOOTPRINT_PREVIEW_PANEL_BASE* m_prev_panel; diff --git a/pcbnew/dialogs/dialog_footprint_chooser.cpp b/pcbnew/dialogs/dialog_footprint_chooser.cpp index b784e951cd..aec6ecaeb2 100644 --- a/pcbnew/dialogs/dialog_footprint_chooser.cpp +++ b/pcbnew/dialogs/dialog_footprint_chooser.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2023 CERN - * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -27,15 +27,30 @@ #include #include #include +#include <3d_canvas/eda_3d_canvas.h> +#include +#include +#include +#include +#include +#include +#include +#include DIALOG_FOOTPRINT_CHOOSER::DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent, const LIB_ID& aPreselect, const wxArrayString& aFootprintHistoryList ) : DIALOG_SHIM( aParent, wxID_ANY, _( "Choose Footprint" ), wxDefaultPosition, wxDefaultSize, - wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ), + m_boardAdapter(), + m_currentCamera( m_trackBallCamera ), + m_trackBallCamera( 2 * RANGE_SCALE_3D ) { - wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); + m_parent = aParent; + m_showFpMode = true; + + wxBoxSizer* m_SizerTop = new wxBoxSizer( wxVERTICAL ); m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( aParent, this, aFootprintHistoryList, // Filter []( LIB_TREE_NODE& aNode ) -> bool @@ -53,7 +68,35 @@ DIALOG_FOOTPRINT_CHOOSER::DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent, EndModal( wxID_CANCEL ); } ); - sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 ); + m_SizerTop->Add( m_chooserPanel, 1, wxEXPAND, 5 ); + FOOTPRINT_PREVIEW_WIDGET* viewerFpPanel = m_chooserPanel->GetViewerPanel(); + + viewerFpPanel->Show( m_showFpMode ); + + build3DCanvas(); + + m_preview3DCanvas->Show( !m_showFpMode ); + + wxBoxSizer* bSizerBottom; + bSizerBottom = new wxBoxSizer( wxHORIZONTAL ); + // Add a spacer on the left + bSizerBottom->Add( 20, 0, 0, 0, 5 ); + + m_grButton3DView = new BITMAP_BUTTON( this, wxID_ANY, + wxNullBitmap, wxDefaultPosition, wxDefaultSize/*, wxBU_AUTODRAW|wxBORDER_NONE*/ ); + m_grButton3DView->SetIsRadioButton(); + m_grButton3DView->SetBitmap( KiBitmapBundle( BITMAPS::shape_3d ) ); + m_grButton3DView->Check( !m_showFpMode ); + bSizerBottom->Add( m_grButton3DView, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_grButtonFpView = new BITMAP_BUTTON( this, wxID_ANY, + wxNullBitmap, wxDefaultPosition, wxDefaultSize/*, wxBU_AUTODRAW|wxBORDER_NONE*/ ); + m_grButtonFpView->SetIsRadioButton(); + m_grButtonFpView->SetBitmap( KiBitmapBundle( BITMAPS::module ) ); + m_grButtonFpView->Check( m_showFpMode ); + bSizerBottom->Add( m_grButtonFpView, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizerBottom->Add( 0, 0, 1, wxEXPAND, 5 ); if( aPreselect.IsValid() ) m_chooserPanel->SetPreselect( aPreselect ); @@ -68,18 +111,126 @@ DIALOG_FOOTPRINT_CHOOSER::DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent, sdbSizer->AddButton( cancelButton ); sdbSizer->Realize(); - sizer->Add( sdbSizer, 0, wxEXPAND | wxALL, 5 ); - SetSizer( sizer ); + bSizerBottom->Add( sdbSizer, 0, wxEXPAND | wxALL, 5 ); + + m_SizerTop->Add( bSizerBottom, 0, wxEXPAND, 5 ); + SetSizer( m_SizerTop ); SetInitialFocus( m_chooserPanel->GetFocusTarget() ); SetupStandardButtons(); m_chooserPanel->FinishSetup(); Layout(); + + // Connect Events + m_grButton3DView->Connect( wxEVT_COMMAND_BUTTON_CLICKED , + wxCommandEventHandler( DIALOG_FOOTPRINT_CHOOSER::on3DviewReq ), + NULL, this ); + m_grButtonFpView->Connect( wxEVT_COMMAND_BUTTON_CLICKED , + wxCommandEventHandler( DIALOG_FOOTPRINT_CHOOSER::onFpViewReq ), + NULL, this ); + + this->Connect( FP_SELECTION_EVENT, // custom event fired by a PANEL_FOOTPRINT_CHOOSER + wxCommandEventHandler( DIALOG_FOOTPRINT_CHOOSER::onFpChanged ), NULL, this ); } +DIALOG_FOOTPRINT_CHOOSER::~DIALOG_FOOTPRINT_CHOOSER() +{ + // Disconnect Events + m_grButton3DView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_FOOTPRINT_CHOOSER::on3DviewReq ), NULL, this ); + m_grButtonFpView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_FOOTPRINT_CHOOSER::onFpViewReq ), NULL, this ); + + this->Disconnect( FP_SELECTION_EVENT, + wxCommandEventHandler( DIALOG_FOOTPRINT_CHOOSER::onFpChanged ), NULL, this ); +} + + +void DIALOG_FOOTPRINT_CHOOSER::build3DCanvas() +{ + // Create the dummy board used by the 3D canvas + m_dummyBoard = new BOARD(); + m_dummyBoard->SetProject( &m_parent->Prj(), true ); + + // This board will only be used to hold a footprint for viewing + m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER ); + + m_boardAdapter.SetBoard( m_dummyBoard ); + m_boardAdapter.m_IsBoardView = false; + m_boardAdapter.m_IsPreviewer = true; // Force display 3D models, regardless the 3D viewer options + EDA_3D_VIEWER_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings(); + m_boardAdapter.m_Cfg = cfg; + + // Build the 3D canvas + + m_preview3DCanvas = new EDA_3D_CANVAS( m_chooserPanel->m_RightPanel, + OGL_ATT_LIST::GetAttributesList( ANTIALIASING_MODE::AA_8X ), + m_boardAdapter, m_currentCamera, + PROJECT_PCB::Get3DCacheManager( &m_parent->Prj() ) ); + + m_chooserPanel->m_RightPanelSizer->Add( m_preview3DCanvas, 1, wxEXPAND, 5 ); + m_chooserPanel->m_RightPanel->Layout(); + + BOARD_DESIGN_SETTINGS parent_bds = m_parent->GetDesignSettings(); + BOARD_DESIGN_SETTINGS& dummy_bds = m_dummyBoard->GetDesignSettings(); + dummy_bds.SetBoardThickness( parent_bds.GetBoardThickness() ); + dummy_bds.SetEnabledLayers( LSET::FrontMask() | LSET::BackMask() ); + BOARD_STACKUP& dummy_board_stackup = m_dummyBoard->GetDesignSettings().GetStackupDescriptor(); + dummy_board_stackup.RemoveAll(); + dummy_board_stackup.BuildDefaultStackupList( &dummy_bds, 2 ); +} + + + LIB_ID DIALOG_FOOTPRINT_CHOOSER::GetSelectedLibId() const { return m_chooserPanel->GetSelectedLibId(); } + + +void DIALOG_FOOTPRINT_CHOOSER::onFpChanged( wxCommandEvent& event ) +{ + if( m_showFpMode ) // the 3D viewer is not activated + return; + + on3DviewReq( event ); +} + + +void DIALOG_FOOTPRINT_CHOOSER::on3DviewReq( wxCommandEvent& event ) +{ + m_showFpMode = false; + + m_grButtonFpView->Check( m_showFpMode ); + m_grButton3DView->Check( !m_showFpMode ); + + FOOTPRINT_PREVIEW_WIDGET* viewFpPanel = m_chooserPanel->GetViewerPanel(); + viewFpPanel->Show( m_showFpMode ); + m_preview3DCanvas->Show( !m_showFpMode ); + m_dummyBoard->DeleteAllFootprints(); + + if( m_chooserPanel->m_CurrFootprint ) + m_dummyBoard->Add( (FOOTPRINT*)m_chooserPanel->m_CurrFootprint->Clone() ); + + m_preview3DCanvas->ReloadRequest(); + m_preview3DCanvas->Request_refresh(); + m_chooserPanel->m_RightPanel->Layout(); + m_chooserPanel->m_RightPanel->Refresh(); +} + + +void DIALOG_FOOTPRINT_CHOOSER::onFpViewReq( wxCommandEvent& event ) +{ + m_showFpMode = true; + + m_grButtonFpView->Check( m_showFpMode ); + m_grButton3DView->Check( !m_showFpMode ); + + FOOTPRINT_PREVIEW_WIDGET* viewFpPanel = m_chooserPanel->GetViewerPanel(); + viewFpPanel->Show( m_showFpMode ); + m_preview3DCanvas->Show( !m_showFpMode ); + m_chooserPanel->m_RightPanel->Layout(); + m_chooserPanel->m_RightPanel->Refresh(); +} diff --git a/pcbnew/dialogs/dialog_footprint_chooser.h b/pcbnew/dialogs/dialog_footprint_chooser.h index d2f305c751..6e80f9aede 100644 --- a/pcbnew/dialogs/dialog_footprint_chooser.h +++ b/pcbnew/dialogs/dialog_footprint_chooser.h @@ -25,10 +25,16 @@ #include #include "dialog_shim.h" - +#include <3d_canvas/board_adapter.h> +#include <3d_rendering/track_ball.h> class PCB_BASE_FRAME; class PANEL_FOOTPRINT_CHOOSER; +class EDA_3D_CANVAS; +class BOARD; +class CAMERA; +class TRACK_BALL; +class BITMAP_BUTTON; class DIALOG_FOOTPRINT_CHOOSER : public DIALOG_SHIM @@ -37,7 +43,7 @@ public: DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent, const LIB_ID& aPreselect, const wxArrayString& aFootprintHistoryList ); - ~DIALOG_FOOTPRINT_CHOOSER() {}; + ~DIALOG_FOOTPRINT_CHOOSER(); /** * To be called after this dialog returns from ShowModal(). @@ -46,8 +52,28 @@ public: */ LIB_ID GetSelectedLibId() const; +protected: + void on3DviewReq( wxCommandEvent& event ); + void onFpViewReq( wxCommandEvent& event ); + + // A command event sent by a PANEL_FOOTPRINT_CHOOSER will fire this event: + void onFpChanged( wxCommandEvent& event ); + + void build3DCanvas(); + protected: PANEL_FOOTPRINT_CHOOSER* m_chooserPanel; + bool m_showFpMode; // True to show the footprint, false for the 3D model + +private: + PCB_BASE_FRAME* m_parent; + BOARD_ADAPTER m_boardAdapter; + EDA_3D_CANVAS* m_preview3DCanvas; + CAMERA& m_currentCamera; + TRACK_BALL m_trackBallCamera; + BOARD* m_dummyBoard; + BITMAP_BUTTON* m_grButtonFpView; + BITMAP_BUTTON* m_grButton3DView; }; #endif /* DIALOG_FOOTPRINT_CHOOSER_H */ diff --git a/pcbnew/footprint_chooser_frame.cpp b/pcbnew/footprint_chooser_frame.cpp index 10516c9e4c..4badbf1104 100644 --- a/pcbnew/footprint_chooser_frame.cpp +++ b/pcbnew/footprint_chooser_frame.cpp @@ -34,6 +34,9 @@ #include #include #include "wx/display.h" +#include <3d_canvas/eda_3d_canvas.h> +#include +#include static wxArrayString s_FootprintHistoryList; @@ -75,11 +78,15 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare FOOTPRINT_CHOOSER_FRAME_NAME ), m_filterByPinCount( nullptr ), m_filterByFPFilters( nullptr ), + m_boardAdapter(), + m_currentCamera( m_trackBallCamera ), + m_trackBallCamera( 2 * RANGE_SCALE_3D ), m_pinCount( 0 ), m_firstPaintEvent( true ) { SetModal( true ); + m_showFpMode = true; m_messagePanel->Hide(); wxPanel* bottomPanel = new wxPanel( this ); @@ -119,12 +126,32 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare frameSizer->Add( m_chooserPanel, 1, wxEXPAND ); + build3DCanvas(); // must be called after creating m_chooserPanel + m_preview3DCanvas->Show( !m_showFpMode ); + wxBoxSizer* fpFilterSizer = new wxBoxSizer( wxVERTICAL ); - fpFilterSizer->Add( m_filterByFPFilters, 0, wxTOP | wxEXPAND, 5 ); - bottomSizer->Add( fpFilterSizer, 0, wxEXPAND | wxLEFT, 10 ); + fpFilterSizer->Add( m_filterByFPFilters, 0, wxLEFT | wxTOP | wxEXPAND, 5 ); wxBoxSizer* buttonsSizer = new wxBoxSizer( wxHORIZONTAL ); - buttonsSizer->Add( m_filterByPinCount, 0, wxLEFT | wxTOP | wxALIGN_TOP, 5 ); + fpFilterSizer->Add( m_filterByPinCount, 0, wxLEFT | wxTOP | wxBOTTOM, 5 ); + buttonsSizer->Add( fpFilterSizer, 0, wxEXPAND | wxLEFT, 10 ); + + wxBoxSizer* grbuttSizer = new wxBoxSizer( wxHORIZONTAL ); + m_grButton3DView = new BITMAP_BUTTON( bottomPanel, wxID_ANY, + wxNullBitmap, wxDefaultPosition, + wxDefaultSize/*, wxBU_AUTODRAW|wxBORDER_NONE*/ ); + m_grButton3DView->SetIsRadioButton(); + m_grButton3DView->SetBitmap( KiBitmapBundle( BITMAPS::shape_3d ) ); + m_grButton3DView->Check( !m_showFpMode ); + grbuttSizer->Add( m_grButton3DView, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_grButtonFpView = new BITMAP_BUTTON( bottomPanel, wxID_ANY, + wxNullBitmap, wxDefaultPosition, + wxDefaultSize/*, wxBU_AUTODRAW|wxBORDER_NONE*/ ); + m_grButtonFpView->SetIsRadioButton(); + m_grButtonFpView->SetBitmap( KiBitmapBundle( BITMAPS::module ) ); + m_grButtonFpView->Check( m_showFpMode ); + grbuttSizer->Add( m_grButtonFpView, 0, wxALIGN_CENTER_VERTICAL, 5 ); wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer(); wxButton* okButton = new wxButton( bottomPanel, wxID_OK ); @@ -134,6 +161,7 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare sdbSizer->AddButton( cancelButton ); sdbSizer->Realize(); + buttonsSizer->Add( grbuttSizer, 1, wxALL, 5 ); buttonsSizer->Add( sdbSizer, 1, wxALL, 5 ); bottomSizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 ); @@ -160,11 +188,31 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare { m_chooserPanel->Regenerate(); } ); + + // Connect Events + m_grButton3DView->Connect( wxEVT_COMMAND_BUTTON_CLICKED , + wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ), + NULL, this ); + m_grButtonFpView->Connect( wxEVT_COMMAND_BUTTON_CLICKED , + wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpViewReq ), + NULL, this ); + + Connect( FP_SELECTION_EVENT, // custom event fired by a PANEL_FOOTPRINT_CHOOSER + wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpChanged ), NULL, this ); } FOOTPRINT_CHOOSER_FRAME::~FOOTPRINT_CHOOSER_FRAME() { + // Disconnect Events + m_grButton3DView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ), NULL, this ); + m_grButtonFpView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpViewReq ), NULL, this ); + + Disconnect( FP_SELECTION_EVENT, + wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpChanged ), NULL, this ); + if( PCBNEW_SETTINGS* cfg = dynamic_cast( Kiface().KifaceSettings() ) ) { cfg->m_FootprintChooser.use_fp_filters = m_filterByFPFilters->GetValue(); @@ -410,3 +458,83 @@ void FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser( wxCommandEvent& aEvent ) } +void FOOTPRINT_CHOOSER_FRAME::onFpChanged( wxCommandEvent& event ) +{ + if( m_showFpMode ) // the 3D viewer is not activated + return; + + on3DviewReq( event ); +} + + +void FOOTPRINT_CHOOSER_FRAME::build3DCanvas() +{ + // Create the dummy board used by the 3D canvas + m_dummyBoard = new BOARD(); + m_dummyBoard->SetProject( &Prj(), true ); + + // This board will only be used to hold a footprint for viewing + m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER ); + + m_boardAdapter.SetBoard( m_dummyBoard ); + m_boardAdapter.m_IsBoardView = false; + m_boardAdapter.m_IsPreviewer = true; // Force display 3D models, regardless the 3D viewer options + + EDA_3D_VIEWER_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings(); + m_boardAdapter.m_Cfg = cfg; + + // Build the 3D canvas + m_preview3DCanvas = new EDA_3D_CANVAS( m_chooserPanel->m_RightPanel, + OGL_ATT_LIST::GetAttributesList( ANTIALIASING_MODE::AA_8X ), + m_boardAdapter, m_currentCamera, + PROJECT_PCB::Get3DCacheManager( &Prj() ) ); + + m_chooserPanel->m_RightPanelSizer->Add( m_preview3DCanvas, 1, wxEXPAND, 5 ); + m_chooserPanel->m_RightPanel->Layout(); + + BOARD_DESIGN_SETTINGS& dummy_bds = m_dummyBoard->GetDesignSettings(); + dummy_bds.SetBoardThickness( pcbIUScale.mmToIU( 1.6 ) ); + dummy_bds.SetEnabledLayers( LSET::FrontMask() | LSET::BackMask() ); + BOARD_STACKUP& dummy_board_stackup = m_dummyBoard->GetDesignSettings().GetStackupDescriptor(); + dummy_board_stackup.RemoveAll(); + dummy_board_stackup.BuildDefaultStackupList( &dummy_bds, 2 ); +} + + + +void FOOTPRINT_CHOOSER_FRAME::on3DviewReq( wxCommandEvent& event ) +{ + m_showFpMode = false; + + m_grButtonFpView->Check( m_showFpMode ); + m_grButton3DView->Check( !m_showFpMode ); + + FOOTPRINT_PREVIEW_WIDGET* viewFpPanel = m_chooserPanel->GetViewerPanel(); + viewFpPanel->Show( m_showFpMode ); + m_preview3DCanvas->Show( !m_showFpMode ); + m_dummyBoard->DeleteAllFootprints(); + + if( m_chooserPanel->m_CurrFootprint ) + m_dummyBoard->Add( (FOOTPRINT*)m_chooserPanel->m_CurrFootprint->Clone() ); + + m_preview3DCanvas->ReloadRequest(); + m_preview3DCanvas->Request_refresh(); + m_chooserPanel->m_RightPanel->Layout(); + m_chooserPanel->m_RightPanel->Refresh(); +} + + +void FOOTPRINT_CHOOSER_FRAME::onFpViewReq( wxCommandEvent& event ) +{ + m_showFpMode = true; + + m_grButtonFpView->Check( m_showFpMode ); + m_grButton3DView->Check( !m_showFpMode ); + + FOOTPRINT_PREVIEW_WIDGET* viewFpPanel = m_chooserPanel->GetViewerPanel(); + viewFpPanel->Show( m_showFpMode ); + m_preview3DCanvas->Show( !m_showFpMode ); + m_chooserPanel->m_RightPanel->Layout(); + m_chooserPanel->m_RightPanel->Refresh(); +} + diff --git a/pcbnew/footprint_chooser_frame.h b/pcbnew/footprint_chooser_frame.h index cd0bf4d1a7..8c39778e12 100644 --- a/pcbnew/footprint_chooser_frame.h +++ b/pcbnew/footprint_chooser_frame.h @@ -31,9 +31,14 @@ #include #include #include +#include <3d_canvas/board_adapter.h> +#include <3d_rendering/track_ball.h> class PANEL_FOOTPRINT_CHOOSER; class wxCheckBox; +class BITMAP_BUTTON; +class BOARD; +class CAMERA; namespace PCB { struct IFACE; } @@ -77,6 +82,13 @@ private: WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override; COLOR_SETTINGS* GetColorSettings( bool aForceRefresh ) const override; + void on3DviewReq( wxCommandEvent& event ); + void onFpViewReq( wxCommandEvent& event ); + + // A command event sent by a PANEL_FOOTPRINT_CHOOSER will fire this event: + void onFpChanged( wxCommandEvent& event ); + + void build3DCanvas(); DECLARE_EVENT_TABLE() @@ -84,9 +96,18 @@ private: private: PANEL_FOOTPRINT_CHOOSER* m_chooserPanel; + bool m_showFpMode; // True to show the footprint, false for 3D model wxCheckBox* m_filterByPinCount; wxCheckBox* m_filterByFPFilters; + BOARD_ADAPTER m_boardAdapter; + EDA_3D_CANVAS* m_preview3DCanvas; + CAMERA& m_currentCamera; + TRACK_BALL m_trackBallCamera; + BOARD* m_dummyBoard; + BITMAP_BUTTON* m_grButtonFpView; + BITMAP_BUTTON* m_grButton3DView; + int m_pinCount; std::vector> m_fpFilters; diff --git a/pcbnew/footprint_preview_panel.h b/pcbnew/footprint_preview_panel.h index ecf21030ce..e6c5a8e2a2 100644 --- a/pcbnew/footprint_preview_panel.h +++ b/pcbnew/footprint_preview_panel.h @@ -39,6 +39,7 @@ class FOOTPRINT; class KIWAY; class IO_MGR; class BOARD; +class FOOTPRINT; /** @@ -68,6 +69,7 @@ public: static FOOTPRINT_PREVIEW_PANEL* New( KIWAY* aKiway, wxWindow* aParent, UNITS_PROVIDER* aUnitsProvider ); + const FOOTPRINT* GetCurrentFootprint() const { return m_currentFootprint.get(); } private: /** diff --git a/pcbnew/widgets/panel_footprint_chooser.cpp b/pcbnew/widgets/panel_footprint_chooser.cpp index 61968866e0..8b0b9a683b 100644 --- a/pcbnew/widgets/panel_footprint_chooser.cpp +++ b/pcbnew/widgets/panel_footprint_chooser.cpp @@ -43,6 +43,9 @@ #include #include +// When a new footprint is selected, a custom event is sent, for instance to update +// 3D viewer. So define a FP_SELECTION_EVENT event +wxDEFINE_EVENT(FP_SELECTION_EVENT, wxCommandEvent); PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent, const wxArrayString& aFootprintHistoryList, @@ -57,6 +60,7 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopL m_acceptHandler( std::move( aAcceptHandler ) ), m_escapeHandler( std::move( aEscapeHandler ) ) { + m_CurrFootprint = nullptr; FP_LIB_TABLE* fpTable = PROJECT_PCB::PcbFootprintLibs( &aFrame->Prj() ); // Load footprint files: @@ -134,18 +138,18 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopL m_hsplitter->SetSashGravity( 0.8 ); m_hsplitter->SetMinimumPaneSize( 20 ); - wxPanel* rightPanel = new wxPanel( m_hsplitter ); - wxBoxSizer* rightPanelSizer = new wxBoxSizer( wxVERTICAL ); + m_RightPanel = new wxPanel( m_hsplitter ); + m_RightPanelSizer = new wxBoxSizer( wxVERTICAL ); - m_preview_ctrl = new FOOTPRINT_PREVIEW_WIDGET( rightPanel, m_frame->Kiway() ); + m_preview_ctrl = new FOOTPRINT_PREVIEW_WIDGET( m_RightPanel, m_frame->Kiway() ); m_preview_ctrl->SetUserUnits( m_frame->GetUserUnits() ); - rightPanelSizer->Add( m_preview_ctrl, 1, wxEXPAND | wxALL, 5 ); + m_RightPanelSizer->Add( m_preview_ctrl, 1, wxEXPAND | wxALL, 5 ); - rightPanel->SetSizer( rightPanelSizer ); - rightPanel->Layout(); - rightPanelSizer->Fit( rightPanel ); + m_RightPanel->SetSizer( m_RightPanelSizer ); + m_RightPanel->Layout(); + m_RightPanelSizer->Fit( m_RightPanel ); - m_hsplitter->SplitVertically( m_tree, rightPanel ); + m_hsplitter->SplitVertically( m_tree, m_RightPanel ); m_dbl_click_timer = new wxTimer( this ); m_open_libs_timer = new wxTimer( this ); @@ -314,7 +318,7 @@ void PANEL_FOOTPRINT_CHOOSER::onCloseTimer( wxTimerEvent& aEvent ) } } - +#include void PANEL_FOOTPRINT_CHOOSER::onOpenLibsTimer( wxTimerEvent& aEvent ) { if( PCBNEW_SETTINGS* cfg = dynamic_cast( Kiface().KifaceSettings() ) ) @@ -338,6 +342,14 @@ void PANEL_FOOTPRINT_CHOOSER::onFootprintSelected( wxCommandEvent& aEvent ) m_preview_ctrl->ClearStatus(); m_preview_ctrl->DisplayFootprint( lib_id ); } + + m_CurrFootprint = static_cast(m_preview_ctrl->GetPreviewPanel())->GetCurrentFootprint(); + + // Send a FP_SELECTION_EVENT event after a footprint change + wxCommandEvent event( FP_SELECTION_EVENT, GetId() ); + event.SetEventObject( this ); + + ProcessWindowEvent( event ); } diff --git a/pcbnew/widgets/panel_footprint_chooser.h b/pcbnew/widgets/panel_footprint_chooser.h index d32647634d..a80a29c63b 100644 --- a/pcbnew/widgets/panel_footprint_chooser.h +++ b/pcbnew/widgets/panel_footprint_chooser.h @@ -31,9 +31,13 @@ class wxTimer; class wxSplitterWindow; +class wxBoxSizer; class PCB_BASE_FRAME; +// When a new footprint is selected, a custom event is sent, for instance to update +// 3D viewer. So declare a FP_SELECTION_EVENT event +wxDECLARE_EVENT(FP_SELECTION_EVENT, wxCommandEvent); class PANEL_FOOTPRINT_CHOOSER : public wxPanel { @@ -71,6 +75,13 @@ public: void Regenerate() { m_tree->Regenerate( true ); } + FOOTPRINT_PREVIEW_WIDGET* GetViewerPanel() const { return m_preview_ctrl; } + + wxPanel* m_RightPanel; + wxBoxSizer* m_RightPanelSizer; + + const FOOTPRINT* m_CurrFootprint; + protected: static constexpr int DblClickDelay = 100; // milliseconds