Push most of footprint chooser into PANEL_FOOTPRINT_CHOOSER.

Create 2 wrappers for it: DIALOG_FOOTPRINT_CHOOSER and
FOOTPRINT_CHOOSER_FRAME.  The first now gets called from wxGrid
editors, text button editors (such as Change Footprints), etc.

Retire FOOTPRINT_VIEWER_FRAME_MODAL.  FOOTPRINT_VIEWER_FRAME still
exists, but has very few uses at this point.
This commit is contained in:
Jeff Young 2023-09-26 18:31:45 +01:00
parent 4e77c9089e
commit 1047130046
31 changed files with 923 additions and 615 deletions

View File

@ -122,45 +122,51 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
m_auimgr.SetFlags( wxAUI_MGR_DEFAULT );
CreateStatusBar( 8 )->SetDoubleBuffered( true );
if( ( aStyle & wxFRAME_NO_TASKBAR ) == 0 )
{
CreateStatusBar( 8 )->SetDoubleBuffered( true );
// set the size of the status bar subwindows:
wxWindow* stsbar = GetStatusBar();
int spacer = KIUI::GetTextSize( wxT( "M" ), stsbar ).x * 2;
wxWindow* stsbar = GetStatusBar();
int spacer = KIUI::GetTextSize( wxT( "M" ), stsbar ).x * 2;
int dims[] = {
int dims[] =
{
// remainder of status bar on far left is set to a default or whatever is left over.
-1,
// remainder of status bar on far left is set to a default or whatever is left over.
-1,
// When using GetTextSize() remember the width of character '1' is not the same
// as the width of '0' unless the font is fixed width, and it usually won't be.
// When using GetTextSize() remember the width of character '1' is not the same
// as the width of '0' unless the font is fixed width, and it usually won't be.
// zoom:
KIUI::GetTextSize( wxT( "Z 762000" ), stsbar ).x,
// zoom:
KIUI::GetTextSize( wxT( "Z 762000" ), stsbar ).x + spacer,
// cursor coords
KIUI::GetTextSize( wxT( "X 1234.1234 Y 1234.1234" ), stsbar ).x,
// cursor coords
KIUI::GetTextSize( wxT( "X 1234.1234 Y 1234.1234" ), stsbar ).x + spacer,
// delta distances
KIUI::GetTextSize( wxT( "dx 1234.1234 dy 1234.1234 dist 1234.1234" ), stsbar ).x,
// delta distances
KIUI::GetTextSize( wxT( "dx 1234.1234 dy 1234.1234 dist 1234.1234" ), stsbar ).x + spacer,
// grid size
KIUI::GetTextSize( wxT( "grid X 1234.1234 Y 1234.1234" ), stsbar ).x,
// grid size
KIUI::GetTextSize( wxT( "grid X 1234.1234 Y 1234.1234" ), stsbar ).x + spacer,
// units display, Inches is bigger than mm
KIUI::GetTextSize( _( "Inches" ), stsbar ).x,
// units display, Inches is bigger than mm
KIUI::GetTextSize( _( "Inches" ), stsbar ).x + spacer,
// Size for the "Current Tool" panel; longest string from SetTool()
KIUI::GetTextSize( wxT( "Add layer alignment target" ), stsbar ).x,
// Size for the "Current Tool" panel; longest string from SetTool()
KIUI::GetTextSize( wxT( "Add layer alignment target" ), stsbar ).x + spacer,
// constraint mode
KIUI::GetTextSize( _( "Constrain to H, V, 45" ), stsbar ).x
};
// constraint mode
KIUI::GetTextSize( _( "Constrain to H, V, 45" ), stsbar ).x + spacer
};
for( size_t ii = 1; ii < arrayDim( dims ); ii++ )
dims[ii] += spacer;
SetStatusWidths( arrayDim( dims ), dims );
stsbar->SetFont( KIUI::GetStatusFont( this ) );
SetStatusWidths( arrayDim( dims ), dims );
stsbar->SetFont( KIUI::GetStatusFont( this ) );
}
// Create child subwindows.
GetClientSize( &m_frameSize.x, &m_frameSize.y );

View File

@ -381,7 +381,7 @@ KIWAY::FACE_T KIWAY::KifaceType( FRAME_T aFrameType )
case FRAME_PCB_EDITOR:
case FRAME_FOOTPRINT_EDITOR:
case FRAME_FOOTPRINT_VIEWER:
case FRAME_FOOTPRINT_VIEWER_MODAL:
case FRAME_FOOTPRINT_CHOOSER:
case FRAME_FOOTPRINT_WIZARD:
case FRAME_PCB_DISPLAY3D:
return FACE_PCB;

View File

@ -354,8 +354,9 @@ int COMMON_TOOLS::doZoomFit( ZOOM_FIT_TYPE_T aFitType )
{
// Leave a bigger margin for library editors & viewers
if( frame->IsType( FRAME_FOOTPRINT_VIEWER ) || frame->IsType( FRAME_FOOTPRINT_VIEWER_MODAL )
|| frame->IsType( FRAME_SCH_VIEWER ) || frame->IsType( FRAME_SCH_VIEWER_MODAL ) )
if( frame->IsType( FRAME_FOOTPRINT_VIEWER )
|| frame->IsType( FRAME_SCH_VIEWER )
|| frame->IsType( FRAME_SCH_VIEWER_MODAL ) )
{
margin_scale_factor = 1.30;
}

View File

@ -267,7 +267,7 @@ protected:
if( fpid.IsEmpty() )
fpid = m_preselect;
KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true, m_dlg );
KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_dlg );
if( !m_symbolNetlist.empty() )
{

View File

@ -220,7 +220,7 @@ void DIALOG_FIELD_PROPERTIES::OnTextValueSelectButtonClick( wxCommandEvent& aEve
else
fpid = m_TextCtrl->GetValue();
if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true ) )
if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true ) )
{
if( frame->ShowModal( &fpid, this ) )
{

View File

@ -110,8 +110,7 @@ protected:
// pick a footprint using the footprint picker.
wxString fpid = m_grid->GetCellValue( m_grid->GetGridCursorRow(),
FOOTPRINT_FIELD );
KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true,
m_dlg );
KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_dlg );
if( frame->ShowModal( &fpid, m_dlg ) )
m_grid->SetCellValue( m_grid->GetGridCursorRow(), FOOTPRINT_FIELD, fpid );

View File

@ -896,7 +896,7 @@ void FIELDS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
{
// pick a footprint using the footprint picker.
wxString fpid = m_grid->GetCellValue( FOOTPRINT_FIELD, FDC_VALUE );
KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true, m_dlg );
KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_dlg );
if( frame->ShowModal( &fpid, m_dlg ) )
m_grid->SetCellValue( FOOTPRINT_FIELD, FDC_VALUE, fpid );

View File

