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  bool aUpdate, int aMaxItems ) :
46  wxPanel( aParent ),
47  m_kiway( nullptr ),
48  m_update( aUpdate ),
49  m_finished_loading( false ),
50  m_max_items( aMaxItems ),
51  m_last_item( 0 ),
52  m_fp_list( aFpList )
53 {
54  m_zero_filter = true;
55  m_sizer = new wxBoxSizer( wxVERTICAL );
56  m_fp_sel_ctrl = new FOOTPRINT_CHOICE( this, wxID_ANY );
57  m_sizer->Add( m_fp_sel_ctrl, 1, wxEXPAND, 5 );
58 
59  SetSizer( m_sizer );
60  Layout();
61  m_sizer->Fit( this );
62 
63  m_fp_sel_ctrl->Bind( wxEVT_COMBOBOX, &FOOTPRINT_SELECT_WIDGET::OnComboBox, this );
64  m_fp_sel_ctrl->Bind( EVT_INTERACTIVE_CHOICE, &FOOTPRINT_SELECT_WIDGET::OnComboInteractive, this );
65 }
66 
67 
68 void FOOTPRINT_SELECT_WIDGET::Load( KIWAY& aKiway, PROJECT& aProject )
69 {
70  m_kiway = &aKiway;
71 
72  try
73  {
74  auto fp_lib_table = aProject.PcbFootprintLibs( aKiway );
76 
77  WX_PROGRESS_REPORTER progressReporter( this, _( "Loading Footprint Libraries" ), 2 );
78  m_fp_list->ReadFootprintFiles( fp_lib_table, nullptr, &progressReporter );
80  }
81  catch( ... )
82  {
83  // no footprint libraries available
84  }
85 }
86 
87 
89 {
91 
92  m_finished_loading = true;
93 
94  if( m_update )
95  UpdateList();
96 }
97 
98 
99 void FOOTPRINT_SELECT_WIDGET::OnComboBox( wxCommandEvent& aEvent )
100 {
101  wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
102  int sel = m_fp_sel_ctrl->GetSelection();
103 
104  switch( sel )
105  {
106  case wxNOT_FOUND: return;
107 
108  case POS_SEPARATOR:
109  // User somehow managed to select the separator. This should not be
110  // possible, but just in case... deselect it
111  m_fp_sel_ctrl->SetSelection( m_last_item );
112  break;
113 
114  case POS_OTHER:
115  // When POS_OTHER is selected, a dialog should be shown. However, we don't want to
116  // do this ALL the time, as some times (e.g. when moving around with the arrow keys)
117  // it could be very annoying. Therefore showing the picker is done from the custom
118  // "interactive select" event on FOOTPRINT_CHOICE, which only fires for more direct
119  // choice actions.
120  break;
121 
122  default:
123  {
124  wxStringClientData* clientdata =
125  static_cast<wxStringClientData*>( m_fp_sel_ctrl->GetClientObject( sel ) );
126  wxASSERT( clientdata );
127 
128  evt.SetString( clientdata->GetData() );
129  wxPostEvent( this, evt );
130  }
131  }
132 }
133 
134 
135 void FOOTPRINT_SELECT_WIDGET::OnComboInteractive( wxCommandEvent& aEvent )
136 {
137  if( aEvent.GetInt() == POS_OTHER && !m_fp_sel_ctrl->IsPopupShown() )
138  {
139  DoOther();
140  }
141 }
142 
143 
145 {
146  wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
147 
148  wxString fpname = ShowPicker();
149  m_other_footprint = fpname;
150  UpdateList();
151  m_fp_sel_ctrl->SetSelection( POS_OTHER );
153 
154  evt.SetString( m_other_footprint );
155  wxPostEvent( this, evt );
156 }
157 
158 
160 {
161  wxString fpname;
162  wxWindow* parent = ::wxGetTopLevelParent( this );
163  DIALOG_SHIM* dsparent = dynamic_cast<DIALOG_SHIM*>( parent );
164 
165  // Only quasimodal dialogs can launch modal kiface dialogs. Otherwise the
166  // event loop goes all silly.
167  wxASSERT( !dsparent || dsparent->IsQuasiModal() );
168 
169  auto frame = m_kiway->Player( FRAME_FOOTPRINT_VIEWER_MODAL, true );
170 
171  if( !frame->ShowModal( &fpname, parent ) )
172  {
173  fpname = wxEmptyString;
174  }
175 
176  frame->Destroy();
177 
178  return fpname;
179 }
180 
181 
183 {
185  m_default_footprint.Clear();
186  m_other_footprint.Clear();
187  m_zero_filter = false;
188 }
189 
190 
192 {
193  m_fp_filter.FilterByPinCount( aPinCount );
194 }
195 
196 
197 void FOOTPRINT_SELECT_WIDGET::FilterByFootprintFilters( wxArrayString const& aFilters,
198  bool aZeroFilters )
199 {
200  m_zero_filter = ( aZeroFilters && aFilters.size() == 0 );
202 }
203 
204 
206 {
207  m_default_footprint = aFp;
208 }
209 
210 
212 {
213  int n_items = 0;
214 
215  if( !m_fp_list || !m_finished_loading )
216  return false;
217 
218  wxWindowUpdateLocker lock( m_fp_sel_ctrl );
219  m_fp_sel_ctrl->Clear();
220 
221  // Be careful adding items! "Default" must occupy POS_DEFAULT,
222  // "Other" must occupy POS_OTHER, and the separator must occupy POS_SEPARATOR.
223 
224  m_fp_sel_ctrl->Append( m_default_footprint.IsEmpty() ?
225  _( "No default footprint" ) :
226  "[" + _( "Default" ) + "] " + m_default_footprint,
227  new wxStringClientData( m_default_footprint ) );
228 
229  m_fp_sel_ctrl->Append( m_other_footprint.IsEmpty() ?
230  _( "Other..." ) :
231  "[" + _( "Other..." ) + "] " + m_other_footprint,
232  new wxStringClientData( m_other_footprint ) );
233 
234  m_fp_sel_ctrl->Append( "", new wxStringClientData( "" ) );
235 
236  if( !m_zero_filter )
237  {
238  for( auto& fpinfo : m_fp_filter )
239  {
240  wxString display_name( fpinfo.GetLibNickname() + ":" + fpinfo.GetFootprintName() );
241 
242  m_fp_sel_ctrl->Append( display_name, new wxStringClientData( display_name ) );
243  ++n_items;
244 
245  if( n_items >= m_max_items )
246  break;
247  }
248  }
249 
250  SelectDefault();
251  return true;
252 }
253 
254 
256 {
257  m_fp_sel_ctrl->SetSelection( POS_DEFAULT );
258 }
259 
260 
262 {
263  return m_fp_sel_ctrl->Enable( aEnable );
264 }
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.
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()
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)
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:342
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:284
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
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.