KiCad PCB EDA Suite
dialog_choose_footprint.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2014 Henner Zeller <[email protected]>
5 * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26#include <algorithm>
27#include <wx/utils.h>
28#include <wx/button.h>
29#include <wx/panel.h>
30#include <wx/sizer.h>
31#include <wx/splitter.h>
32#include <wx/timer.h>
33#include <wx/wxhtml.h>
34#include <pcb_base_frame.h>
35#include <pcbnew_settings.h>
36#include <pgm_base.h>
37#include <fp_lib_table.h>
39#include <widgets/lib_tree.h>
42#include <kiface_base.h>
43
44
46 const wxString& aTitle,
47 wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>& aAdapter )
48 : DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, wxDefaultSize,
49 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
50 m_browser_button( nullptr ),
51 m_hsplitter( nullptr ),
52 m_vsplitter( nullptr ),
53 m_parent( aParent ),
54 m_external_browser_requested( false )
55{
56 auto sizer = new wxBoxSizer( wxVERTICAL );
57 HTML_WINDOW* details = nullptr;
58
59 m_vsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
60 wxSP_LIVE_UPDATE );
61
62 m_hsplitter = new wxSplitterWindow( m_vsplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
63 wxSP_LIVE_UPDATE );
64
65 //Avoid the splitter window being assigned as the Parent to additional windows
66 m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
67
68 auto detailsPanel = new wxPanel( m_vsplitter );
69 auto detailsSizer = new wxBoxSizer( wxVERTICAL );
70 detailsPanel->SetSizer( detailsSizer );
71
72 details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
73 wxHW_SCROLLBAR_AUTO );
74 detailsSizer->Add( details, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
75 detailsPanel->Layout();
76 detailsSizer->Fit( detailsPanel );
77
78 m_vsplitter->SetSashGravity( 0.5 );
79 m_vsplitter->SetMinimumPaneSize( 20 );
80 m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel );
81
82 sizer->Add( m_vsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
83
84 m_tree = new LIB_TREE( m_hsplitter, wxT( "footprints" ), Prj().PcbFootprintLibs(), aAdapter,
85 LIB_TREE::FLAGS::ALL_WIDGETS, details );
86
87 m_hsplitter->SetSashGravity( 0.8 );
88 m_hsplitter->SetMinimumPaneSize( 20 );
89 m_hsplitter->SplitVertically( m_tree, ConstructRightPanel( m_hsplitter ) );
90
91 m_dbl_click_timer = new wxTimer( this );
92
93 auto buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
94
95 m_browser_button = new wxButton( this, wxID_ANY, _( "Select with Browser" ) );
96 buttonsSizer->Add( m_browser_button, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
97
98 auto sdbSizer = new wxStdDialogButtonSizer();
99 auto okButton = new wxButton( this, wxID_OK );
100 auto cancelButton = new wxButton( this, wxID_CANCEL );
101 sdbSizer->AddButton( okButton );
102 sdbSizer->AddButton( cancelButton );
103 sdbSizer->Realize();
104
105 buttonsSizer->Add( sdbSizer, 1, wxALL, 5 );
106
107 sizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 );
108 SetSizer( sizer );
109
110 aAdapter->FinishTreeInitialization();
111
113
114 Bind( wxEVT_TIMER, &DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer, this, m_dbl_click_timer->GetId() );
115 Bind( SYMBOL_PRESELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentPreselected, this );
116 Bind( SYMBOL_SELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentSelected, this );
117 m_browser_button->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_CHOOSE_FOOTPRINT::OnUseBrowser,
118 this );
119
120 Layout();
121
122 auto cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
123
124 // We specify the width of the right window (m_symbol_view_panel), because specify
125 // the width of the left window does not work as expected when SetSashGravity() is called
126 if( cfg->m_FootprintChooser.sash_h < 0 )
128
129 m_hsplitter->SetSashPosition( cfg->m_FootprintChooser.sash_h );
130
131 if( cfg->m_FootprintChooser.sash_v < 0 )
132 cfg->m_FootprintChooser.sash_v = horizPixelsFromDU( 230 );
133
134 if( m_vsplitter )
135 m_vsplitter->SetSashPosition( cfg->m_FootprintChooser.sash_v );
136
137 int w = cfg->m_FootprintChooser.width < 0 ?
138 horizPixelsFromDU( 440 ) : cfg->m_FootprintChooser.width;
139 int h = cfg->m_FootprintChooser.height < 0 ?
140 horizPixelsFromDU( 340 ) : cfg->m_FootprintChooser.height;
141 SetSize( wxSize( w, h ) );
142
144}
145
146
148{
149 Unbind( wxEVT_TIMER, &DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer, this );
150 Unbind( SYMBOL_PRESELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentPreselected, this );
151 Unbind( SYMBOL_SELECTED, &DIALOG_CHOOSE_FOOTPRINT::OnComponentSelected, this );
152 m_browser_button->Unbind( wxEVT_COMMAND_BUTTON_CLICKED,
154
155 // I am not sure the following two lines are necessary,
156 // but they will not hurt anyone
157 m_dbl_click_timer->Stop();
158 delete m_dbl_click_timer;
159
160 auto cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
161
162 cfg->m_FootprintChooser.width = GetSize().x;
163 cfg->m_FootprintChooser.height = GetSize().y;
164 cfg->m_FootprintChooser.sash_h = m_hsplitter->GetSashPosition();
165
166 if( m_vsplitter )
167 cfg->m_FootprintChooser.sash_v = m_vsplitter->GetSashPosition();
168}
169
170
172{
173 auto panel = new wxPanel( aParent );
174 auto sizer = new wxBoxSizer( wxVERTICAL );
175
178 sizer->Add( m_preview_ctrl, 1, wxEXPAND | wxTOP | wxRIGHT, 5 );
179
180 panel->SetSizer( sizer );
181 panel->Layout();
182 sizer->Fit( panel );
183
184 return panel;
185}
186
187
189{
190 return m_tree->GetSelectedLibId();
191}
192
193
194void DIALOG_CHOOSE_FOOTPRINT::OnUseBrowser( wxCommandEvent& aEvent )
195{
197 EndQuasiModal( wxID_OK );
198}
199
200
201void DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer( wxTimerEvent& aEvent )
202{
203 // Hack handler because of eaten MouseUp event. See
204 // DIALOG_CHOOSE_FOOTPRINT::OnComponentSelected for the beginning
205 // of this spaghetti noodle.
206
207 auto state = wxGetMouseState();
208
209 if( state.LeftIsDown() )
210 {
211 // Mouse hasn't been raised yet, so fire the timer again. Otherwise the
212 // purpose of this timer is defeated.
214 }
215 else
216 {
217 EndQuasiModal( wxID_OK );
218 }
219}
220
221
223{
225 return;
226
227 LIB_ID lib_id = m_tree->GetSelectedLibId();
228
229 if( !lib_id.IsValid() )
230 {
231 m_preview_ctrl->SetStatusText( _( "No footprint selected" ) );
232 }
233 else
234 {
237 }
238}
239
240
242{
244 {
245 // Got a selection. We can't just end the modal dialog here, because
246 // wx leaks some events back to the parent window (in particular, the
247 // MouseUp following a double click).
248 //
249 // NOW, here's where it gets really fun. wxTreeListCtrl eats MouseUp.
250 // This isn't really feasible to bypass without a fully custom
251 // wxDataViewCtrl implementation, and even then might not be fully
252 // possible (docs are vague). To get around this, we use a one-shot
253 // timer to schedule the dialog close.
254 //
255 // See DIALOG_CHOOSE_FOOTPRINT::OnCloseTimer for the other end of this
256 // spaghetti noodle.
258 }
259}
void OnCloseTimer(wxTimerEvent &aEvent)
DIALOG_CHOOSE_FOOTPRINT(PCB_BASE_FRAME *aParent, const wxString &aTitle, wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > &aAdapter)
Create dialog to choose component.
wxPanel * ConstructRightPanel(wxWindow *aParent)
void OnComponentPreselected(wxCommandEvent &aEvent)
void OnComponentSelected(wxCommandEvent &aEvent)
Handle the selection of an item.
void OnUseBrowser(wxCommandEvent &aEvent)
static constexpr int DblClickDelay
FOOTPRINT_PREVIEW_WIDGET * m_preview_ctrl
LIB_ID GetSelectedLibId() const
To be called after this dialog returns from ShowModal().
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:83
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int horizPixelsFromDU(int x) const
Convert an integer number of dialog units to pixels, horizontally.
void EndQuasiModal(int retCode)
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:121
void DisplayFootprint(const LIB_ID &aFPID)
Set the currently displayed footprint.
void SetUserUnits(EDA_UNITS aUnits)
Set the units for the preview.
bool IsInitialized() const
Return whether the widget initialized properly.
void SetStatusText(const wxString &aText)
Set the contents of the status label and display it.
void ClearStatus()
Clear the contents of the status label and hide it.
Add dark theme support to wxHtmlWindow.
Definition: html_window.h:34
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
Widget displaying a tree of symbols with optional search text control and description panel....
Definition: lib_tree.h:46
wxWindow * GetFocusTarget()
Definition: lib_tree.cpp:319
LIB_ID GetSelectedLibId(int *aUnit=nullptr) const
For multi-unit symbols, if the user selects the symbol itself rather than picking an individual unit,...
Definition: lib_tree.cpp:188
FOOTPRINT_CHOOSER m_FootprintChooser
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
#define _(s)
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111