@ -56,14 +56,14 @@ namespace KIGFX
using KIGFX::COLOR4D;
using KIGFX::RENDER_SETTINGS;
#define LIB_EDIT_FRAME_NAME wxT( "LibeditFrame" )
#define SCH_EDIT_FRAME_NAME wxT( "SchematicFrame" )
#define PL_EDITOR_FRAME_NAME wxT( "PlEditorFrame" )
#define FOOTPRINT_WIZARD_FRAME_NAME wxT( "FootprintWizard" )
#define FOOTPRINT_EDIT_FRAME_NAME wxT( "ModEditFrame" )
#define FOOTPRINT_VIEWER_FRAME_NAME wxT( "ModViewFrame" )
#define FOOTPRINT_VIEWER_FRAME_NAME_MODAL wxT( "ModViewFrameModal" )
#define PCB_EDIT_FRAME_NAME wxT( "PcbFrame" )
#define LIB_EDIT_FRAME_NAME wxT( "LibeditFrame" )
#define SCH_EDIT_FRAME_NAME wxT( "SchematicFrame" )
#define PL_EDITOR_FRAME_NAME wxT( "PlEditorFrame" )
#define FOOTPRINT_WIZARD_FRAME_NAME wxT( "FootprintWizard" )
#define FOOTPRINT_CHOOSER_FRAME_NAME wxT( "FootprintChooserFrame" )
#define FOOTPRINT_EDIT_FRAME_NAME wxT( "ModEditFrame" )
#define FOOTPRINT_VIEWER_FRAME_NAME wxT( "ModViewFrame" )
#define PCB_EDIT_FRAME_NAME wxT( "PcbFrame" )
/**

View File

@ -39,8 +39,8 @@ enum FRAME_T
FRAME_PCB_EDITOR,
FRAME_FOOTPRINT_EDITOR,
FRAME_FOOTPRINT_CHOOSER,
FRAME_FOOTPRINT_VIEWER,
FRAME_FOOTPRINT_VIEWER_MODAL,
FRAME_FOOTPRINT_WIZARD,
FRAME_PCB_DISPLAY3D,
FRAME_FOOTPRINT_PREVIEW,

View File

@ -290,7 +290,7 @@ public:
*
* @param aPreslect if valid, the #LIB_ID to select (otherwise the global history is used).
*/
FOOTPRINT* SelectFootprintFromLibTree( LIB_ID aPreselect = LIB_ID() );
FOOTPRINT* SelectFootprintFromLibrary( LIB_ID aPreselect = LIB_ID() );
/**
* Add the given footprint to the board.
@ -299,13 +299,6 @@ public:
*/
virtual void AddFootprintToBoard( FOOTPRINT* aFootprint );
/**
* Launch the footprint viewer to select the name of a footprint to load.
*
* @return the selected footprint name or an empty string if no selection was made.
*/
wxString SelectFootprintFromLibBrowser();
/**
* Create the entire board ratsnest.
*

View File

@ -37,7 +37,6 @@ set( PCBNEW_DIALOGS
dialogs/dialog_board_statistics_base.cpp
dialogs/dialog_board_reannotate.cpp
dialogs/dialog_board_reannotate_base.cpp
dialogs/dialog_choose_footprint.cpp
dialogs/dialog_cleanup_graphics.cpp
dialogs/dialog_cleanup_graphics_base.cpp
dialogs/dialog_cleanup_tracks_and_vias.cpp
@ -50,10 +49,11 @@ set( PCBNEW_DIALOGS
dialogs/dialog_dimension_properties_base.cpp
dialogs/dialog_drc.cpp
dialogs/dialog_drc_base.cpp
dialogs/dialog_footprint_checker.cpp
dialogs/dialog_footprint_checker_base.cpp
dialogs/dialog_footprint_associations.cpp
dialogs/dialog_footprint_associations_base.cpp
dialogs/dialog_footprint_checker.cpp
dialogs/dialog_footprint_checker_base.cpp
dialogs/dialog_footprint_chooser.cpp
dialogs/dialog_footprint_properties.cpp
dialogs/dialog_footprint_properties_base.cpp
dialogs/dialog_footprint_properties_fp_editor.cpp
@ -287,6 +287,7 @@ set( PCBNEW_CLASS_SRCS
footprint_editor_utils.cpp
footprint_editor_settings.cpp
fp_tree_synchronizing_adapter.cpp
footprint_chooser_frame.cpp
footprint_edit_frame.cpp
footprint_libraries_utils.cpp
footprint_viewer_frame.cpp
@ -356,6 +357,7 @@ set( PCBNEW_CLASS_SRCS
widgets/appearance_controls.cpp
widgets/appearance_controls_base.cpp
widgets/panel_footprint_chooser.cpp
widgets/panel_selection_filter.cpp
widgets/panel_selection_filter_base.cpp
widgets/pcb_properties_panel.cpp

View File

@ -1,265 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
* Copyright (C) 2016-2021 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <dialog_choose_footprint.h>
#include <algorithm>
#include <wx/utils.h>
#include <wx/button.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/splitter.h>
#include <wx/timer.h>
#include <wx/wxhtml.h>
#include <pcb_base_frame.h>
#include <pcbnew_settings.h>
#include <pgm_base.h>
#include <fp_lib_table.h>
#include <settings/settings_manager.h>
#include <widgets/lib_tree.h>
#include <widgets/footprint_preview_widget.h>
#include <widgets/footprint_select_widget.h>
#include <kiface_base.h>
DIALOG_CHOOSE_FOOTPRINT::DIALOG_CHOOSE_FOOTPRINT( PCB_BASE_FRAME* aParent,
const wxString& aTitle,
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>& aAdapter )
: DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
m_browser_button( nullptr ),
m_hsplitter( nullptr ),
m_vsplitter( nullptr ),
m_parent( aParent ),
m_external_browser_requested( false )
{
auto sizer = new wxBoxSizer( wxVERTICAL );
HTML_WINDOW* details = nullptr;
m_vsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxSP_LIVE_UPDATE );
m_hsplitter = new wxSplitterWindow( m_vsplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxSP_LIVE_UPDATE );
//Avoid the splitter window being assigned as the Parent to additional windows
m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
auto detailsPanel = new wxPanel( m_vsplitter );
auto detailsSizer = new wxBoxSizer( wxVERTICAL );
detailsPanel->SetSizer( detailsSizer );
details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxHW_SCROLLBAR_AUTO );
detailsSizer->Add( details, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
detailsPanel->Layout();
detailsSizer->Fit( detailsPanel );
m_vsplitter->SetSashGravity( 0.5 );
m_vsplitter->SetMinimumPaneSize( 20 );
m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel );
sizer->Add( m_vsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
m_tree = new LIB_TREE( m_hsplitter, wxT( "footprints" ), Prj().PcbFootprintLibs(), aAdapter,
LIB_TREE::FLAGS::ALL_WIDGETS, details );
m_hsplitter->SetSashGravity( 0.8 );
m_hsplitter->SetMinimumPaneSize( 20 );
m_hsplitter->SplitVertically( m_tree, ConstructRightPanel( m_hsplitter ) );
m_dbl_click_timer = new wxTimer( this );
auto buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
m_browser_button = new wxButton( this, wxID_ANY, _( "Select with Browser" ) );
buttonsSizer->Add( m_browser_button, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
auto sdbSizer = new wxStdDialogButtonSizer();
auto okButton = new wxButton( this, wxID_OK );
auto cancelButton = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( okButton );
sdbSizer->AddButton( cancelButton );
sdbSizer->Realize();
buttonsSizer->Add( sdbSizer, 1, wxALL, 5 );
sizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 );
SetSizer( sizer );
aAdapter->FinishTreeInitialization();
SetupStandardButtons();
Bind( wxEVT_TIMER, &DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer, this, m_dbl_click_timer->GetId() );
Bind( SYMBOL_PRESELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentPreselected, this );
Bind( SYMBOL_SELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentSelected, this );
m_browser_button->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_CHOOSE_FOOTPRINT::OnUseBrowser,
this );
Layout();
if( PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>() )
{
// We specify the width of the right window (m_symbol_view_panel), because specify
// the width of the left window does not work as expected when SetSashGravity() is called
if( cfg->m_FootprintChooser.sash_h < 0 )
cfg->m_FootprintChooser.sash_h = horizPixelsFromDU( 220 );
m_hsplitter->SetSashPosition( cfg->m_FootprintChooser.sash_h );
if( cfg->m_FootprintChooser.sash_v < 0 )
cfg->m_FootprintChooser.sash_v = horizPixelsFromDU( 230 );
if( m_vsplitter )
m_vsplitter->SetSashPosition( cfg->m_FootprintChooser.sash_v );
int w = cfg->m_FootprintChooser.width < 0 ?
horizPixelsFromDU( 440 ) : cfg->m_FootprintChooser.width;
int h = cfg->m_FootprintChooser.height < 0 ?
horizPixelsFromDU( 340 ) : cfg->m_FootprintChooser.height;
SetSize( wxSize( w, h ) );
aAdapter->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) cfg->m_FootprintChooser.sort_mode );
}
SetInitialFocus( m_tree->GetFocusTarget() );
}
DIALOG_CHOOSE_FOOTPRINT::~DIALOG_CHOOSE_FOOTPRINT()
{
Unbind( wxEVT_TIMER, &DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer, this );
Unbind( SYMBOL_PRESELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentPreselected, this );
Unbind( SYMBOL_SELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentSelected, this );
m_browser_button->Unbind( wxEVT_COMMAND_BUTTON_CLICKED,
&DIALOG_CHOOSE_FOOTPRINT::OnUseBrowser, this );
// I am not sure the following two lines are necessary,
// but they will not hurt anyone
m_dbl_click_timer->Stop();
delete m_dbl_click_timer;
if( PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>() )
{
cfg->m_FootprintChooser.width = GetSize().x;
cfg->m_FootprintChooser.height = GetSize().y;
cfg->m_FootprintChooser.sash_h = m_hsplitter->GetSashPosition();
if( m_vsplitter )
cfg->m_FootprintChooser.sash_v = m_vsplitter->GetSashPosition();
cfg->m_FootprintChooser.sort_mode = m_tree->GetSortMode();
}
}
wxPanel* DIALOG_CHOOSE_FOOTPRINT::ConstructRightPanel( wxWindow* aParent )
{
auto panel = new wxPanel( aParent );
auto sizer = new wxBoxSizer( wxVERTICAL );
m_preview_ctrl = new FOOTPRINT_PREVIEW_WIDGET( panel, Kiway() );
m_preview_ctrl->SetUserUnits( GetUserUnits() );
sizer->Add( m_preview_ctrl, 1, wxEXPAND | wxTOP | wxRIGHT, 5 );
panel->SetSizer( sizer );
panel->Layout();
sizer->Fit( panel );
return panel;
}
LIB_ID DIALOG_CHOOSE_FOOTPRINT::GetSelectedLibId() const
{
return m_tree->GetSelectedLibId();
}
void DIALOG_CHOOSE_FOOTPRINT::OnUseBrowser( wxCommandEvent& aEvent )
{
m_external_browser_requested = true;
EndQuasiModal( wxID_OK );
}
void DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer( wxTimerEvent& aEvent )
{
// Hack handler because of eaten MouseUp event. See
// DIALOG_CHOOSE_FOOTPRINT::OnComponentSelected for the beginning
// of this spaghetti noodle.
auto state = wxGetMouseState();
if( state.LeftIsDown() )
{
// Mouse hasn't been raised yet, so fire the timer again. Otherwise the
// purpose of this timer is defeated.
m_dbl_click_timer->StartOnce( DIALOG_CHOOSE_FOOTPRINT::DblClickDelay );
}
else
{
EndQuasiModal( wxID_OK );
}
}
void DIALOG_CHOOSE_FOOTPRINT::OnComponentPreselected( wxCommandEvent& aEvent )
{
if( !m_preview_ctrl || !m_preview_ctrl->IsInitialized() )
return;
LIB_ID lib_id = m_tree->GetSelectedLibId();
if( !lib_id.IsValid() )
{
m_preview_ctrl->SetStatusText( _( "No footprint selected" ) );
}
else
{
m_preview_ctrl->ClearStatus();
m_preview_ctrl->DisplayFootprint( lib_id );
}
}
void DIALOG_CHOOSE_FOOTPRINT::OnComponentSelected( wxCommandEvent& aEvent )
{
if( m_tree->GetSelectedLibId().IsValid() )
{
// Got a selection. We can't just end the modal dialog here, because
// wx leaks some events back to the parent window (in particular, the
// MouseUp following a double click).
//
// NOW, here's where it gets really fun. wxTreeListCtrl eats MouseUp.
// This isn't really feasible to bypass without a fully custom
// wxDataViewCtrl implementation, and even then might not be fully
// possible (docs are vague). To get around this, we use a one-shot
// timer to schedule the dialog close.
//
// See DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer for the other end of this
// spaghetti noodle.
m_dbl_click_timer->StartOnce( DIALOG_CHOOSE_FOOTPRINT::DblClickDelay );
}
}

View File

@ -1,148 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
* Copyright (C) 2014-2018 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef DIALOG_CHOOSE_FOOTPRINT_H
#define DIALOG_CHOOSE_FOOTPRINT_H
#include "dialog_shim.h"
#include <fp_tree_model_adapter.h>
#include <footprint_info.h>
#include <widgets/footprint_preview_widget.h>
class wxStaticBitmap;
class wxTextCtrl;
class wxStdDialogButtonSizer;
class wxDataViewCtrl;
class wxHtmlLinkEvent;
class wxPanel;
class wxChoice;
class wxButton;
class wxTimer;
class wxSplitterWindow;
class PCB_BASE_FRAME;
class LIB_TREE;
class FOOTPRINT;
/**
* Dialog class to select a footprint from the libraries. This is the master
* View class in a Model-View-Adapter (mediated MVC) architecture. The other
* pieces are in:
*
* - Adapter: CMP_TREE_MODEL_ADAPTER in common/cmp_tree_model_adapter.h
* - Model: CMP_TREE_NODE and descendants in common/cmp_tree_model.h
*
* Because everything is tied together in the adapter class, see that file
* for thorough documentation. A simple example usage follows:
*
* // Create the adapter class
* auto adapter( FP_TREE_MODEL_ADAPTER::Create( Prj().PcbFootprintLibs() ) );
*
* // Perform any configuration of adapter properties here
* adapter->SetPreselectNode( "LIB_NICKNAME", "FP_NAME", 2 );
*
* // Initialize model from #FP_LIB_TABLE
* libNicknames = libs->GetLogicalLibs();
*
* for( auto nickname : libNicknames )
* {
* adapter->AddLibrary( nickname );
* }
*
* // Create and display dialog
* DIALOG_CHOOSE_FOOTPRINT dlg( this, title, adapter, 1 );
* bool selected = ( dlg.ShowModal() != wxID_CANCEL );
*
* // Receive part
* if( selected )
* {
* int unit;
* #LIB_ID id = dlg.GetSelectedAlias( &unit );
* do_something( id, unit );
* }
*
*/
class DIALOG_CHOOSE_FOOTPRINT : public DIALOG_SHIM
{
public:
/**
* Create dialog to choose component.
*
* @param aParent a PCB_BASE_FRAME parent window.
* @param aAdapter FP_TREE_MODEL_ADAPTER::PTR. See CMP_TREE_MODEL_ADAPTER
* for documentation.
*/
DIALOG_CHOOSE_FOOTPRINT( PCB_BASE_FRAME* aParent, const wxString& aTitle,
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>& aAdapter );
~DIALOG_CHOOSE_FOOTPRINT();
/**
* To be called after this dialog returns from ShowModal().
*
* @return the #LIB_ID of the symbol that has been selected.
*/
LIB_ID GetSelectedLibId() const;
/** Function IsExternalBrowserSelected
*
* @return true, iff the user pressed the thumbnail view of the component to
* launch the component browser.
*/
bool IsExternalBrowserSelected() const
{
return m_external_browser_requested;
}
protected:
static constexpr int DblClickDelay = 100; // milliseconds
wxPanel* ConstructRightPanel( wxWindow* aParent );
void OnCloseTimer( wxTimerEvent& aEvent );
void OnUseBrowser( wxCommandEvent& aEvent );
void OnComponentPreselected( wxCommandEvent& aEvent );
/**
* Handle the selection of an item. This is called when either the search
* box or the tree receive an Enter, or the tree receives a double click.
* If the item selected is a category, it is expanded or collapsed; if it
* is a component, the component is picked.
*/
void OnComponentSelected( wxCommandEvent& aEvent );
wxTimer* m_dbl_click_timer;
wxButton* m_browser_button;
wxSplitterWindow* m_hsplitter;
wxSplitterWindow* m_vsplitter;
FOOTPRINT_PREVIEW_WIDGET* m_preview_ctrl;
LIB_TREE* m_tree;
PCB_BASE_FRAME* m_parent;
bool m_external_browser_requested;
};
#endif /* DIALOG_CHOOSE_FOOTPRINT_H */

