KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_chooser_frame.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) 2023 CERN
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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <wx/button.h>
22#include <wx/checkbox.h>
23#include <wx/splitter.h>
24
25#include <bitmaps.h>
26#include <pgm_base.h>
27#include <kiface_base.h>
28#include <kiway.h>
29#include <kiway_mail.h>
30#include <board.h>
31#include <footprint.h>
32#include <kiplatform/ui.h>
33#include <lset.h>
38#include <tool/tool_manager.h>
40#include <tool/common_tools.h>
41#include <tool/zoom_tool.h>
43#include <tools/pcb_actions.h>
47#include "wx/display.h"
50#include <project_pcb.h>
54
55
56static wxArrayString s_FootprintHistoryList;
57static unsigned s_FootprintHistoryMaxCount = 8;
58
59static void AddFootprintToHistory( const wxString& aName )
60{
61 // Remove duplicates
62 for( int ii = (int) s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii )
63 {
64 if( s_FootprintHistoryList[ ii ] == aName )
65 s_FootprintHistoryList.RemoveAt( (size_t) ii );
66 }
67
68 // Add the new name at the beginning of the history list
69 s_FootprintHistoryList.Insert( aName, 0 );
70
71 // Remove extra names
73 s_FootprintHistoryList.RemoveAt( s_FootprintHistoryList.GetCount() - 1 );
74}
75
76
77BEGIN_EVENT_TABLE( FOOTPRINT_CHOOSER_FRAME, PCB_BASE_FRAME )
79 EVT_BUTTON( wxID_OK, FOOTPRINT_CHOOSER_FRAME::OnOK )
80 EVT_BUTTON( wxID_CANCEL, FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser )
82END_EVENT_TABLE()
83
84
85#define PARENT_STYLE ( wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN \
86 | wxWANTS_CHARS | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT )
87#define MODAL_STYLE ( wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN \
88 | wxWANTS_CHARS | wxFRAME_NO_TASKBAR )
89
90
92 PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_CHOOSER, _( "Footprint Chooser" ),
93 wxDefaultPosition, wxDefaultSize, aParent ? PARENT_STYLE : MODAL_STYLE,
95 m_filterByPinCount( nullptr ),
96 m_filterByFPFilters( nullptr ),
100 m_pinCount( 0 ),
101 m_firstPaintEvent( true )
102{
103 SetModal( true );
104
105 m_messagePanel->Hide();
106
107 m_bottomPanel = new wxPanel( this );
108 wxBoxSizer* bottomSizer = new wxBoxSizer( wxVERTICAL );
109 wxBoxSizer* frameSizer = new wxBoxSizer( wxVERTICAL );
110
112 // Filter
113 [this]( LIB_TREE_NODE& aNode ) -> bool
114 {
115 return filterFootprint( aNode );
116 },
117 // Accept handler
118 [this]()
119 {
120 wxCommandEvent dummy;
121 OnOK( dummy );
122 },
123 // Escape handler
124 [this]()
125 {
127 } );
128
129 frameSizer->Add( m_chooserPanel, 1, wxEXPAND );
130
131 SetCanvas( m_chooserPanel->GetViewerPanel()->GetPreviewPanel()->GetCanvas() );
132 SetBoard( m_chooserPanel->GetViewerPanel()->GetPreviewPanel()->GetBoard() );
133
134 // This board will only be used to hold a footprint for viewing
136
137 build3DCanvas(); // must be called after creating m_chooserPanel
139
140 // buttonsSizer contains the BITMAP buttons
141 wxBoxSizer* buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
142
143 buttonsSizer->Add( 0, 0, 1, 0, 5 ); // Add spacer to right-align buttons
144
145
146 m_toggleDescription = new BITMAP_BUTTON( m_bottomPanel, wxID_ANY, wxNullBitmap );
147 m_toggleDescription->SetIsRadioButton();
149 m_toggleDescription->SetToolTip( _( "Show/hide description panel" ) );
151 buttonsSizer->Add( m_toggleDescription, 0, wxRIGHT | wxLEFT | wxALIGN_CENTER_VERTICAL, 1 );
152
153 BITMAP_BUTTON* separator = new BITMAP_BUTTON( m_bottomPanel, wxID_ANY, wxNullBitmap );
154 separator->SetIsSeparator();
155 buttonsSizer->Add( separator, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
156
157 m_grButton3DView = new BITMAP_BUTTON( m_bottomPanel, wxID_ANY, wxNullBitmap );
158 m_grButton3DView->SetIsRadioButton();
160 m_grButton3DView->SetToolTip( _( "Show/hide 3D view panel" ) );
162 buttonsSizer->Add( m_grButton3DView, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
163
164 m_grButtonFpView = new BITMAP_BUTTON( m_bottomPanel, wxID_ANY, wxNullBitmap );
165 m_grButtonFpView->SetIsRadioButton();
167 m_grButtonFpView->SetToolTip( _( "Show/hide footprint view panel" ) );
169 buttonsSizer->Add( m_grButtonFpView, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
170
171 separator = new BITMAP_BUTTON( m_bottomPanel, wxID_ANY, wxNullBitmap );
172 separator->SetIsSeparator();
173 buttonsSizer->Add( separator, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
174
175 m_show3DViewer = new wxCheckBox( m_bottomPanel, wxID_ANY, _( "Show 3D viewer in own window" ) );
176 buttonsSizer->Add( m_show3DViewer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 3 );
177
178 wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
179 wxButton* okButton = new wxButton( m_bottomPanel, wxID_OK );
180 wxButton* cancelButton = new wxButton( m_bottomPanel, wxID_CANCEL );
181
182 sdbSizer->AddButton( okButton );
183 sdbSizer->AddButton( cancelButton );
184 sdbSizer->Realize();
185
186 buttonsSizer->Add( 20, 0, 0, 0, 5 ); // Add spacer
187 buttonsSizer->Add( sdbSizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
188 bottomSizer->Add( buttonsSizer, 0, wxEXPAND, 5 );
189
190 m_bottomPanel->SetSizer( bottomSizer );
191 frameSizer->Add( m_bottomPanel, 0, wxEXPAND );
192
193 SetSizer( frameSizer );
194
195 SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ),
196 m_chooserPanel->GetItemCount() ) );
197
198 Layout();
199 m_chooserPanel->FinishSetup();
200
201 Bind( wxEVT_CHAR_HOOK, &PANEL_FOOTPRINT_CHOOSER::OnChar, m_chooserPanel );
202
203 if( !m_showDescription )
204 {
205 m_chooserPanel->GetVerticalSpliter()->SetMinimumPaneSize( 0 );
206 m_chooserPanel->GetVerticalSpliter()->GetWindow2()->Hide();
207 m_chooserPanel->GetVerticalSpliter()->SetSashInvisible();
208
210 }
211
212 // Create the manager and dispatcher & route draw panel events to the dispatcher
214 m_toolManager->SetEnvironment( GetBoard(), GetCanvas()->GetView(),
215 GetCanvas()->GetViewControls(), GetViewerSettingsBase(), this );
216 m_actions = new PCB_ACTIONS();
219
220 m_toolManager->RegisterTool( new COMMON_TOOLS ); // for std context menus (zoom & grid)
221 m_toolManager->RegisterTool( new PCB_PICKER_TOOL ); // for setting grid origin
222 m_toolManager->RegisterTool( new ZOOM_TOOL );
223 m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
225
226 m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
227 m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetIsDefaultTool( true );
228
229 m_toolManager->InitTools();
230
233
234 // clang-format off
235 // Connect Events
236 m_toggleDescription->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
237 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::toggleBottomSplit ),
238 nullptr, this );
239
240 m_grButton3DView->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
241 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ),
242 nullptr, this );
243
244 m_grButtonFpView->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
245 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpViewReq ),
246 nullptr, this );
247
248 m_show3DViewer->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED ,
250 nullptr, this );
251
252 Connect( FP_SELECTION_EVENT, // custom event fired by a PANEL_FOOTPRINT_CHOOSER
253 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpChanged ), nullptr, this );
254 // clang-format on
255
256 // Needed on Linux to fix the position of widgets in bottomPanel
257 PostSizeEvent();
258}
259
260
262{
263 Unbind( wxEVT_CHAR_HOOK, &PANEL_FOOTPRINT_CHOOSER::OnChar, m_chooserPanel );
264
265 // Shutdown all running tools
266 if( m_toolManager )
267 m_toolManager->ShutdownAllTools();
268
269 // Idempotent; normally already ran from OnOK() or doCloseWindow() before DismissModal.
271
272 // Disconnect board, which is owned by FOOTPRINT_PREVIEW_PANEL.
273 m_pcb = nullptr;
274
275 // The 3D canvas holds references to m_boardAdapter and m_trackBallCamera, and wx would not
276 // destroy this grandchild window until well after those members are gone
277 delete m_preview3DCanvas;
278 m_preview3DCanvas = nullptr;
279
280 // clang-format off
281 // Disconnect Events
282 m_toggleDescription->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
283 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::toggleBottomSplit ),
284 nullptr, this );
285
286 m_grButton3DView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
287 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ),
288 nullptr, this );
289 m_grButtonFpView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
290 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpViewReq ),
291 nullptr, this );
292
293 m_show3DViewer->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED ,
295 nullptr, this );
296
297 Disconnect( FP_SELECTION_EVENT,
298 wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpChanged ), nullptr, this );
299
300 // clang-format on
301
302 if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
303 {
305 cfg->m_FootprintChooser.use_fp_filters = m_filterByFPFilters->GetValue();
306
308 cfg->m_FootprintChooser.filter_on_pin_count = m_filterByPinCount->GetValue();
309 }
310}
311
312
314{
315 if( m_quiesced )
316 return;
317
318 m_quiesced = true;
319
320 // Running this teardown before DismissModal() ensures the preview cannot
321 // receive further paint or timer events during KIWAY_PLAYER::ShowModal()'s
322 // post-loop wxSafeYield() while the frame is hidden but not yet destroyed.
323
324 // Work around assertion firing when we try to LockCtx on a hidden 3D canvas
326 {
327 m_preview3DCanvas->Show();
328
329 wxCloseEvent dummy;
330 m_preview3DCanvas->OnCloseWindow( dummy );
331 m_preview3DCanvas->SetEvtHandlerEnabled( false );
332 }
333
334 if( EDA_3D_VIEWER_FRAME* our3DViewer = GetOur3DViewerFrame() )
335 our3DViewer->Close( true );
336
337 if( m_chooserPanel )
338 {
339 FOOTPRINT_PREVIEW_WIDGET* viewerPanel = m_chooserPanel->GetViewerPanel();
340
341 if( viewerPanel )
342 {
343 if( FOOTPRINT_PREVIEW_PANEL* previewPanel =
344 static_cast<FOOTPRINT_PREVIEW_PANEL*>( viewerPanel->GetPreviewPanel() ) )
345 {
346 previewPanel->GetCanvas()->StopDrawing();
347 previewPanel->GetCanvas()->SetEvtHandlerEnabled( false );
348 previewPanel->ClearViewAndData();
349 }
350 }
351 }
352}
353
354
356{
357 if( aEvent.IsChecked() )
358 {
359 if( m_grButton3DView->IsChecked() )
360 Show3DViewerFrame(); // show external 3D viewer
361 }
362 else if( EDA_3D_VIEWER_FRAME* viewer3D = GetOur3DViewerFrame() )
363 {
364 // Close the external 3D viewer frame, if it is still enabled
365 viewer3D->Close( true );
366 }
367
369}
370
371
373{
374 bool do_reload_board = true; // reload board flag
375
376 // At EDA_3D_VIEWER_FRAME creation, the current board is loaded, so disable loading
377 // the current board if the 3D frame is not yet created
378 if( GetOur3DViewerFrame() == nullptr )
379 do_reload_board = false;
380
382
383 // A stronger version of Raise() which promotes the window to its parent's level.
384 KIPLATFORM::UI::ReparentModal( draw3DFrame );
385
386 // And load or update the current board (if needed)
387 if( do_reload_board )
388 Update3DView( true, true );
389}
390
391
392void FOOTPRINT_CHOOSER_FRAME::Update3DView( bool aMarkDirty, bool aRefresh, const wxString* aTitle )
393{
394 LIB_ID fpID = m_chooserPanel->GetSelectedLibId();
395 wxString footprintName;
396
397 if( fpID.IsValid() )
398 footprintName << fpID.Format();
399
400 wxString title = _( "3D Viewer" ) + wxT( " \u2014 " ) + footprintName;
401 PCB_BASE_FRAME::Update3DView( aMarkDirty, aRefresh, &title );
402}
403
404
406{
408 return m_filterByPinCount->GetValue();
409
410 if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
411 return cfg->m_FootprintChooser.filter_on_pin_count;
412
413 return false;
414}
415
416
418{
420 return m_filterByFPFilters->GetValue();
421
422 if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
423 return cfg->m_FootprintChooser.use_fp_filters;
424
425 return false;
426}
427
428
430{
431 if( aNode.m_Type == LIB_TREE_NODE::TYPE::LIBRARY )
432 {
433 // Normally lib nodes get scored by the max of their children's scores. However, if a
434 // lib node *has* no children then the scorer will call the filter on the lib node itself,
435 // and we just want to return true if we're not filtering at all.
436 return !filterByPinCount() && !filterByFPFilters();
437 }
438
439 auto patternMatch =
440 []( LIB_ID& id, std::vector<std::unique_ptr<EDA_PATTERN_MATCH>>& filters ) -> bool
441 {
442 // The matching is case insensitive
443 wxString name;
444
445 for( const std::unique_ptr<EDA_PATTERN_MATCH>& filter : filters )
446 {
447 name.Empty();
448
449 // If the filter contains a ':' then include the library name in the pattern
450 if( filter->GetPattern().Contains( wxS( ":" ) ) )
451 name = id.GetUniStringLibNickname().Lower() + wxS( ":" );
452
453 name += id.GetUniStringLibItemName().Lower();
454
455 if( filter->Find( name ) )
456 return true;
457 }
458
459 return false;
460 };
461
462 if( m_pinCount > 0 && filterByPinCount() )
463 {
464 if( aNode.m_PinCount != m_pinCount )
465 return false;
466 }
467
468 if( !m_fpFilters.empty() && filterByFPFilters() )
469 {
470 if( !patternMatch( aNode.m_LibId, m_fpFilters ) )
471 return false;
472 }
473
474 return true;
475}
476
477
479{
480 // Tear down the preview canvases before DismissModal() so nothing can paint
481 // or timer-fire into them during the post-loop wxSafeYield().
483
484 // Only dismiss a modal frame once, so that the return values set by
485 // the prior DismissModal() are not bashed for ShowModal().
486 if( !IsDismissed() )
487 DismissModal( false );
488
489 // window to be destroyed by the caller of KIWAY_PLAYER::ShowModal()
490}
491
492
494{
495 if( PCBNEW_SETTINGS* pcb_cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg ) )
496 return &pcb_cfg->m_FootprintViewer;
497 else if( CVPCB_SETTINGS* cvpcb_cfg = dynamic_cast<CVPCB_SETTINGS*>( aCfg ) )
498 return &cvpcb_cfg->m_FootprintViewer;
499
500 wxFAIL_MSG( wxT( "FOOTPRINT_CHOOSER not running with PCBNEW_SETTINGS or CVPCB_SETTINGS" ) );
501 return &aCfg->m_Window; // non-null fail-safe
502}
503
504
506{
508 return ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME );
509}
510
511
512static wxRect s_dialogRect( 0, 0, 0, 0 );
513
514
516{
517 const std::string& payload = mail.GetPayload();
518
519 switch( mail.Command() )
520 {
522 {
523 wxLogTrace( "FOOTPRINT_CHOOSER", wxS( "MAIL_SYMBOL_NETLIST received: size=%zu" ), payload.size() );
524 wxSizer* filtersSizer = m_chooserPanel->GetFiltersSizer();
525 wxWindow* filtersWindow = filtersSizer->GetContainingWindow();
526 wxString msg;
527
528 m_pinCount = 0;
529 m_fpFilters.clear();
530 bool needRegen = false;
531 /*
532 * Symbol netlist format:
533 * pinNumber pinName <tab> pinNumber pinName...
534 * fpFilter fpFilter...
535 */
536 std::map<wxString, wxString> pinNames;
537 std::vector<std::string> strings = split( payload, "\r" );
538
539 if( strings.size() >= 1 && !strings[0].empty() )
540 {
541 wxArrayString tokens = wxSplit( strings[0], '\t' );
542
543 wxLogTrace( "FOOTPRINT_CHOOSER", wxS( "First line entries=%u" ), (unsigned) tokens.size() );
544
545 for( const wxString& pin : tokens )
546 pinNames[ pin.BeforeFirst( ' ' ) ] = pin.AfterFirst( ' ' );
547
548 m_pinCount = (int) pinNames.size();
549
550 wxString pinList;
551
552 for( const auto& kv : pinNames )
553 {
554 if( !pinList.IsEmpty() )
555 pinList << wxS( "," );
556
557 pinList << kv.first;
558 }
559
560 wxLogTrace( "FOOTPRINT_CHOOSER", wxS( "Parsed pins=%d -> [%s]" ), m_pinCount, pinList );
561 }
562
563 if( strings.size() >= 2 && !strings[1].empty() )
564 {
565 for( const wxString& filter : wxSplit( strings[1], ' ' ) )
566 {
567 m_fpFilters.push_back( std::make_unique<EDA_PATTERN_MATCH_WILDCARD_ANCHORED>() );
568 m_fpFilters.back()->SetPattern( filter.Lower() );
569 }
570 }
571
572 if( !m_fpFilters.empty() )
573 {
574 msg.Printf( _( "Apply footprint filters (%s)" ), strings[1] );
575
577 {
578 m_filterByFPFilters = new wxCheckBox( filtersWindow, wxID_ANY, msg );
579
580 m_filterByFPFilters->Bind( wxEVT_CHECKBOX,
581 [&]( wxCommandEvent& evt )
582 {
583 m_chooserPanel->Regenerate();
584 } );
585
586 if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
587 {
588 m_filterByFPFilters->SetValue( cfg->m_FootprintChooser.use_fp_filters );
589 needRegen = cfg->m_FootprintChooser.use_fp_filters;
590 }
591
592 m_chooserPanel->GetFiltersSizer()->Add( m_filterByFPFilters, 0, wxEXPAND|wxBOTTOM, 4 );
593 }
594
595 m_filterByFPFilters->SetLabel( msg );
596 }
597 else
598 {
600 m_filterByFPFilters->Hide();
601 }
602
603 if( m_pinCount > 0 )
604 {
605 msg.Printf( _( "Filter by pin count (%d)" ), m_pinCount );
606 wxLogTrace( "FOOTPRINT_CHOOSER", wxS( "Pin-count label: %s" ), msg );
607
608 if( !m_filterByPinCount )
609 {
610 m_filterByPinCount = new wxCheckBox( filtersWindow, wxID_ANY, msg );
611
612 m_filterByPinCount->Bind( wxEVT_CHECKBOX,
613 [&]( wxCommandEvent& evt )
614 {
615 m_chooserPanel->Regenerate();
616 } );
617
618 if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
619 {
620 m_filterByPinCount->SetValue( cfg->m_FootprintChooser.filter_on_pin_count );
621 needRegen = needRegen || cfg->m_FootprintChooser.filter_on_pin_count;
622 }
623
624 m_chooserPanel->GetFiltersSizer()->Add( m_filterByPinCount, 0, wxEXPAND|wxBOTTOM, 4 );
625 }
626
627 m_filterByPinCount->SetLabel( msg );
628 }
629 else
630 {
632 m_filterByPinCount->Hide();
633 }
634
635 // Regenerate footprint tree to account for pin number filter and footprint filters being applied in settings.
636 if( needRegen )
637 m_chooserPanel->Regenerate();
638
639 m_chooserPanel->GetViewerPanel()->SetPinFunctions( pinNames );
640 wxLogTrace( "FOOTPRINT_CHOOSER", wxS( "SetPinFunctions called with %zu entries" ), pinNames.size() );
641
642 // Save the wxFormBuilder size of the dialog...
643 if( s_dialogRect.GetSize().x == 0 || s_dialogRect.GetSize().y == 0 )
644 s_dialogRect = wxRect( wxWindow::GetPosition(), wxWindow::GetSize() );
645
646 // ... and then give it a kick to get it to layout the new items
647 GetSizer()->SetSizeHints( this );
648 break;
649 }
650
651 default:
652 break;
653 }
654}
655
656
658{
659 return static_cast<FOOTPRINT_PREVIEW_PANEL*>( m_chooserPanel->GetViewerPanel()->GetPreviewPanel() )->GetCurrentFootprint();
660}
661
662
663bool FOOTPRINT_CHOOSER_FRAME::ShowModal( wxString* aFootprint, wxWindow* aParent )
664{
665 if( aFootprint && !aFootprint->IsEmpty() )
666 {
667 LIB_ID fpid;
668
669 fpid.Parse( *aFootprint, true );
670
671 if( fpid.IsValid() )
672 m_chooserPanel->SetPreselect( fpid );
673 }
674
675 return KIWAY_PLAYER::ShowModal( aFootprint, aParent );
676}
677
678
679void FOOTPRINT_CHOOSER_FRAME::SetPosition( const wxPoint& aNewPosition )
680{
681 PCB_BASE_FRAME::SetPosition( aNewPosition );
682
683 s_dialogRect.SetPosition( aNewPosition );
684}
685
686
688{
689 bool ret;
690
691 // Show or hide the window. If hiding, save current position and size.
692 // If showing, use previous position and size.
693 if( show )
694 {
695#ifndef __WINDOWS__
696 PCB_BASE_FRAME::Raise(); // Needed on OS X and some other window managers (i.e. Unity)
697#endif
698 ret = PCB_BASE_FRAME::Show( show );
699
700 // returns a zeroed-out default wxRect if none existed before.
701 wxRect savedDialogRect = s_dialogRect;
702
703 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
704 {
705 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
706 std::max( wxWindow::GetSize().x, savedDialogRect.GetSize().x ),
707 std::max( wxWindow::GetSize().y, savedDialogRect.GetSize().y ),
708 0 );
709 }
710
711 // Be sure that the dialog appears in a visible area
712 // (the dialog position might have been stored at the time when it was
713 // shown on another display)
714 if( wxDisplay::GetFromWindow( this ) == wxNOT_FOUND )
715 Centre();
716 }
717 else
718 {
719 s_dialogRect = wxRect( wxWindow::GetPosition(), wxWindow::GetSize() );
720 ret = PCB_BASE_FRAME::Show( show );
721 }
722
723 return ret;
724}
725
726
727void FOOTPRINT_CHOOSER_FRAME::OnPaint( wxPaintEvent& aEvent )
728{
730 {
732 KIPLATFORM::UI::ForceFocus( m_chooserPanel->GetFocusTarget() );
733
734 m_firstPaintEvent = false;
735 }
736
737 aEvent.Skip();
738}
739
740
741void FOOTPRINT_CHOOSER_FRAME::OnOK( wxCommandEvent& aEvent )
742{
743 // A queued accept event can still fire during the post-loop wxSafeYield()
744 // after Escape/Cancel already dismissed the frame; don't bash that result.
745 if( IsDismissed() )
746 return;
747
748 LIB_ID fpID = m_chooserPanel->GetSelectedLibId();
749
750 // Tear down the preview canvases before DismissModal() so nothing can paint
751 // or timer-fire into them during the post-loop wxSafeYield().
753
754 if( fpID.IsValid() )
755 {
756 wxString footprint = fpID.Format();
757
758 AddFootprintToHistory( footprint );
759 DismissModal( true, footprint );
760 }
761 else
762 {
763 DismissModal( false );
764 }
765}
766
767
769{
770 Close( false );
771}
772
773
774void FOOTPRINT_CHOOSER_FRAME::onFpChanged( wxCommandEvent& event )
775{
776 updateViews();
777
779}
780
781
783{
784 // initialize m_boardAdapter used by the 3D canvas
785 BOARD* dummyBoard = GetBoard();
786 m_boardAdapter.SetBoard( dummyBoard );
787 m_boardAdapter.m_IsBoardView = false;
788 m_boardAdapter.m_IsPreviewer = true; // Force display 3D models, regardless the 3D viewer options
789
791
792 // Build the 3D canvas
797
798 m_chooserPanel->m_RightPanelSizer->Add( m_preview3DCanvas, 1, wxEXPAND, 5 );
799 m_chooserPanel->m_RightPanel->Layout();
800
801 BOARD_DESIGN_SETTINGS& dummyBoard_bds = dummyBoard->GetDesignSettings();
802 dummyBoard_bds.SetBoardThickness( pcbIUScale.mmToIU( 1.6 ) );
803 dummyBoard_bds.SetEnabledLayers( LSET::FrontMask() | LSET::BackMask() );
804 BOARD_STACKUP& dummy_board_stackup = dummyBoard->GetDesignSettings().GetStackupDescriptor();
805 dummy_board_stackup.RemoveAll();
806 dummy_board_stackup.BuildDefaultStackupList( &dummyBoard_bds, 2 );
807}
808
809
811{
813
815
816 m_chooserPanel->GetDetailsPanel()->Show( m_showDescription );
817
818 if( !m_showDescription )
819 {
820 m_chooserPanel->GetVerticalSpliter()->SetMinimumPaneSize( GetSize().GetHeight() );
821 m_chooserPanel->GetVerticalSpliter()->SetSashPosition(
822 GetSize().GetHeight() + m_chooserPanel->GetDetailsPanel()->GetSize().GetHeight() );
823
824 m_chooserPanel->GetVerticalSpliter()->GetWindow2()->Hide();
825 m_chooserPanel->GetVerticalSpliter()->SetSashInvisible();
826
828 }
829 else
830 {
831 m_chooserPanel->GetVerticalSpliter()->SetMinimumPaneSize( 80 );
832 m_chooserPanel->GetVerticalSpliter()->GetWindow2()->Show();
833 m_chooserPanel->GetVerticalSpliter()->SetSashInvisible( false );
834
836 }
837
838 m_chooserPanel->GetVerticalSpliter()->UpdateSize();
839
840 m_chooserPanel->Layout();
841 m_chooserPanel->Refresh();
842}
843
844
845void FOOTPRINT_CHOOSER_FRAME::on3DviewReq( wxCommandEvent& event )
846{
847 if( m_show3DMode == true )
848 {
849 if( m_showFpMode == true )
850 {
851 m_show3DMode = false;
854 }
855 }
856 else
857 {
858 if( m_show3DViewer->IsChecked() )
859 {
861 }
862 else if( EDA_3D_VIEWER_FRAME* viewer3D = GetOur3DViewerFrame() )
863 {
864 // Close 3D viewer frame, if it is still enabled
865 viewer3D->Close( true );
866 }
867
868 m_show3DMode = true;
871 }
872}
873
874
875void FOOTPRINT_CHOOSER_FRAME::onFpViewReq( wxCommandEvent& event )
876{
877 if( m_showFpMode == true )
878 {
879 if( m_show3DMode == true )
880 {
881 m_showFpMode = false;
884 }
885 }
886 else
887 {
888 m_showFpMode = true;
891 }
892}
893
894
896{
897 // A selection event queued before dismissal can still dispatch during the
898 // post-loop wxSafeYield(). The 3D canvas stays IsShown() after quiescePreview()
899 // released its GL context, so reloading it here would touch torn-down state.
900 if( m_quiesced )
901 return;
902
904
905 if( m_preview3DCanvas->IsShown() )
906 {
907 m_preview3DCanvas->ReloadRequest();
908 m_preview3DCanvas->Request_refresh();
909 }
910
911 if( viewer3D )
912 {
913 Update3DView( true, true );
914 }
915
916 m_chooserPanel->m_RightPanel->Layout();
917 m_chooserPanel->m_RightPanel->Refresh();
918}
919
920
922{
923 FOOTPRINT_PREVIEW_WIDGET* viewFpPanel = m_chooserPanel->GetViewerPanel();
924 viewFpPanel->Show( m_showFpMode );
926
927 updateViews();
928}
929
930
932{
934
935 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
936 PCB_EDITOR_CONDITIONS cond( this );
937
938 wxASSERT( mgr );
939
940 // clang-format off
941#define CHECK( x ) ACTION_CONDITIONS().Check( x )
942
947
952
953#undef CHECK
954 // clang-format on
955}
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
@ text_visibility_off
@ text_visibility
@ FPHOLDER
Definition board.h:403
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
static TOOL_ACTION toggleGrid
Definition actions.h:194
static TOOL_ACTION cursorSmallCrosshairs
Definition actions.h:148
static TOOL_ACTION measureTool
Definition actions.h:248
static TOOL_ACTION cursor45Crosshairs
Definition actions.h:150
static TOOL_ACTION cursorFullCrosshairs
Definition actions.h:149
Manage TOOL_ACTION objects.
void SetConditions(const TOOL_ACTION &aAction, const ACTION_CONDITIONS &aConditions)
Set the conditions the UI elements for activating a specific tool action should use for determining t...
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
WINDOW_SETTINGS m_Window
wxString m_ColorTheme
Active color theme name.
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
void SetIsSeparator()
Render button as a toolbar separator.
Container for design settings for a BOARD object.
void SetEnabledLayers(const LSET &aMask)
Change the bit-mask of enabled layers to aMask.
BOARD_STACKUP & GetStackupDescriptor()
void SetBoardThickness(int aThickness)
Abstract interface for BOARD_ITEMs capable of storing other items inside.
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
void SetBoardUse(BOARD_USE aUse)
Set what the board is going to be used for.
Definition board.h:423
BOARD_DESIGN_SETTINGS & GetDesignSettings()
Definition board.cpp:1290
Color settings are a bit different than most of the settings objects in that there can be more than o...
Handles action that are shared between different applications.
Implement a canvas based on a wxGLCanvas.
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
EDA_MSG_PANEL * m_messagePanel
void SetCanvas(EDA_DRAW_PANEL_GAL *aPanel)
void SetEventDispatcher(TOOL_DISPATCHER *aEventDispatcher)
Set a dispatcher that processes events and forwards them to tools.
SELECTION_CONDITION CursorSmallCrosshairs()
Create a functor testing if the cursor is full screen in a frame.
SELECTION_CONDITION GridVisible()
Create a functor testing if the grid is visible in a frame.
SELECTION_CONDITION Cursor45Crosshairs()
SELECTION_CONDITION CursorFullCrosshairs()
void onFpViewReq(wxCommandEvent &event)
void updateViews()
Must be called after loading a new footprint: update footprint and/or 3D views.
void quiescePreview()
Stop the preview canvases and release their GPU/board state before the modal loop exits.
WINDOW_SETTINGS * GetWindowSettings(APP_SETTINGS_BASE *aCfg) override
Return a pointer to the window settings for this frame.
void KiwayMailIn(KIWAY_MAIL_EVENT &mail) override
Receive KIWAY_MAIL_EVENT messages from other players.
void closeFootprintChooser(wxCommandEvent &aEvent)
bool filterFootprint(LIB_TREE_NODE &aNode)
void on3DviewReq(wxCommandEvent &event)
void onFpChanged(wxCommandEvent &event)
FOOTPRINT_CHOOSER_FRAME(KIWAY *aKiway, wxWindow *aParent)
bool ShowModal(wxString *aFootprint, wxWindow *aParent) override
void OnPaint(wxPaintEvent &aEvent)
BOARD_ITEM_CONTAINER * GetModel() const override
void setupUIConditions() override
Setup the UI conditions for the various actions and their controls in this frame.
bool Show(bool show) override
void OnOK(wxCommandEvent &aEvent)
void updatePanelsVisibility()
Show hide footprint view panel and/or 3d view panel according to the options (display 3D shapes and u...
void toggleBottomSplit(wxCommandEvent &event)
void SetPosition(const wxPoint &aNewPosition)
Force the position of the dialog to a new position.
void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr) override
Update the 3D view, if the viewer is opened by this frame.
std::vector< std::unique_ptr< EDA_PATTERN_MATCH > > m_fpFilters
void onExternalViewer3DEnable(wxCommandEvent &aEvent)
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh) const override
Helper to retrieve the current color settings.
PANEL_FOOTPRINT_CHOOSER * m_chooserPanel
Selection tool for the footprint viewer in CvPcb.
Panel that renders a single footprint via Cairo GAL, meant to be exported through Kiface.
FOOTPRINT * GetCurrentFootprint() const
FOOTPRINT_PREVIEW_PANEL_BASE * GetPreviewPanel()
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition kiway_mail.h:34
std::string & GetPayload()
Return the payload, which can be any text but it typically self identifying s-expression.
Definition kiway_mail.h:52
MAIL_T Command()
Returns the MAIL_T associated with this mail.
Definition kiway_mail.h:44
virtual bool ShowModal(wxString *aResult=nullptr, wxWindow *aResultantFocusWindow=nullptr)
Show this wxFrame as if it were a modal dialog, with all other instantiated wxFrames disabled until t...
void SetModal(bool aIsModal)
void DismissModal(bool aRetVal, const wxString &aResult=wxEmptyString)
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:348
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition lib_id.cpp:65
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
UTF8 Format() const
Definition lib_id.cpp:132
Model class in the component selector Model-View-Adapter (mediated MVC) architecture.
static const LSET & FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition lset.cpp:718
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition lset.cpp:725
static const wxGLAttributes GetAttributesList(ANTIALIASING_MODE aAntiAliasingMode, bool aAlpha=false)
Get a list of attributes to pass to wxGLCanvas.
void OnChar(wxKeyEvent &aEvent)
Gather all the actions that are shared by tools.
Definition pcb_actions.h:51
static TOOL_ACTION padDisplayMode
static TOOL_ACTION graphicsOutlines
Display footprint graphics as outlines.
static TOOL_ACTION textOutlines
Display texts as lines.
static TOOL_ACTION showPadNumbers
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCB_BASE_FRAME(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName)
virtual PCB_VIEWERS_SETTINGS_BASE * GetViewerSettingsBase() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual void SetBoard(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr)
Set the m_pcb member in such as way as to ensure deleting any previous BOARD.
BOARD * GetBoard() const
EDA_3D_VIEWER_FRAME * CreateAndShow3D_Frame()
Show the 3D view frame.
EDA_3D_VIEWER_FRAME * GetOur3DViewerFrame()
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
Group generic conditions for PCB editor states.
SELECTION_CONDITION PadFillDisplay()
Create a functor that tests if the frame fills the pads.
SELECTION_CONDITION GraphicsFillDisplay()
Create a functor that tests if the frame fills graphics items.
SELECTION_CONDITION PadNumbersDisplay()
Create a functor that tests if the pad numbers are displayed.
SELECTION_CONDITION TextFillDisplay()
Create a functor that tests if the frame fills text items.
Generic tool for picking an item.
Tool useful for viewing footprints.
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
TOOL_MANAGER * m_toolManager
TOOL_DISPATCHER * m_toolDispatcher
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
ACTIONS * m_actions
Master controller class:
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Definition cvpcb.cpp:165
#define CHECK(x)
#define _(s)
Declaration of the eda_3d_viewer class.
#define FOOTPRINT_CHOOSER_FRAME_NAME
static wxRect s_dialogRect(0, 0, 0, 0)
static wxArrayString s_FootprintHistoryList
static unsigned s_FootprintHistoryMaxCount
static void AddFootprintToHistory(const wxString &aName)
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:40
PROJECT & Prj()
Definition kicad.cpp:737
EVT_MENU(ID_COMPARE_PROJECT_BRANCHES, KICAD_MANAGER_FRAME::OnCompareProjectBranches) KICAD_MANAGER_FRAME
@ MAIL_SYMBOL_NETLIST
Definition mail_type.h:41
void FixupCancelButtonCmdKeyCollision(wxWindow *aWindow)
Definition wxgtk/ui.cpp:347
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition wxgtk/ui.cpp:208
void ReparentModal(wxNonOwnedWindow *aWindow)
Move a window's parent to be the top-level window and force the window to be on top.
Definition wxgtk/ui.cpp:335
see class PGM_BASE
static const std::vector< std::string > filters
Definition plugin.cpp:64
#define DEFAULT_THEME
T * GetAppSettings(const char *aFilename)
std::vector< FAB_LAYER_COLOR > dummy
static std::vector< std::string > split(const std::string &aStr, const std::string &aDelim)
Split the input string into a vector of output strings.
Store the common settings that are saved and loaded for each window / frame.
#define PARENT_STYLE
#define MODAL_STYLE
KIBIS_PIN * pin
#define kv