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 <kiway.h>
22 #include <kiway_player.h>
23 #include <project.h>
26 
27 #include <wx/wupdlock.h>
29 
33 enum
34 {
38 };
39 
40 
41 wxDEFINE_EVENT( EVT_FOOTPRINT_SELECTED, wxCommandEvent );
42 
43 
45  FOOTPRINT_LIST* aFpList, bool aUpdate,
46  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 {
55  m_zero_filter = true;
56  m_sizer = new wxBoxSizer( wxVERTICAL );
57  m_fp_sel_ctrl = new FOOTPRINT_CHOICE( this, wxID_ANY );
58  m_sizer->Add( m_fp_sel_ctrl, 1, wxEXPAND, 5 );
59 
60  SetSizer( m_sizer );
61  Layout();
62  m_sizer->Fit( this );
63 
64  m_fp_sel_ctrl->Bind( wxEVT_COMBOBOX, &FOOTPRINT_SELECT_WIDGET::OnComboBox, this );
65  m_fp_sel_ctrl->Bind( EVT_INTERACTIVE_CHOICE, &FOOTPRINT_SELECT_WIDGET::OnComboInteractive, this );
66 }
67 
68 
69 void FOOTPRINT_SELECT_WIDGET::Load( KIWAY& aKiway, PROJECT& aProject )
70 {
71  m_kiway = &aKiway;
72 
73  try
74  {
75  auto fp_lib_table = aProject.PcbFootprintLibs( aKiway );
77 
78  WX_PROGRESS_REPORTER progressReporter( this, _( "Loading Footprint Libraries" ), 2 );
79  m_fp_list->ReadFootprintFiles( fp_lib_table, nullptr, &progressReporter );
81  }
82  catch( ... )
83  {
84  // no footprint libraries available
85  }
86 }
87 
88 
90 {
92 
93  m_finished_loading = true;
94 
95  if( m_update )
96  UpdateList();
97 }
98 
99 
100 void FOOTPRINT_SELECT_WIDGET::OnComboBox( wxCommandEvent& aEvent )
101 {
102  wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
103  int sel = m_fp_sel_ctrl->GetSelection();
104 
105  switch( sel )
106  {
107  case wxNOT_FOUND: return;
108 
109  case POS_SEPARATOR:
110  // User somehow managed to select the separator. This should not be
111  // possible, but just in case... deselect it
112  m_fp_sel_ctrl->SetSelection( m_last_item );
113  break;
114 
115  case POS_OTHER:
116  // When POS_OTHER is selected, a dialog should be shown. However, we don't want to
117  // do this ALL the time, as some times (e.g. when moving around with the arrow keys)
118  // it could be very annoying. Therefore showing the picker is done from the custom
119  // "interactive select" event on FOOTPRINT_CHOICE, which only fires for more direct
120  // choice actions.
121  break;
122 
123  default:
124  {
125  wxStringClientData* clientdata =
126  static_cast<wxStringClientData*>( m_fp_sel_ctrl->GetClientObject( sel ) );
127  wxASSERT( clientdata );
128 
129  evt.SetString( clientdata->GetData() );
130  wxPostEvent( this, evt );
131  }
132  }
133 }
134 
135 
136 void FOOTPRINT_SELECT_WIDGET::OnComboInteractive( wxCommandEvent& aEvent )
137 {
138  if( aEvent.GetInt() == POS_OTHER && !m_fp_sel_ctrl->IsPopupShown() )
139  {
140  DoOther();
141  }
142 }
143 
144 
146 {
147  wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
148 
149  wxString fpname = ShowPicker();
150  m_other_footprint = fpname;
151  UpdateList();
152  m_fp_sel_ctrl->SetSelection( POS_OTHER );
154 
155  evt.SetString( m_other_footprint );
156  wxPostEvent( this, evt );
157 }
158 
159 
161 {
162  wxString fpname;
163  wxWindow* parent = ::wxGetTopLevelParent( this );
164  DIALOG_SHIM* dsparent = dynamic_cast<DIALOG_SHIM*>( parent );
165 
166  // Only quasimodal dialogs can launch modal kiface dialogs. Otherwise the
167  // event loop goes all silly.
168  wxASSERT( !dsparent || dsparent->IsQuasiModal() );
169 
170  auto frame = m_kiway->Player( FRAME_PCB_MODULE_VIEWER_MODAL, true );
171 
172  if( !frame->ShowModal( &fpname, parent ) )
173  {
174  fpname = wxEmptyString;
175  }
176 
177  frame->Destroy();
178 
179  return fpname;
180 }
181 
182 
184 {
186  m_default_footprint.Clear();
187  m_other_footprint.Clear();
188  m_zero_filter = false;
189 }
190 
191 
193 {
194  m_fp_filter.FilterByPinCount( aPinCount );
195 }
196 
197 
199  wxArrayString const& aFilters, bool aZeroFilters )
200 {
201  if( aZeroFilters && aFilters.size() == 0 )
202  m_zero_filter = true;
203  else
204  m_zero_filter = false;
205 
207 }
208 
209 
211 {
212  m_default_footprint = aFp;
213 }
214 
215 
217 {
218  int n_items = 0;
219 
220  if( !m_fp_list || !m_finished_loading )
221  return false;
222 
223  wxWindowUpdateLocker lock( m_fp_sel_ctrl );
224  m_fp_sel_ctrl->Clear();
225 
226  // Be careful adding items! "Default" must occupy POS_DEFAULT,
227  // "Other" must occupy POS_OTHER, and the separator must occupy POS_SEPARATOR.
228 
229  m_fp_sel_ctrl->Append( m_default_footprint.IsEmpty() ?
230  _( "No default footprint" ) :
231  "[" + _( "Default" ) + "] " + m_default_footprint,
232  new wxStringClientData( m_default_footprint ) );
233 
234  m_fp_sel_ctrl->Append( m_other_footprint.IsEmpty() ?
235  _( "Other..." ) :
236  "[" + _( "Other..." ) + "] " + m_other_footprint,
237  new wxStringClientData( m_other_footprint ) );
238 
239  m_fp_sel_ctrl->Append( "", new wxStringClientData( "" ) );
240 
241  if( !m_zero_filter )
242  {
243  for( auto& fpinfo : m_fp_filter )
244  {
245  wxString display_name( fpinfo.GetLibNickname() + ":" + fpinfo.GetFootprintName() );
246 
247  m_fp_sel_ctrl->Append( display_name, new wxStringClientData( display_name ) );
248  ++n_items;
249 
250  if( n_items >= m_max_items )
251  break;
252  }
253  }
254 
255  SelectDefault();
256  return true;
257 }
258 
259 
261 {
262  m_fp_sel_ctrl->SetSelection( POS_DEFAULT );
263 }
264 
265 
267 {
268  return m_fp_sel_ctrl->Enable( aEnable );
269 }
void SetList(FOOTPRINT_LIST &aList)
Set the list to filter.
Class PROJECT holds project specific data.
Definition: project.h:57
void FilterByFootprintFilters(wxArrayString const &aFilters, bool aZeroFilters)
Filter by footprint filter list.
void OnComboInteractive(wxCommandEvent &aEvent)
void DoOther()
Handle activation of the "Other..." item.
FOOTPRINT_SELECT_WIDGET(wxWindow *aParent, FOOTPRINT_LIST *aFpList, bool aUpdate=true, int aMaxItems=400)
Construct a footprint selector widget.
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()
Class DIALOG_SHIM may sit in the inheritance tree between wxDialog and any class written by wxFormBui...
Definition: dialog_shim.h:82
wxDEFINE_EVENT(EVT_FOOTPRINT_SELECTED, wxCommandEvent)
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.
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:300
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:124
Class KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within...
Definition: kiway.h:258
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.
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...
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.