View File

@ -394,8 +394,6 @@ void DIALOG_EXCHANGE_FOOTPRINTS::processFootprint( FOOTPRINT* aFootprint, const
msg += _( ": OK" );
m_MessageWindow->Report( msg, RPT_SEVERITY_ACTION );
}
return;
}
@ -403,7 +401,7 @@ void DIALOG_EXCHANGE_FOOTPRINTS::ViewAndSelectFootprint( wxCommandEvent& event )
{
wxString newname = m_newID->GetValue();
KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true );
KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true );
if( frame->ShowModal( &newname, this ) )
{

View File

@ -0,0 +1,73 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <dialog_footprint_chooser.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <pcb_base_frame.h>
#include <widgets/panel_footprint_chooser.h>
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 )
{
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( aParent, this, aFootprintHistoryList,
[this]()
{
EndQuasiModal( wxID_OK );
} );
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );
if( aPreselect.IsValid() )
m_chooserPanel->SetPreselect( aPreselect );
SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ),
m_chooserPanel->GetItemCount() ) );
wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
wxButton* okButton = new wxButton( this, wxID_OK );
wxButton* cancelButton = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( okButton );
sdbSizer->AddButton( cancelButton );
sdbSizer->Realize();
sizer->Add( sdbSizer, 0, wxEXPAND | wxALL, 5 );
SetSizer( sizer );
SetInitialFocus( m_chooserPanel->GetFocusTarget() );
SetupStandardButtons();
m_chooserPanel->FinishSetup();
Layout();
}
LIB_ID DIALOG_FOOTPRINT_CHOOSER::GetSelectedLibId() const
{
return m_chooserPanel->GetSelectedLibId();
}

