KiCad PCB EDA Suite
footprint_select_widget.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) 2017 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <dialog_shim.h>
21 #include <eda_draw_frame.h>
22 #include <kiway.h>
23 #include <kiway_player.h>
24 #include <project.h>
27 
28 #include <wx/wupdlock.h>
30 
34 enum
35 {
39 };
40 
41 
42 wxDEFINE_EVENT( EVT_FOOTPRINT_SELECTED, wxCommandEvent );
43 
44 
46  FOOTPRINT_LIST* aFpList, bool aUpdate, int aMaxItems ) :
47  wxPanel( aParent ),
48  m_kiway( nullptr ),
49  m_update( aUpdate ),
50  m_finished_loading( false ),
51  m_max_items( aMaxItems ),
52  m_last_item( 0 ),
53  m_fp_list( aFpList ),
54  m_eda_frame( aFrame )
55 {
56  m_zero_filter = true;
57  m_sizer = new wxBoxSizer( wxVERTICAL );
58  m_fp_sel_ctrl = new FOOTPRINT_CHOICE( this, wxID_ANY );
59  m_sizer->Add( m_fp_sel_ctrl, 1, wxEXPAND, 5 );
60 
61  SetSizer( m_sizer );
62  Layout();
63  m_sizer->Fit( this );
64 
65  m_fp_sel_ctrl->Bind( wxEVT_COMBOBOX, &FOOTPRINT_SELECT_WIDGET::OnComboBox, this );
66  m_fp_sel_ctrl->Bind( EVT_INTERACTIVE_CHOICE, &FOOTPRINT_SELECT_WIDGET::OnComboInteractive, this );
67 }
68 
69 
70 void FOOTPRINT_SELECT_WIDGET::Load( KIWAY& aKiway, PROJECT& aProject )
71 {
72  m_kiway = &aKiway;
73 
74  try
75  {
76  auto fp_lib_table = aProject.PcbFootprintLibs( aKiway );
78 
79  // We parent to the eda frame so that the taskbar progress indicator displays on it
80  WX_PROGRESS_REPORTER progressReporter( m_eda_frame, _( "Loading Footprint Libraries" ), 2 );
81  m_fp_list->ReadFootprintFiles( fp_lib_table, nullptr, &progressReporter );
83  }
84  catch( ... )
85  {
86  // no footprint libraries available
87  }
88 }
89 
90 
92 {
94 
95  m_finished_loading = true;
96 
97  if( m_update )
98  UpdateList();
99 }
100 
101 
102 void FOOTPRINT_SELECT_WIDGET::OnComboBox( wxCommandEvent& aEvent )
103 {
104  wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
105  int sel = m_fp_sel_ctrl->GetSelection();
106 
107  switch( sel )
108  {
109  case wxNOT_FOUND: return;
110 
111  case POS_SEPARATOR:
112  // User somehow managed to select the separator. This should not be
113  // possible, but just in case... deselect it
114  m_fp_sel_ctrl->SetSelection( m_last_item );
115  break;
116 
117  case POS_OTHER:
118  // When POS_OTHER is selected, a dialog should be shown. However, we don't want to
119  // do this ALL the time, as some times (e.g. when moving around with the arrow keys)
120  // it could be very annoying. Therefore showing the picker is done from the custom
121  // "interactive select" event on FOOTPRINT_CHOICE, which only fires for more direct
122  // choice actions.
123  break;
124 
125  default:
126  {
127  wxStringClientData* clientdata =
128  static_cast<wxStringClientData*>( m_fp_sel_ctrl->GetClientObject( sel ) );
129  wxASSERT( clientdata );
130 
131  evt.SetString( clientdata->GetData() );
132  wxPostEvent( this, evt );
133  }
134  }
135 }
136 
137 
138 void FOOTPRINT_SELECT_WIDGET::OnComboInteractive( wxCommandEvent& aEvent )
139 {
140  if( aEvent.GetInt() == POS_OTHER && !m_fp_sel_ctrl->IsPopupShown() )
141  {
142  DoOther();
143  }
144 }
145 
146 
148 {
149  wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
150 
151  wxString fpname = ShowPicker();
152  m_other_footprint = fpname;
153  UpdateList();
154  m_fp_sel_ctrl->SetSelection( POS_OTHER );
156 
157  evt.SetString( m_other_footprint );
158  wxPostEvent( this, evt );
159 }
160 
161 
163 {
164  wxString fpname;
165  wxWindow* parent = ::wxGetTopLevelParent( this );
166  DIALOG_SHIM* dsparent = dynamic_cast<DIALOG_SHIM*>( parent );
167 
168  // Only quasimodal dialogs can launch modal kiface dialogs. Otherwise the
169  // event loop goes all silly.
170  wxASSERT( !dsparent || dsparent->IsQuasiModal() );
171 
172  auto frame = m_kiway->Player( FRAME_FOOTPRINT_VIEWER_MODAL, true );
173 
174  if( !frame->ShowModal( &fpname, parent ) )
175  {
176  fpname = wxEmptyString;
177  }
178 
179  frame->Destroy();
180 
181  return fpname;
182 }
183 
184 
186 {
188  m_default_footprint.Clear();
189  m_other_footprint.Clear();
190  m_zero_filter = false;
191 }
192 
193 
195 {
196  m_fp_filter.FilterByPinCount( aPinCount );
197 }
198 
199 
200 void FOOTPRINT_SELECT_WIDGET::FilterByFootprintFilters( wxArrayString const& aFilters,
201  bool aZeroFilters )
202 {
203  m_zero_filter = ( aZeroFilters && aFilters.size() == 0 );
205 }
206 
207 
209 {
210  m_default_footprint = aFp;
211 }
212 
213 
215 {
216  int n_items = 0;
217 
218  if( !m_fp_list || !m_finished_loading )
219  return false;
220 
221  wxWindowUpdateLocker lock( m_fp_sel_ctrl );
222  m_fp_sel_ctrl->Clear();
223 
224  // Be careful adding items! "Default" must occupy POS_DEFAULT,
225  // "Other" must occupy POS_OTHER, and the separator must occupy POS_SEPARATOR.
226 
227  m_fp_sel_ctrl->Append( m_default_footprint.IsEmpty() ?
228  _( "No default footprint" ) :
229  "[" + _( "Default" ) + "] " + m_default_footprint,
230  new wxStringClientData( m_default_footprint ) );
231 
232  m_fp_sel_ctrl->Append( m_other_footprint.IsEmpty() ?
233  _( "Other..." ) :
234  "[" + _( "Other..." ) + "] " + m_other_footprint,
235  new wxStringClientData( m_other_footprint ) );
236 
237  m_fp_sel_ctrl->Append( "", new wxStringClientData( "" ) );
238 
239  if( !m_zero_filter )
240  {
241  for( auto& fpinfo : m_fp_filter )
242  {
243  wxString display_name( fpinfo.GetLibNickname() + ":" + fpinfo.GetFootprintName() );
244 
245  m_fp_sel_ctrl->Append( display_name, new wxStringClientData( display_name ) );
246  ++n_items;
247 
248  if( n_items >= m_max_items )
249  break;
250  }
251  }
252 
253  SelectDefault();
254  return true;
255 }
256 
257 
259 {
260  m_fp_sel_ctrl->SetSelection( POS_DEFAULT );
261 }
262 
263 
265 {
266  return m_fp_sel_ctrl->Enable( aEnable );
267 }
void SetList(FOOTPRINT_LIST &aList)
Set the list to filter.
PROJECT holds project specific data.
Definition: project.h:61
void FilterByFootprintFilters(wxArrayString const &aFilters, bool aZeroFilters)
Filter by footprint filter list.
void OnComboInteractive(wxCommandEvent &aEvent)
void DoOther()
Handle activation of the "Other..." item.
void FilterByFootprintFilters(wxArrayString const &aFilters)
Set a list of footprint filters to filter by.
void ClearFilters()
Clear all filter criteria.
void SetDefaultFootprint(wxString const &aFp)
Set the default footprint for a part.
Customized combo box for footprint selection.
wxString ShowPicker()
Show the component picker and return the selected component. Used by DoOther()
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:83
wxDEFINE_EVENT(EVT_FOOTPRINT_SELECTED, wxCommandEvent)
The base class for create windows for drawing purpose.
void ClearFilters()
Clear all filters.
bool UpdateList()
Update the contents of the list to match the filters.
void FilterByPinCount(int aPinCount)
Set a pin count to filter by.
static FOOTPRINT_LIST * GetInstance(KIWAY &aKiway)
Factory function to return a FOOTPRINT_LIST via Kiway.
Multi-thread safe progress reporter dialog, intended for use of tasks that paralleize reporting back ...
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:343
virtual bool ReadFootprintFiles(FP_LIB_TABLE *aTable, const wxString *aNickname=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)=0
Read all the footprints provided by the combination of aTable and aNickname.
void OnComboBox(wxCommandEvent &aEvent)
bool IsQuasiModal()
Definition: dialog_shim.h:123
KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the s...
Definition: kiway.h:273
virtual bool Enable(bool aEnable=true) override
Enable or disable the control for input.
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:286
void SelectDefault()
Set current selection to the default footprint.
Holds a list of FOOTPRINT_INFO objects, along with a list of IO_ERRORs or PARSE_ERRORs that were thro...
#define _(s)
Definition: 3d_actions.cpp:33
FOOTPRINT_SELECT_WIDGET(EDA_DRAW_FRAME *aFrame, wxWindow *aParent, FOOTPRINT_LIST *aFpList, bool aUpdate=true, int aMaxItems=400)
Construct a footprint selector widget.
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
void Load(KIWAY &aKiway, PROJECT &aProject)
Start loading.
void FilterByPinCount(int aPinCount)
Filter by pin count.