KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_symbol_chooser.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 The 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
27#include <pgm_base.h>
28#include <kiface_base.h>
29#include <sch_base_frame.h>
30#include <project_sch.h>
31#include <widgets/lib_tree.h>
37#include <eeschema_settings.h>
39#include <symbol_library.h> // For SYMBOL_LIBRARY_FILTER
40#include <symbol_lib_table.h>
41#include <algorithm>
42#include <wx/button.h>
43#include <wx/clipbrd.h>
44#include <wx/panel.h>
45#include <wx/sizer.h>
46#include <wx/splitter.h>
47#include <wx/timer.h>
48#include <wx/wxhtml.h>
49#include <wx/log.h>
50
51
55
57 const SYMBOL_LIBRARY_FILTER* aFilter,
58 std::vector<PICKED_SYMBOL>& aHistoryList,
59 std::vector<PICKED_SYMBOL>& aAlreadyPlaced,
60 bool aAllowFieldEdits, bool aShowFootprints, bool& aCancelled,
61 std::function<void()> aAcceptHandler,
62 std::function<void()> aEscapeHandler ) :
63 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ),
64 m_symbol_preview( nullptr ),
65 m_hsplitter( nullptr ),
66 m_vsplitter( nullptr ),
67 m_fp_sel_ctrl( nullptr ),
68 m_fp_preview( nullptr ),
69 m_tree( nullptr ),
70 m_details( nullptr ),
71 m_acceptHandler( std::move( aAcceptHandler ) ),
72 m_escapeHandler( std::move( aEscapeHandler ) ),
73 m_showPower( false ),
74 m_allow_field_edits( aAllowFieldEdits ),
75 m_show_footprints( aShowFootprints )
76{
77 m_frame = aFrame;
78
82
83 // Make sure settings are loaded before we start running multi-threaded symbol loaders
84 GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
85 GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" );
86
88 SYMBOL_TREE_MODEL_ADAPTER* adapter = static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( m_adapter.get() );
89 bool loaded = false;
90
91 if( aFilter )
92 {
93 const wxArrayString& liblist = aFilter->GetAllowedLibList();
94
95 for( const wxString& nickname : liblist )
96 {
97 if( libs->HasLibrary( nickname, true ) )
98 {
99 loaded = true;
100
101 bool pinned = alg::contains( session.pinned_symbol_libs, nickname )
102 || alg::contains( project.m_PinnedSymbolLibs, nickname );
103
104 SYMBOL_LIB_TABLE_ROW* row = libs->FindRow( nickname );
105
106 if( row && row->GetIsVisible() )
107 adapter->AddLibrary( nickname, pinned );
108 }
109 }
110
111 adapter->AssignIntrinsicRanks();
112
113 if( aFilter->GetFilterPowerSymbols() )
114 {
115 static std::function<bool( LIB_TREE_NODE& )> powerFilter =
116 []( LIB_TREE_NODE& aNode ) -> bool
117 {
119 {
120 LIB_SYMBOL* symbol = PANEL_SYMBOL_CHOOSER::m_frame->GetLibSymbol(aNode.m_LibId);
121
122 if (symbol && symbol->IsPower())
123 return true;
124
125 }
126
127 return false;
128 };
129
130 adapter->SetFilter( &powerFilter );
131
132 m_showPower = true;
133 m_show_footprints = false;
134 }
135 }
136
137 std::vector<LIB_SYMBOL> history_list_storage;
138 std::vector<LIB_TREE_ITEM*> history_list;
139 std::vector<LIB_SYMBOL> already_placed_storage;
140 std::vector<LIB_TREE_ITEM*> already_placed;
141
142 // Lambda to encapsulate the common logic
143 auto processList =
144 [&]( const std::vector<PICKED_SYMBOL>& inputList,
145 std::vector<LIB_SYMBOL>& storageList,
146 std::vector<LIB_TREE_ITEM*>& resultList )
147 {
148 storageList.reserve( inputList.size() );
149
150 for( const PICKED_SYMBOL& i : inputList )
151 {
152 LIB_SYMBOL* symbol = m_frame->GetLibSymbol( i.LibId );
153
154 if( symbol )
155 {
156 storageList.emplace_back( *symbol );
157
158 for( const auto& [fieldType, fieldValue] : i.Fields )
159 {
160 SCH_FIELD* field = storageList.back().GetField( fieldType );
161
162 if( field )
163 field->SetText( fieldValue );
164 }
165
166 resultList.push_back( &storageList.back() );
167 }
168 }
169 };
170
171 // Sort the already placed list since it is potentially from multiple sessions,
172 // but not the most recent list since we want this listed by most recent usage.
173 std::sort( aAlreadyPlaced.begin(), aAlreadyPlaced.end(),
174 []( PICKED_SYMBOL const& a, PICKED_SYMBOL const& b )
175 {
176 return a.LibId.GetLibItemName() < b.LibId.GetLibItemName();
177 } );
178
179 processList( aHistoryList, history_list_storage, history_list );
180 processList( aAlreadyPlaced, already_placed_storage, already_placed );
181
182 adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString,
183 history_list, false, true )
184 .m_IsRecentlyUsedGroup = true;
185
186 if( !aHistoryList.empty() )
187 adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
188
189 adapter->DoAddLibrary( wxT( "-- " ) + _( "Already Placed" ) + wxT( " --" ), wxEmptyString,
190 already_placed, false, true )
192
193 const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
194
195 if( !loaded )
196 {
197 if( !adapter->AddLibraries( libNicknames, m_frame ) )
198 {
199 // loading cancelled by user
200 aCancelled = true;
201 }
202 }
203
204 // -------------------------------------------------------------------------------------
205 // Construct the actual panel
206 //
207
208 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
209
210 // Use a slightly different layout, with a details pane spanning the entire window,
211 // if we're not showing footprints.
213 {
214 m_hsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
215 wxSP_LIVE_UPDATE | wxSP_NOBORDER | wxSP_3DSASH );
216
217 //Avoid the splitter window being assigned as the Parent to additional windows
218 m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
219
220 sizer->Add( m_hsplitter, 1, wxEXPAND, 5 );
221 }
222 else
223 {
224 m_vsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
225 wxSP_LIVE_UPDATE | wxSP_NOBORDER | wxSP_3DSASH );
226
227 m_hsplitter = new wxSplitterWindow( m_vsplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
228 wxSP_LIVE_UPDATE | wxSP_NOBORDER | wxSP_3DSASH );
229
230 // Avoid the splitter window being assigned as the parent to additional windows.
231 m_vsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
232 m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
233
234 wxPanel* detailsPanel = new wxPanel( m_vsplitter );
235 wxBoxSizer* detailsSizer = new wxBoxSizer( wxVERTICAL );
236 detailsPanel->SetSizer( detailsSizer );
237
238 m_details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize );
239 detailsSizer->Add( m_details, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
240 detailsPanel->Layout();
241 detailsSizer->Fit( detailsPanel );
242
243 m_vsplitter->SetSashGravity( 0.5 );
244 m_vsplitter->SetMinimumPaneSize( 20 );
245 m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel );
246
247 sizer->Add( m_vsplitter, 1, wxEXPAND | wxBOTTOM, 5 );
248 }
249
250 wxPanel* treePanel = new wxPanel( m_hsplitter );
251 wxBoxSizer* treeSizer = new wxBoxSizer( wxVERTICAL );
252 treePanel->SetSizer( treeSizer );
253
254 m_tree = new LIB_TREE( treePanel, m_showPower ? wxT( "power" ) : wxT( "symbols" ),
256
257 treeSizer->Add( m_tree, 1, wxALL | wxEXPAND, 5 );
258 treePanel->Layout();
259 treeSizer->Fit( treePanel );
260
261 m_adapter->FinishTreeInitialization();
262
263 if( m_showPower )
265 else
267
268 m_hsplitter->SetSashGravity( 0.8 );
269 m_hsplitter->SetMinimumPaneSize( 20 );
270 m_hsplitter->SplitVertically( treePanel, constructRightPanel( m_hsplitter ) );
271
272 m_dbl_click_timer = new wxTimer( this );
273 m_open_libs_timer = new wxTimer( this );
274
275 SetSizer( sizer );
276
277 Layout();
278
279 Bind( wxEVT_TIMER, &PANEL_SYMBOL_CHOOSER::onCloseTimer, this, m_dbl_click_timer->GetId() );
280 Bind( wxEVT_TIMER, &PANEL_SYMBOL_CHOOSER::onOpenLibsTimer, this, m_open_libs_timer->GetId() );
281 Bind( EVT_LIBITEM_SELECTED, &PANEL_SYMBOL_CHOOSER::onSymbolSelected, this );
282 Bind( EVT_LIBITEM_CHOSEN, &PANEL_SYMBOL_CHOOSER::onSymbolChosen, this );
283 aFrame->Bind( wxEVT_MENU_OPEN, &PANEL_SYMBOL_CHOOSER::onMenuOpen, this );
284 aFrame->Bind( wxEVT_MENU_CLOSE, &PANEL_SYMBOL_CHOOSER::onMenuClose, this );
285
286 if( m_fp_sel_ctrl )
287 {
288 m_fp_sel_ctrl->Bind( EVT_FOOTPRINT_SELECTED, &PANEL_SYMBOL_CHOOSER::onFootprintSelected,
289 this );
290 }
291
292 if( m_details )
293 {
294 m_details->Connect( wxEVT_CHAR_HOOK,
295 wxKeyEventHandler( PANEL_SYMBOL_CHOOSER::OnDetailsCharHook ),
296 nullptr, this );
297 }
298
299 // Open the user's previously opened libraries on timer expiration.
300 // This is done on a timer because we need a gross hack to keep GTK from garbling the
301 // display. Must be longer than the search debounce timer.
302 m_open_libs_timer->StartOnce( 300 );
303}
304
305
307{
308 m_frame->Unbind( wxEVT_MENU_OPEN, &PANEL_SYMBOL_CHOOSER::onMenuOpen, this );
309 m_frame->Unbind( wxEVT_MENU_CLOSE, &PANEL_SYMBOL_CHOOSER::onMenuClose, this );
310 Unbind( wxEVT_TIMER, &PANEL_SYMBOL_CHOOSER::onCloseTimer, this );
311 Unbind( EVT_LIBITEM_SELECTED, &PANEL_SYMBOL_CHOOSER::onSymbolSelected, this );
312 Unbind( EVT_LIBITEM_CHOSEN, &PANEL_SYMBOL_CHOOSER::onSymbolChosen, this );
313
314 // Stop the timer during destruction early to avoid potential race conditions (that do happen)
315 m_dbl_click_timer->Stop();
316 m_open_libs_timer->Stop();
317 delete m_dbl_click_timer;
318 delete m_open_libs_timer;
319
320 if( m_showPower )
322 else
324
325 if( m_fp_sel_ctrl )
326 {
327 m_fp_sel_ctrl->Unbind( EVT_FOOTPRINT_SELECTED, &PANEL_SYMBOL_CHOOSER::onFootprintSelected,
328 this );
329 }
330
331 if( m_details )
332 {
333 m_details->Disconnect( wxEVT_CHAR_HOOK,
334 wxKeyEventHandler( PANEL_SYMBOL_CHOOSER::OnDetailsCharHook ),
335 nullptr, this );
336 }
337
338 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
339 {
340 // Save any changes to column widths, etc.
341 m_adapter->SaveSettings();
342
343 cfg->m_SymChooserPanel.width = GetParent()->GetSize().x;
344 cfg->m_SymChooserPanel.height = GetParent()->GetSize().y;
345
346 cfg->m_SymChooserPanel.sash_pos_h = m_hsplitter->GetSashPosition();
347
348 if( m_vsplitter )
349 cfg->m_SymChooserPanel.sash_pos_v = m_vsplitter->GetSashPosition();
350
351 cfg->m_SymChooserPanel.sort_mode = m_tree->GetSortMode();
352 }
353
354 m_frame = nullptr;
355}
356
357
358void PANEL_SYMBOL_CHOOSER::onMenuOpen( wxMenuEvent& aEvent )
359{
360 m_tree->BlockPreview( true );
361 aEvent.Skip();
362}
363
364
365void PANEL_SYMBOL_CHOOSER::onMenuClose( wxMenuEvent& aEvent )
366{
367 m_tree->BlockPreview( false );
368 aEvent.Skip();
369}
370
371
372void PANEL_SYMBOL_CHOOSER::OnChar( wxKeyEvent& aEvent )
373{
374 if( aEvent.GetKeyCode() == WXK_ESCAPE )
375 {
376 wxObject* eventSource = aEvent.GetEventObject();
377
378 if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( eventSource ) )
379 {
380 // First escape cancels search string value
381 if( textCtrl->GetValue() == m_tree->GetSearchString()
382 && !m_tree->GetSearchString().IsEmpty() )
383 {
384 m_tree->SetSearchString( wxEmptyString );
385 return;
386 }
387 }
388
390 }
391 else
392 {
393 aEvent.Skip();
394 }
395}
396
397
398wxPanel* PANEL_SYMBOL_CHOOSER::constructRightPanel( wxWindow* aParent )
399{
401
402 if( m_frame->GetCanvas() )
403 backend = m_frame->GetCanvas()->GetBackend();
404 else if( COMMON_SETTINGS* cfg = Pgm().GetCommonSettings() )
405 backend = static_cast<EDA_DRAW_PANEL_GAL::GAL_TYPE>( cfg->m_Graphics.canvas_type );
406
407 wxPanel* panel = new wxPanel( aParent );
408 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
409
410 m_symbol_preview = new SYMBOL_PREVIEW_WIDGET( panel, &m_frame->Kiway(), true, backend );
411 m_symbol_preview->SetLayoutDirection( wxLayout_LeftToRight );
412
414 {
416
417 sizer->Add( m_symbol_preview, 11, wxEXPAND | wxALL, 5 );
418
419 if ( fp_list )
420 {
422 m_fp_sel_ctrl = new FOOTPRINT_SELECT_WIDGET( m_frame, panel, fp_list, true );
423
426 }
427
428 if( m_fp_sel_ctrl )
429 sizer->Add( m_fp_sel_ctrl, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
430
431 if( m_fp_preview )
432 sizer->Add( m_fp_preview, 10, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
433 }
434 else
435 {
436 sizer->Add( m_symbol_preview, 1, wxEXPAND | wxALL, 5 );
437 }
438
439 panel->SetSizer( sizer );
440 panel->Layout();
441 sizer->Fit( panel );
442
443 return panel;
444}
445
446
448{
449 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
450 {
451 auto horizPixelsFromDU =
452 [&]( int x ) -> int
453 {
454 wxSize sz( x, 0 );
455 return GetParent()->ConvertDialogToPixels( sz ).x;
456 };
457
458 EESCHEMA_SETTINGS::PANEL_SYM_CHOOSER& panelCfg = cfg->m_SymChooserPanel;
459
460 int w = panelCfg.width > 40 ? panelCfg.width : horizPixelsFromDU( 440 );
461 int h = panelCfg.height > 40 ? panelCfg.height : horizPixelsFromDU( 340 );
462
463 GetParent()->SetSize( wxSize( w, h ) );
464 GetParent()->Layout();
465
466 // We specify the width of the right window (m_symbol_view_panel), because specify
467 // the width of the left window does not work as expected when SetSashGravity() is called
468
469 if( panelCfg.sash_pos_h < 0 )
470 panelCfg.sash_pos_h = horizPixelsFromDU( 220 );
471
472 if( panelCfg.sash_pos_v < 0 )
473 panelCfg.sash_pos_v = horizPixelsFromDU( 230 );
474
475 m_hsplitter->SetSashPosition( panelCfg.sash_pos_h );
476
477 if( m_vsplitter )
478 m_vsplitter->SetSashPosition( panelCfg.sash_pos_v );
479
480 m_adapter->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) panelCfg.sort_mode );
481 }
482
484 {
485 // This hides the GAL panel and shows the status label
486 m_fp_preview->SetStatusText( wxEmptyString );
487 }
488
489 if( m_fp_sel_ctrl )
491}
492
493
495{
496 if( m_details && e.GetKeyCode() == 'C' && e.ControlDown() &&
497 !e.AltDown() && !e.ShiftDown() && !e.MetaDown() )
498 {
499 wxString txt = m_details->SelectionToText();
500 wxLogNull doNotLog; // disable logging of failed clipboard actions
501
502 if( wxTheClipboard->Open() )
503 {
504 wxTheClipboard->SetData( new wxTextDataObject( txt ) );
505 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
506 wxTheClipboard->Close();
507 }
508 }
509 else
510 {
511 e.Skip();
512 }
513}
514
515
517{
518 m_adapter->SetPreselectNode( aPreselect, 0 );
519}
520
521
523{
524 return m_tree->GetSelectedLibId( aUnit );
525}
526
527
529{
530 m_symbol_preview->GetCanvas()->SetEvtHandlerEnabled( false );
532
533 if( m_fp_preview )
534 {
535 m_fp_preview->GetPreviewPanel()->GetCanvas()->SetEvtHandlerEnabled( false );
537 }
538}
539
540
541void PANEL_SYMBOL_CHOOSER::onCloseTimer( wxTimerEvent& aEvent )
542{
543 // Hack because of eaten MouseUp event. See PANEL_SYMBOL_CHOOSER::onSymbolChosen
544 // for the beginning of this spaghetti noodle.
545
546 wxMouseState state = wxGetMouseState();
547
548 if( state.LeftIsDown() )
549 {
550 // Mouse hasn't been raised yet, so fire the timer again. Otherwise the
551 // purpose of this timer is defeated.
553 }
554 else
555 {
557 }
558}
559
560
561void PANEL_SYMBOL_CHOOSER::onOpenLibsTimer( wxTimerEvent& aEvent )
562{
563 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
564 m_adapter->OpenLibs( cfg->m_LibTree.open_libs );
565}
566
567
569{
571 return;
572
573 LIB_SYMBOL* symbol = nullptr;
574
575 try
576 {
577 symbol = PROJECT_SCH::SchSymbolLibTable( &m_frame->Prj() )->LoadSymbol( aLibId );
578 }
579 catch( const IO_ERROR& ioe )
580 {
581 wxLogError( _( "Error loading symbol %s from library '%s'." ) + wxS( "\n%s" ),
582 aLibId.GetLibItemName().wx_str(),
583 aLibId.GetLibNickname().wx_str(),
584 ioe.What() );
585 }
586
587 if( !symbol )
588 return;
589
590 SCH_FIELD* fp_field = symbol->GetField( FIELD_T::FOOTPRINT );
591 wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
592
593 showFootprint( fp_name );
594}
595
596
597void PANEL_SYMBOL_CHOOSER::showFootprint( wxString const& aFootprint )
598{
600 return;
601
602 if( aFootprint == wxEmptyString )
603 {
604 m_fp_preview->SetStatusText( _( "No footprint specified" ) );
605 }
606 else
607 {
608 LIB_ID lib_id;
609
610 if( lib_id.Parse( aFootprint ) == -1 && lib_id.IsValid() )
611 {
614 }
615 else
616 {
617 m_fp_preview->SetStatusText( _( "Invalid footprint specified" ) );
618 }
619 }
620}
621
622
624{
625 if( !m_fp_sel_ctrl )
626 return;
627
629
630 LIB_SYMBOL* symbol = nullptr;
631
632 if( aLibId.IsValid() )
633 {
634 try
635 {
636 symbol = PROJECT_SCH::SchSymbolLibTable( &m_frame->Prj() )->LoadSymbol( aLibId );
637 }
638 catch( const IO_ERROR& ioe )
639 {
640 wxLogError( _( "Error loading symbol %s from library '%s'." ) + wxS( "\n%s" ),
641 aLibId.GetLibItemName().wx_str(),
642 aLibId.GetLibNickname().wx_str(),
643 ioe.What() );
644 }
645 }
646
647 if( symbol != nullptr )
648 {
649 int pinCount = symbol->GetPins( 0 /* all units */, 1 /* single bodyStyle */ ).size();
650 SCH_FIELD* fp_field = symbol->GetField( FIELD_T::FOOTPRINT );
651 wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
652
653 m_fp_sel_ctrl->FilterByPinCount( pinCount );
658 }
659 else
660 {
662 m_fp_sel_ctrl->Disable();
663 }
664}
665
666
667void PANEL_SYMBOL_CHOOSER::onFootprintSelected( wxCommandEvent& aEvent )
668{
669 m_fp_override = aEvent.GetString();
670
671 std::erase_if( m_field_edits, []( std::pair<FIELD_T, wxString> const& i )
672 {
673 return i.first == FIELD_T::FOOTPRINT;
674 } );
675
676 m_field_edits.emplace_back( std::make_pair( FIELD_T::FOOTPRINT, m_fp_override ) );
677
679}
680
681
682void PANEL_SYMBOL_CHOOSER::onSymbolSelected( wxCommandEvent& aEvent )
683{
685
686 if( node && node->m_LibId.IsValid() )
687 {
689
690 if( !node->m_Footprint.IsEmpty() )
691 showFootprint( node->m_Footprint );
692 else
693 showFootprintFor( node->m_LibId );
694
696 }
697 else
698 {
699 m_symbol_preview->SetStatusText( _( "No symbol selected" ) );
700
702 m_fp_preview->SetStatusText( wxEmptyString );
703
705 }
706}
707
708
709void PANEL_SYMBOL_CHOOSER::onSymbolChosen( wxCommandEvent& aEvent )
710{
712 {
713 // Got a selection. We can't just end the modal dialog here, because wx leaks some events
714 // back to the parent window (in particular, the MouseUp following a double click).
715 //
716 // NOW, here's where it gets really fun. wxTreeListCtrl eats MouseUp. This isn't really
717 // feasible to bypass without a fully custom wxDataViewCtrl implementation, and even then
718 // might not be fully possible (docs are vague). To get around this, we use a one-shot
719 // timer to schedule the dialog close.
720 //
721 // See PANEL_SYMBOL_CHOOSER::onCloseTimer for the other end of this spaghetti noodle.
723 }
724}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
GAL_TYPE GetBackend() const
Return the type of backend currently used by GAL canvas.
void StopDrawing()
Prevent the GAL canvas from further drawing until it is recreated or StartDrawing() is called.
@ GAL_TYPE_OPENGL
OpenGL implementation.
Holds a list of FOOTPRINT_INFO objects, along with a list of IO_ERRORs or PARSE_ERRORs that were thro...
static FOOTPRINT_LIST * GetInstance(KIWAY &aKiway)
Factory function to return a FOOTPRINT_LIST via Kiway.
virtual EDA_DRAW_PANEL_GAL * GetCanvas()=0
Get the GAL canvas.
FOOTPRINT_PREVIEW_PANEL_BASE * GetPreviewPanel()
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.
virtual bool Enable(bool aEnable=true) override
Enable or disable the control for input.
void FilterByFootprintFilters(const wxArrayString &aFilters, bool aZeroFilters)
Filter by footprint filter list.
void SetDefaultFootprint(const wxString &aFp)
Set the default footprint for a part.
void FilterByPinCount(int aPinCount)
Filter by pin count.
bool UpdateList()
Update the contents of the list to match the filters.
void ClearFilters()
Clear all filters.
void Load(KIWAY &aKiway, PROJECT &aProject)
Start loading.
Add dark theme support to wxHtmlWindow.
Definition: html_window.h:35
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
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:55
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:52
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Define a library symbol object.
Definition: lib_symbol.h:85
std::vector< SCH_PIN * > GetPins(int aUnit, int aBodyStyle) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:799
bool IsPower() const override
Definition: lib_symbol.cpp:469
SCH_FIELD * GetField(const wxString &aFieldName)
Find a field within this symbol matching aFieldName; return nullptr if not found.
wxArrayString GetFPFilters() const
Definition: lib_symbol.h:218
bool GetIsVisible() const
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
void SetPreselectNode(const LIB_ID &aLibId, int aUnit)
Set the symbol name to be selected if there are no search results.
void AssignIntrinsicRanks()
Sort the tree and assign ranks after adding libraries.
LIB_TREE_NODE_LIBRARY & DoAddLibrary(const wxString &aNodeName, const wxString &aDesc, const std::vector< LIB_TREE_ITEM * > &aItemList, bool pinned, bool presorted)
Add the given list of symbols by alias.
void SetFilter(std::function< bool(LIB_TREE_NODE &aNode)> *aFilter)
Set the filter.
Model class in the component selector Model-View-Adapter (mediated MVC) architecture.
bool m_IsAlreadyPlacedGroup
bool m_IsRecentlyUsedGroup
wxString m_Footprint
Widget displaying a tree of symbols with optional search text control and description panel.
Definition: lib_tree.h:49
LIB_TREE_NODE * GetCurrentTreeNode() const
Retrieve the tree node for the first selected item.
Definition: lib_tree.cpp:351
LIB_TREE_MODEL_ADAPTER::SORT_MODE GetSortMode() const
Definition: lib_tree.h:155
wxString GetSearchString() const
Definition: lib_tree.cpp:419
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:314
@ ALL_WIDGETS
Definition: lib_tree.h:58
void SetSearchString(const wxString &aSearchString)
Save/restore search string.
Definition: lib_tree.cpp:413
void BlockPreview(bool aBlock)
Definition: lib_tree.h:178
SYMBOL_PREVIEW_WIDGET * m_symbol_preview
PANEL_SYMBOL_CHOOSER(SCH_BASE_FRAME *aFrame, wxWindow *aParent, const SYMBOL_LIBRARY_FILTER *aFilter, std::vector< PICKED_SYMBOL > &aHistoryList, std::vector< PICKED_SYMBOL > &aAlreadyPlaced, bool aAllowFieldEdits, bool aShowFootprints, bool &aCancelled, std::function< void()> aAcceptHandler, std::function< void()> aEscapeHandler)
Create dialog to choose symbol.
void onSymbolSelected(wxCommandEvent &aEvent)
void showFootprintFor(const LIB_ID &aLibId)
Look up the footprint for a given symbol specified in the LIB_ID and display it.
void onMenuClose(wxMenuEvent &aEvent)
wxSplitterWindow * m_hsplitter
FOOTPRINT_SELECT_WIDGET * m_fp_sel_ctrl
std::function< void()> m_escapeHandler
void OnDetailsCharHook(wxKeyEvent &aEvt)
static wxString g_symbolSearchString
void onMenuOpen(wxMenuEvent &aEvent)
Handle parent frame menu events to block tree preview.
std::vector< std::pair< FIELD_T, wxString > > m_field_edits
void onCloseTimer(wxTimerEvent &aEvent)
wxSplitterWindow * m_vsplitter
static SCH_BASE_FRAME * m_frame
void showFootprint(const wxString &aFootprint)
Display the given footprint by name.
void populateFootprintSelector(const LIB_ID &aLibId)
Populate the footprint selector for a given alias.
void onOpenLibsTimer(wxTimerEvent &aEvent)
void onFootprintSelected(wxCommandEvent &aEvent)
static wxString g_powerSearchString
void OnChar(wxKeyEvent &aEvent)
void SetPreselect(const LIB_ID &aPreselect)
std::function< void()> m_acceptHandler
static constexpr int DBLCLICK_DELAY
FOOTPRINT_PREVIEW_WIDGET * m_fp_preview
wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > m_adapter
LIB_ID GetSelectedLibId(int *aUnit=nullptr) const
To be called after this dialog returns from ShowModal().
void onSymbolChosen(wxCommandEvent &aEvent)
Handle the selection of an item.
wxPanel * constructRightPanel(wxWindow *aParent)
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:565
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:68
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:204
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
LIB_SYMBOL * GetLibSymbol(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: sch_field.cpp:301
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1089
Helper object to filter a list of libraries.
const wxArrayString & GetAllowedLibList() const
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_IO object i...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
EDA_DRAW_PANEL_GAL * GetCanvas() const
void SetStatusText(const wxString &aText)
Set the contents of the status label and display it.
void DisplaySymbol(const LIB_ID &aSymbolID, int aUnit, int aBodyStyle=0)
Set the currently displayed symbol.
bool AddLibraries(const std::vector< wxString > &aNicknames, SCH_BASE_FRAME *aFrame)
Add all the libraries in a SYMBOL_LIB_TABLE to the model.
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(SCH_BASE_FRAME *aParent, LIB_TABLE *aLibs)
Factory function: create a model adapter in a reference-counting container.
void AddLibrary(wxString const &aLibNickname, bool pinned)
EDA_UNITS GetUserUnits() const
wxString wx_str() const
Definition: utf8.cpp:45
#define _(s)
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
STL namespace.
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:902
see class PGM_BASE
std::vector< wxString > pinned_symbol_libs
Definition for symbol library class.