View File

@ -0,0 +1,53 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef DIALOG_FOOTPRINT_CHOOSER_H
#define DIALOG_FOOTPRINT_CHOOSER_H
#include <lib_id.h>
#include "dialog_shim.h"
class PCB_BASE_FRAME;
class PANEL_FOOTPRINT_CHOOSER;
class DIALOG_FOOTPRINT_CHOOSER : public DIALOG_SHIM
{
public:
DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent, const LIB_ID& aPreselect,
const wxArrayString& aFootprintHistoryList );
~DIALOG_FOOTPRINT_CHOOSER() {};
/**
* To be called after this dialog returns from ShowModal().
*
* @return the #LIB_ID of the symbol that has been selected.
*/
LIB_ID GetSelectedLibId() const;
protected:
PANEL_FOOTPRINT_CHOOSER* m_chooserPanel;
};
#endif /* DIALOG_FOOTPRINT_CHOOSER_H */

View File

@ -1244,7 +1244,7 @@ void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
UnescapeString( Value().GetText() ) );
if( aFrame->IsType( FRAME_FOOTPRINT_VIEWER )
|| aFrame->IsType( FRAME_FOOTPRINT_VIEWER_MODAL )
|| aFrame->IsType( FRAME_FOOTPRINT_CHOOSER )
|| aFrame->IsType( FRAME_FOOTPRINT_EDITOR ) )
{
size_t padCount = GetPadCount( DO_NOT_INCLUDE_NPTH );

View File

@ -0,0 +1,239 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <pgm_base.h>
#include <kiway.h>
#include <kiway_express.h>
#include <wx/button.h>
#include <kiplatform/ui.h>
#include <widgets/panel_footprint_chooser.h>
#include <settings/settings_manager.h>
#include <footprint_editor_settings.h>
#include <footprint_chooser_frame.h>
static wxArrayString s_FootprintHistoryList;
static unsigned s_FootprintHistoryMaxCount = 8;
static void AddFootprintToHistory( const wxString& aName )
{
// Remove duplicates
for( int ii = s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii )
{
if( s_FootprintHistoryList[ ii ] == aName )
s_FootprintHistoryList.RemoveAt((size_t) ii );
}
// Add the new name at the beginning of the history list
s_FootprintHistoryList.Insert( aName, 0 );
// Remove extra names
while( s_FootprintHistoryList.GetCount() >= s_FootprintHistoryMaxCount )
s_FootprintHistoryList.RemoveAt( s_FootprintHistoryList.GetCount() - 1 );
}
BEGIN_EVENT_TABLE( FOOTPRINT_CHOOSER_FRAME, PCB_BASE_FRAME )
EVT_MENU( wxID_CLOSE, FOOTPRINT_CHOOSER_FRAME::CloseFootprintChooser )
EVT_BUTTON( wxID_OK, FOOTPRINT_CHOOSER_FRAME::OnOK )
EVT_BUTTON( wxID_CANCEL, FOOTPRINT_CHOOSER_FRAME::CloseFootprintChooser )
EVT_PAINT( FOOTPRINT_CHOOSER_FRAME::OnPaint )
END_EVENT_TABLE()
#define PARENT_STYLE ( wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN \
| wxWANTS_CHARS | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT )
#define MODAL_STYLE ( wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN \
| wxWANTS_CHARS | wxFRAME_NO_TASKBAR | wxSTAY_ON_TOP )
FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_CHOOSER, _( "Footprint Chooser" ),
wxDefaultPosition, wxDefaultSize, aParent ? PARENT_STYLE : MODAL_STYLE,
FOOTPRINT_CHOOSER_FRAME_NAME ),
m_comp( LIB_ID(), wxEmptyString, wxEmptyString, KIID_PATH(), {} )
{
SetModal( true );
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( this, this, s_FootprintHistoryList,
[this]()
{
wxCommandEvent dummy;
OnOK( dummy );
} );
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );
wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
wxButton* okButton = new wxButton( this, wxID_OK );
wxButton* cancelButton = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( okButton );
sdbSizer->AddButton( cancelButton );
sdbSizer->Realize();
sizer->Add( sdbSizer, 0, wxEXPAND | wxALL, 5 );
SetSizer( sizer );
SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ),
m_chooserPanel->GetItemCount() ) );
Layout();
m_chooserPanel->FinishSetup();
}
void FOOTPRINT_CHOOSER_FRAME::doCloseWindow()
{
// Only dismiss a modal frame once, so that the return values set by
// the prior DismissModal() are not bashed for ShowModal().
if( !IsDismissed() )
DismissModal( false );
// window to be destroyed by the caller of KIWAY_PLAYER::ShowModal()
}
WINDOW_SETTINGS* FOOTPRINT_CHOOSER_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
{
PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
wxCHECK_MSG( cfg, nullptr, wxT( "config not existing" ) );
return &cfg->m_FootprintViewer;
}
COLOR_SETTINGS* FOOTPRINT_CHOOSER_FRAME::GetColorSettings( bool aForceRefresh ) const
{
auto* settings = Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>();
if( settings )
return Pgm().GetSettingsManager().GetColorSettings( settings->m_ColorTheme );
else
return Pgm().GetSettingsManager().GetColorSettings();
}
void FOOTPRINT_CHOOSER_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
{
// JEY TODO: don't delete this just yet. We can use it to pass in symbol info so that we
// can filter on footprint filters, symbol pin count, etc.
const std::string& payload = mail.GetPayload();
switch( mail.Command() )
{
case MAIL_SYMBOL_NETLIST:
{
/*
* Symbol netlist format:
* library:footprint
* reference
* value
* pinName,netName,pinFunction,pinType
* pinName,netName,pinFunction,pinType
* ...
*/
std::vector<std::string> strings = split( payload, "\r" );
LIB_ID libid;
if( strings.size() >= 3 )
{
libid.Parse( strings[0] );
m_comp.SetFPID( libid );
m_comp.SetReference( strings[1] );
m_comp.SetValue( strings[2] );
m_comp.ClearNets();
for( size_t ii = 3; ii < strings.size(); ++ii )
{
std::vector<std::string> pinData = split( strings[ii], "," );
m_comp.AddNet( pinData[0], pinData[1], pinData[2], pinData[3] );
}
}
break;
}
default:
break;
}
}
bool FOOTPRINT_CHOOSER_FRAME::ShowModal( wxString* aFootprint, wxWindow* aParent )
{
if( aFootprint && !aFootprint->IsEmpty() )
{
LIB_ID fpid;
fpid.Parse( *aFootprint, true );
if( fpid.IsValid() )
m_chooserPanel->SetPreselect( fpid );
}
return KIWAY_PLAYER::ShowModal( aFootprint, aParent );
}
void FOOTPRINT_CHOOSER_FRAME::OnPaint( wxPaintEvent& aEvent )
{
if( m_firstPaintEvent )
{
KIPLATFORM::UI::FixupCancelButtonCmdKeyCollision( this );
KIPLATFORM::UI::ForceFocus( m_chooserPanel->GetFocusTarget() );
m_firstPaintEvent = false;
}
aEvent.Skip();
}
void FOOTPRINT_CHOOSER_FRAME::OnOK( wxCommandEvent& aEvent )
{
LIB_ID fpID = m_chooserPanel->GetSelectedLibId();
if( fpID.IsValid() )
{
wxString footprint = fpID.Format();
AddFootprintToHistory( footprint );
DismissModal( true, footprint );
}
else
{
DismissModal( false );
}
}
void FOOTPRINT_CHOOSER_FRAME::CloseFootprintChooser( wxCommandEvent& aEvent )
{
Close( false );
}

View File

@ -0,0 +1,90 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef FOOTPRINT_CHOOSER_FRAME_H
#define FOOTPRINT_CHOOSER_FRAME_H
#include <wx/gdicmn.h>
#include <pcb_base_frame.h>
#include <pcbnew_settings.h>
#include <netlist_reader/pcb_netlist.h>
class PANEL_FOOTPRINT_CHOOSER;
namespace PCB { struct IFACE; }
class FOOTPRINT_CHOOSER_FRAME : public PCB_BASE_FRAME
{
public:
~FOOTPRINT_CHOOSER_FRAME() {};
///< @copydoc PCB_BASE_FRAME::GetModel()
BOARD_ITEM_CONTAINER* GetModel() const override { return nullptr; }
/**
* @param aFootprint an optional FPID string to initialize the viewer with and to
* return a selected footprint through.
*/
bool ShowModal( wxString* aFootprint, wxWindow* aParent ) override;
void KiwayMailIn( KIWAY_EXPRESS& mail ) override;
protected:
FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent );
void doReCreateMenuBar() override {}
private:
void OnPaint( wxPaintEvent& aEvent );
void OnOK( wxCommandEvent& aEvent );
void doCloseWindow() override;
void CloseFootprintChooser( wxCommandEvent& aEvent );
WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
COLOR_SETTINGS* GetColorSettings( bool aForceRefresh ) const override;
// Required pure-virtual methods
void ReCreateHToolbar() override {};
void ReCreateVToolbar() override {};
void SaveCopyInUndoList( EDA_ITEM*, UNDO_REDO ) override {}
void SaveCopyInUndoList( const PICKED_ITEMS_LIST&, UNDO_REDO ) override {}
void AppendCopyToUndoList( const PICKED_ITEMS_LIST&, UNDO_REDO ) override {}
DECLARE_EVENT_TABLE()
friend struct PCB::IFACE; // constructor called from here only
private:
PANEL_FOOTPRINT_CHOOSER* m_chooserPanel;
COMPONENT m_comp;
// On MacOS (at least) SetFocus() calls made in the constructor will fail because a
// window that isn't yet visible will return false to AcceptsFocus(). So we must delay
// the initial-focus SetFocus() call to the first paint event.
bool m_firstPaintEvent;
};
#endif // FOOTPRINT_CHOOSER_FRAME_H

View File

@ -106,29 +106,12 @@ BEGIN_EVENT_TABLE( FOOTPRINT_VIEWER_FRAME, PCB_BASE_FRAME )
END_EVENT_TABLE()
/*
* Note: FOOTPRINT_VIEWER_FRAME can be created in "modal mode", or as a usual frame.
*/
#define PARENT_STYLE ( KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT )
#define MODAL_STYLE ( KICAD_DEFAULT_DRAWFRAME_STYLE | wxSTAY_ON_TOP )
#define NONMODAL_STYLE ( KICAD_DEFAULT_DRAWFRAME_STYLE )
FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent,
FRAME_T aFrameType ) :
PCB_BASE_FRAME( aKiway, aParent, aFrameType, _( "Footprint Library Browser" ),
wxDefaultPosition, wxDefaultSize,
aFrameType == FRAME_FOOTPRINT_VIEWER_MODAL ? ( aParent ? PARENT_STYLE : MODAL_STYLE )
: NONMODAL_STYLE,
aFrameType == FRAME_FOOTPRINT_VIEWER_MODAL ? FOOTPRINT_VIEWER_FRAME_NAME_MODAL
: FOOTPRINT_VIEWER_FRAME_NAME ),
FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_VIEWER, _( "Footprint Library Browser" ),
wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE,
FOOTPRINT_VIEWER_FRAME_NAME ),
m_comp( LIB_ID(), wxEmptyString, wxEmptyString, KIID_PATH(), {} )
{
wxASSERT( aFrameType == FRAME_FOOTPRINT_VIEWER_MODAL || aFrameType == FRAME_FOOTPRINT_VIEWER );
if( aFrameType == FRAME_FOOTPRINT_VIEWER_MODAL )
SetModal( true );
m_aboutTitle = _HKI( "KiCad Footprint Library Viewer" );
// Force the items to always snap
@ -1067,13 +1050,13 @@ bool FOOTPRINT_VIEWER_FRAME::ShowModal( wxString* aFootprint, wxWindow* aParent
if( WX_INFOBAR* infobar = GetInfoBar() )
{
button = new wxHyperlinkCtrl( infobar, wxID_ANY,
_( "Manage symbol libraries" ),
wxEmptyString );
button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent & aEvent )>(
[=]( wxHyperlinkEvent& aEvent )
{
InvokePcbLibTableEditor( &Kiway(), this );
} ) );
_( "Manage footprint libraries" ),
wxEmptyString );
button->Bind( wxEVT_COMMAND_HYPERLINK,
[=]( wxHyperlinkEvent& aEvent )
{
InvokePcbLibTableEditor( &Kiway(), this );
} );
}
}

View File

@ -94,7 +94,7 @@ public:
void KiwayMailIn( KIWAY_EXPRESS& mail ) override;
protected:
FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType );
FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent );
MAGNETIC_SETTINGS m_magneticItems;

View File

@ -30,15 +30,13 @@ using namespace std::placeholders;
#include <footprint.h>
#include <confirm.h>
#include <connectivity/connectivity_data.h>
#include <dialog_choose_footprint.h>
#include <dialog_footprint_chooser.h>
#include <dialog_get_footprint_by_name.h>
#include <eda_list_dialog.h>
#include <footprint_edit_frame.h>
#include <footprint_info_impl.h>
#include <footprint_tree_pane.h>
#include <footprint_viewer_frame.h>
#include <fp_lib_table.h>
#include <core/ignore.h>
#include <io_mgr.h>
#include <string_utils.h>
#include <kiway.h>
@ -52,8 +50,6 @@ using namespace std::placeholders;
#include <widgets/wx_progress_reporters.h>
#include <dialog_pad_properties.h>
#include "fp_tree_model_adapter.h"
static wxArrayString s_FootprintHistoryList;
static unsigned s_FootprintHistoryMaxCount = 8;
@ -181,120 +177,25 @@ bool FOOTPRINT_EDIT_FRAME::LoadFootprintFromBoard( FOOTPRINT* aFootprint )
}
wxString PCB_BASE_FRAME::SelectFootprintFromLibBrowser()
FOOTPRINT* PCB_BASE_FRAME::SelectFootprintFromLibrary( LIB_ID aPreselect )
{
// Close the current non-modal Lib browser if opened, and open a new one, in "modal" mode:
FOOTPRINT_VIEWER_FRAME* viewer;
viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER, false );
if( viewer )
{
viewer->Destroy();
// Destroy() does not immediately delete the viewer, if some events are pending.
// (for this reason delete operator cannot be used blindly with "top level" windows)
// so gives a slice of time to delete the viewer frame.
// This is especially important in OpenGL mode to avoid recreating context before
// the old one is deleted.
wxSafeYield();
}
SetFocus();
// Creates the modal Lib browser:
viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true, this );
wxString fpid;
ignore_unused( viewer->ShowModal( &fpid, this ) );
viewer->Destroy();
return fpid;
}
FOOTPRINT* PCB_BASE_FRAME::SelectFootprintFromLibTree( LIB_ID aPreselect )
{
FP_LIB_TABLE* fpTable = Prj().PcbFootprintLibs();
wxString footprintName;
LIB_ID fpid;
FOOTPRINT* footprint = nullptr;
static wxString lastComponentName;
// Load footprint files:
WX_PROGRESS_REPORTER* progressReporter = new WX_PROGRESS_REPORTER( this,
_( "Loading Footprint Libraries" ), 3 );
GFootprintList.ReadFootprintFiles( fpTable, nullptr, progressReporter );
bool cancel = progressReporter->WasCancelled();
// Force immediate deletion of the WX_PROGRESS_REPORTER. Do not use Destroy(), or use
// Destroy() followed by wxSafeYield() because on Windows, APP_PROGRESS_DIALOG and
// WX_PROGRESS_REPORTER have some side effects on the event loop manager. For instance, a
// subsequent call to ShowModal() or ShowQuasiModal() for a dialog following the use of a
// WX_PROGRESS_REPORTER results in incorrect modal or quasi modal behavior.
delete progressReporter;
if( cancel )
return nullptr;
if( GFootprintList.GetErrorCount() )
GFootprintList.DisplayErrors( this );
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> ptr = FP_TREE_MODEL_ADAPTER::Create( this, fpTable );
FP_TREE_MODEL_ADAPTER* adapter = static_cast<FP_TREE_MODEL_ADAPTER*>( ptr.get() );
std::vector<LIB_TREE_ITEM*> historyInfos;
for( const wxString& item : s_FootprintHistoryList )
{
LIB_TREE_ITEM* fp_info = GFootprintList.GetFootprintInfo( item );
// this can be null, for example, if the footprint has been deleted from a library.
if( fp_info != nullptr )
historyInfos.push_back( fp_info );
}
adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString,
historyInfos, false, true );
if( aPreselect.IsValid() )
adapter->SetPreselectNode( aPreselect, 0 );
else if( historyInfos.size() )
adapter->SetPreselectNode( historyInfos[0]->GetLibId(), 0 );
adapter->AddLibraries( this );
wxString title;
title.Printf( _( "Choose Footprint (%d items loaded)" ), adapter->GetItemCount() );
DIALOG_CHOOSE_FOOTPRINT dialog( this, title, ptr );
DIALOG_FOOTPRINT_CHOOSER dialog( this, aPreselect, s_FootprintHistoryList );
if( dialog.ShowQuasiModal() == wxID_CANCEL )
return nullptr;
// Save any changes to column widths, etc.
adapter->SaveSettings();
fpid = dialog.GetSelectedLibId();
if( dialog.IsExternalBrowserSelected() )
{
// SelectFootprintFromLibBrowser() returns the "full" footprint name, i.e.
// <lib_name>/<footprint name> or LIB_ID format "lib_name:fp_name:rev#"
footprintName = SelectFootprintFromLibBrowser();
if( footprintName.IsEmpty() ) // Cancel command
return nullptr;
else
fpid.Parse( footprintName );
}
if( !fpid.IsValid() )
return nullptr;
else
{
fpid = dialog.GetSelectedLibId();
if( !fpid.IsValid() )
return nullptr;
else
footprintName = fpid.Format().wx_str();
}
footprintName = fpid.Format().wx_str();
try
{

View File

@ -92,7 +92,8 @@ PCB_BASE_FRAME::~PCB_BASE_FRAME()
m_spaceMouse = nullptr;
// Ensure m_canvasType is up to date, to save it in config
m_canvasType = GetCanvas()->GetBackend();
if( GetCanvas() )
m_canvasType = GetCanvas()->GetBackend();
delete m_pcb;
m_pcb = nullptr;
@ -992,7 +993,7 @@ PCB_VIEWERS_SETTINGS_BASE* PCB_BASE_FRAME::GetViewerSettingsBase() const
return Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
case FRAME_FOOTPRINT_VIEWER:
case FRAME_FOOTPRINT_VIEWER_MODAL:
case FRAME_FOOTPRINT_CHOOSER:
case FRAME_FOOTPRINT_PREVIEW:
case FRAME_CVPCB:
case FRAME_CVPCB_DISPLAY:

View File

@ -1054,7 +1054,7 @@ bool PCB_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
if( fpViewer && !fpViewer->Close() ) // Can close footprint viewer?
return false;
fpViewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, false );
fpViewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_CHOOSER, false );
if( fpViewer && !fpViewer->Close() ) // Can close modal footprint viewer?
return false;

View File

@ -88,7 +88,7 @@ PCB_VIEWERS_SETTINGS_BASE* PCB_PAINTER::viewer_settings()
return Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
case FRAME_FOOTPRINT_VIEWER:
case FRAME_FOOTPRINT_VIEWER_MODAL:
case FRAME_FOOTPRINT_CHOOSER:
case FRAME_FOOTPRINT_PREVIEW:
case FRAME_CVPCB:
case FRAME_CVPCB_DISPLAY:

View File

@ -42,6 +42,7 @@
#include <fp_lib_table.h>
#include <footprint_edit_frame.h>
#include <footprint_viewer_frame.h>
#include <footprint_chooser_frame.h>
#include <footprint_wizard_frame.h>
#include <footprint_preview_panel.h>
#include <footprint_info_impl.h>
@ -112,8 +113,10 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
return new FOOTPRINT_EDIT_FRAME( aKiway, aParent );
case FRAME_FOOTPRINT_VIEWER:
case FRAME_FOOTPRINT_VIEWER_MODAL:
return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent, FRAME_T( aClassId ) );
return new FOOTPRINT_VIEWER_FRAME( aKiway, aParent );
case FRAME_FOOTPRINT_CHOOSER:
return new FOOTPRINT_CHOOSER_FRAME( aKiway, aParent );
case FRAME_FOOTPRINT_WIZARD:
return new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, FRAME_T( aClassId ) );

View File

@ -1086,7 +1086,7 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
if( !fp )
{
// Pick the footprint to be placed
fp = m_frame->SelectFootprintFromLibTree();
fp = m_frame->SelectFootprintFromLibrary();
if( fp == nullptr )
continue;

View File

@ -150,8 +150,7 @@ bool PCB_SELECTION_TOOL::Init()
{
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
if( frame && ( frame->IsType( FRAME_FOOTPRINT_VIEWER )
|| frame->IsType( FRAME_FOOTPRINT_VIEWER_MODAL ) ) )
if( frame && frame->IsType( FRAME_FOOTPRINT_VIEWER ) )
{
frame->AddStandardSubMenus( m_menu );
return true;

View File

@ -67,7 +67,6 @@ int PCB_VIEWER_TOOLS::Show3DViewer( const TOOL_EVENT& aEvent )
EDA_3D_VIEWER_FRAME* draw3DFrame = frame()->CreateAndShow3D_Frame();
if( frame()->IsType( FRAME_FOOTPRINT_VIEWER )
|| frame()->IsType( FRAME_FOOTPRINT_VIEWER_MODAL )
|| frame()->IsType( FRAME_FOOTPRINT_WIZARD ) )
{
// A stronger version of Raise() which promotes the window to its parent's level.

View File

@ -0,0 +1,282 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
* Copyright (C) 2016-2023 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <widgets/panel_footprint_chooser.h>
#include <wx/button.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/splitter.h>
#include <wx/timer.h>
#include <wx/wxhtml.h>
#include <pcb_base_frame.h>
#include <pcbnew_settings.h>
#include <pgm_base.h>
#include <fp_lib_table.h>
#include <settings/settings_manager.h>
#include <widgets/lib_tree.h>
#include <widgets/footprint_preview_widget.h>
#include <widgets/wx_progress_reporters.h>
#include <footprint_info_impl.h>
PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent,
const wxArrayString& aFootprintHistoryList,
std::function<void()> aCloseHandler ) :
wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ),
m_hsplitter( nullptr ),
m_vsplitter( nullptr ),
m_frame( aFrame ),
m_closeHandler( std::move( aCloseHandler ) )
{
FP_LIB_TABLE* fpTable = aFrame->Prj().PcbFootprintLibs();
// Load footprint files:
WX_PROGRESS_REPORTER* progressReporter = new WX_PROGRESS_REPORTER( aParent,
_( "Loading Footprint Libraries" ), 3 );
GFootprintList.ReadFootprintFiles( fpTable, nullptr, progressReporter );
// Force immediate deletion of the WX_PROGRESS_REPORTER. Do not use Destroy(), or use
// Destroy() followed by wxSafeYield() because on Windows, APP_PROGRESS_DIALOG and
// WX_PROGRESS_REPORTER have some side effects on the event loop manager. For instance, a
// subsequent call to ShowModal() or ShowQuasiModal() for a dialog following the use of a
// WX_PROGRESS_REPORTER results in incorrect modal or quasi modal behavior.
delete progressReporter;
if( GFootprintList.GetErrorCount() )
GFootprintList.DisplayErrors( aParent );
m_adapter = FP_TREE_MODEL_ADAPTER::Create( aFrame, fpTable );
FP_TREE_MODEL_ADAPTER* adapter = static_cast<FP_TREE_MODEL_ADAPTER*>( m_adapter.get() );
std::vector<LIB_TREE_ITEM*> historyInfos;
for( const wxString& item : aFootprintHistoryList )
{
LIB_TREE_ITEM* fp_info = GFootprintList.GetFootprintInfo( item );
// this can be null, for example, if the footprint has been deleted from a library.
if( fp_info != nullptr )
historyInfos.push_back( fp_info );
}
adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString,
historyInfos, false, true );
if( historyInfos.size() )
adapter->SetPreselectNode( historyInfos[0]->GetLibId(), 0 );
adapter->AddLibraries( aFrame );
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
HTML_WINDOW* details = nullptr;
m_vsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxSP_LIVE_UPDATE | wxSP_3DSASH );
m_hsplitter = new wxSplitterWindow( m_vsplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxSP_LIVE_UPDATE | wxSP_3DSASH );
//Avoid the splitter window being assigned as the Parent to additional windows
m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
auto detailsPanel = new wxPanel( m_vsplitter );
auto detailsSizer = new wxBoxSizer( wxVERTICAL );
detailsPanel->SetSizer( detailsSizer );
details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxHW_SCROLLBAR_AUTO );
detailsSizer->Add( details, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
detailsPanel->Layout();
detailsSizer->Fit( detailsPanel );
m_vsplitter->SetSashGravity( 0.5 );
m_vsplitter->SetMinimumPaneSize( 20 );
m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel );
sizer->Add( m_vsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
m_tree = new LIB_TREE( m_hsplitter, wxT( "footprints" ), fpTable, m_adapter,
LIB_TREE::FLAGS::ALL_WIDGETS, details );
m_hsplitter->SetSashGravity( 0.8 );
m_hsplitter->SetMinimumPaneSize( 20 );
wxPanel* rightPanel = new wxPanel( m_hsplitter );
wxBoxSizer* rightPanelSizer = new wxBoxSizer( wxVERTICAL );
m_preview_ctrl = new FOOTPRINT_PREVIEW_WIDGET( rightPanel, m_frame->Kiway() );
m_preview_ctrl->SetUserUnits( m_frame->GetUserUnits() );
rightPanelSizer->Add( m_preview_ctrl, 1, wxEXPAND | wxTOP | wxRIGHT, 5 );
rightPanel->SetSizer( rightPanelSizer );
rightPanel->Layout();
rightPanelSizer->Fit( rightPanel );
m_hsplitter->SplitVertically( m_tree, rightPanel );
m_dbl_click_timer = new wxTimer( this );
SetSizer( sizer );
m_adapter->FinishTreeInitialization();
Bind( wxEVT_TIMER, &PANEL_FOOTPRINT_CHOOSER::onCloseTimer, this, m_dbl_click_timer->GetId() );
Bind( SYMBOL_PRESELECTED, &PANEL_FOOTPRINT_CHOOSER::onComponentPreselected, this );
Bind( SYMBOL_SELECTED, &PANEL_FOOTPRINT_CHOOSER::onComponentSelected, this );
Layout();
}
PANEL_FOOTPRINT_CHOOSER::~PANEL_FOOTPRINT_CHOOSER()
{
Unbind( wxEVT_TIMER, &PANEL_FOOTPRINT_CHOOSER::onCloseTimer, this );
Unbind( SYMBOL_PRESELECTED, &PANEL_FOOTPRINT_CHOOSER::onComponentPreselected, this );
Unbind( SYMBOL_SELECTED, &PANEL_FOOTPRINT_CHOOSER::onComponentSelected, this );
// I am not sure the following two lines are necessary, but they will not hurt anyone
m_dbl_click_timer->Stop();
delete m_dbl_click_timer;
if( PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>() )
{
// Save any changes to column widths, etc.
m_adapter->SaveSettings();
cfg->m_FootprintChooser.width = GetParent()->GetSize().x;
cfg->m_FootprintChooser.height = GetParent()->GetSize().y;
cfg->m_FootprintChooser.sash_h = m_hsplitter->GetSashPosition();
if( m_vsplitter )
cfg->m_FootprintChooser.sash_v = m_vsplitter->GetSashPosition();
cfg->m_FootprintChooser.sort_mode = m_tree->GetSortMode();
}
}
void PANEL_FOOTPRINT_CHOOSER::FinishSetup()
{
if( PCBNEW_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>() )
{
auto horizPixelsFromDU =
[&]( int x ) -> int
{
wxSize sz( x, 0 );
return GetParent()->ConvertDialogToPixels( sz ).x;
};
PCBNEW_SETTINGS::FOOTPRINT_CHOOSER& cfg = settings->m_FootprintChooser;
int w = cfg.width < 0 ? horizPixelsFromDU( 440 ) : cfg.width;
int h = cfg.height < 0 ? horizPixelsFromDU( 340 ) : cfg.height;
GetParent()->SetSize( wxSize( w, h ) );
GetParent()->Layout();
// We specify the width of the right window (m_symbol_view_panel), because specify
// the width of the left window does not work as expected when SetSashGravity() is called
if( cfg.sash_h < 0 )
cfg.sash_h = horizPixelsFromDU( 220 );
m_hsplitter->SetSashPosition( cfg.sash_h );
if( cfg.sash_v < 0 )
cfg.sash_v = horizPixelsFromDU( 230 );
if( m_vsplitter )
m_vsplitter->SetSashPosition( cfg.sash_v );
m_adapter->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) cfg.sort_mode );
}
}
void PANEL_FOOTPRINT_CHOOSER::SetPreselect( const LIB_ID& aPreselect )
{
m_adapter->SetPreselectNode( aPreselect, 0 );
}
LIB_ID PANEL_FOOTPRINT_CHOOSER::GetSelectedLibId() const
{
return m_tree->GetSelectedLibId();
}
void PANEL_FOOTPRINT_CHOOSER::onCloseTimer( wxTimerEvent& aEvent )
{
// Hack because of eaten MouseUp event. See PANEL_FOOTPRINT_CHOOSER::onComponentSelected
// for the beginning of this spaghetti noodle.
auto state = wxGetMouseState();
if( state.LeftIsDown() )
{
// Mouse hasn't been raised yet, so fire the timer again. Otherwise the
// purpose of this timer is defeated.
m_dbl_click_timer->StartOnce( PANEL_FOOTPRINT_CHOOSER::DblClickDelay );
}
else
{
m_closeHandler();
}
}
void PANEL_FOOTPRINT_CHOOSER::onComponentPreselected( wxCommandEvent& aEvent )
{
if( !m_preview_ctrl || !m_preview_ctrl->IsInitialized() )
return;
LIB_ID lib_id = m_tree->GetSelectedLibId();
if( !lib_id.IsValid() )
{
m_preview_ctrl->SetStatusText( _( "No footprint selected" ) );
}
else
{
m_preview_ctrl->ClearStatus();
m_preview_ctrl->DisplayFootprint( lib_id );
}
}
void PANEL_FOOTPRINT_CHOOSER::onComponentSelected( wxCommandEvent& aEvent )
{
if( m_tree->GetSelectedLibId().IsValid() )
{
// Got a selection. We can't just end the modal dialog here, because wx leaks some
// events back to the parent window (in particular, the MouseUp following a double click).
//
// NOW, here's where it gets really fun. wxTreeListCtrl eats MouseUp. This isn't really
// feasible to bypass without a fully custom wxDataViewCtrl implementation, and even then
// might not be fully possible (docs are vague). To get around this, we use a one-shot
// timer to schedule the dialog close.
//
// See PANEL_FOOTPRINT_CHOOSER::onCloseTimer for the other end of this spaghetti noodle.
m_dbl_click_timer->StartOnce( PANEL_FOOTPRINT_CHOOSER::DblClickDelay );
}
}

View File

@ -0,0 +1,99 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014-2023 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PANEL_FOOTPRINT_CHOOSER_H
#define PANEL_FOOTPRINT_CHOOSER_H
#include "dialog_shim.h"
#include <widgets/lib_tree.h>
#include <fp_tree_model_adapter.h>
#include <footprint_info.h>
#include <widgets/footprint_preview_widget.h>
class wxTimer;
class wxSplitterWindow;
class PCB_BASE_FRAME;
class PANEL_FOOTPRINT_CHOOSER : public wxPanel
{
public:
/**
* Create dialog to choose component.
*
* @param aFrame the parent frame (FRAME_PCB_EDIT_FRAME or FOOTPRINT_CHOOSER_FRAME)
* @param aParent the parent window (DIALOG_SHIM or FOOTPRINT_CHOOSER_FRAME)
* @param aCloseHandler a handler to be called on double-click of a footprint
*/
PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent,
const wxArrayString& aFootprintHistoryList,
std::function<void()> aCloseHandler );
~PANEL_FOOTPRINT_CHOOSER();
void FinishSetup();
void SetPreselect( const LIB_ID& aPreselect );
/**
* To be called after this dialog returns from ShowModal().
*
* @return the #LIB_ID of the symbol that has been selected.
*/
LIB_ID GetSelectedLibId() const;
int GetItemCount() const { return m_adapter->GetItemCount(); }
wxWindow* GetFocusTarget() const { return m_tree->GetFocusTarget(); }
protected:
static constexpr int DblClickDelay = 100; // milliseconds
void onCloseTimer( wxTimerEvent& aEvent );
void onComponentPreselected( wxCommandEvent& aEvent );
/**
* Handle the selection of an item. This is called when either the search
* box or the tree receive an Enter, or the tree receives a double click.
* If the item selected is a category, it is expanded or collapsed; if it
* is a component, the component is picked.
*/
void onComponentSelected( wxCommandEvent& aEvent );
protected:
wxTimer* m_dbl_click_timer;
wxSplitterWindow* m_hsplitter;
wxSplitterWindow* m_vsplitter;
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> m_adapter;
FOOTPRINT_PREVIEW_WIDGET* m_preview_ctrl;
LIB_TREE* m_tree;
PCB_BASE_FRAME* m_frame;
std::function<void()> m_closeHandler;
};
#endif /* PANEL_FOOTPRINT_CHOOSER_H */