KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_edit_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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2015-2016 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23#include "tool/embed_tool.h"
24#include "tools/convert_tool.h"
26#include "tools/drawing_tool.h"
27#include "tools/edit_tool.h"
30#include "tools/pad_tool.h"
31#include "tools/pcb_actions.h"
32#include "tools/pcb_control.h"
38#include <bitmaps.h>
41#include <api/api_server.h>
42#include <board.h>
44#include <widgets/wx_infobar.h>
45#include <footprint.h>
46#include <confirm.h>
47#include <drc/drc_item.h>
48#include <kidialog.h>
54#include <pcb_painter.h>
55#include <render_settings.h>
56#include <scoped_set_reset.h>
57#include <view/view.h>
58#include <kiface_base.h>
59#include <kiplatform/app.h>
60#include <kiplatform/ui.h>
61#include <kiway.h>
62#include <macros.h>
63#include <pcbnew_id.h>
64#include <pgm_base.h>
65#include <project.h>
66#include <project_pcb.h>
67#include <string_utils.h>
69#include <tool/action_toolbar.h>
70#include <tool/common_control.h>
71#include <tool/common_tools.h>
73#include <tool/selection.h>
76#include <tool/tool_manager.h>
77#include <tool/zoom_tool.h>
78#include <tools/array_tool.h>
86#include <widgets/lib_tree.h>
92
93#include <algorithm>
94
95#include <wx/filedlg.h>
96#include <wx/hyperlink.h>
97
98BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
101
103
106
108
109 // Drop files event
110 EVT_DROP_FILES( FOOTPRINT_EDIT_FRAME::OnDropFiles )
111
112END_EVENT_TABLE()
113
114
115FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
116 PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_FOOTPRINT_EDITOR, _( "Footprint Editor" ), wxDefaultPosition,
119 m_tabsPanel( nullptr ),
120 m_activeTab( nullptr ),
122 m_protectedBorrowedBoard( nullptr ),
124{
125 m_showBorderAndTitleBlock = false; // true to show the frame references
126 m_aboutTitle = _HKI( "KiCad Footprint Editor" );
127 m_editorSettings = nullptr;
128
129 // Give an icon
130 wxIcon icon;
131 wxIconBundle icon_bundle;
132
133 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit, 48 ) );
134 icon_bundle.AddIcon( icon );
135 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit, 128 ) );
136 icon_bundle.AddIcon( icon );
137 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit, 256 ) );
138 icon_bundle.AddIcon( icon );
139 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit_32 ) );
140 icon_bundle.AddIcon( icon );
141 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit_16 ) );
142 icon_bundle.AddIcon( icon );
143
144 SetIcons( icon_bundle );
145
146 // Create GAL canvas
148
149 PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_frameSize,
151 SetCanvas( drawPanel );
152
153 SetBoard( new BOARD() );
154
155 // This board will only be used to hold a footprint for editing
156 GetBoard()->SetBoardUse( BOARD_USE::FPHOLDER );
157
158 // In Footprint Editor, the default net clearance is not known (it depends on the actual
159 // board). So we do not show the default clearance, by setting it to 0. The footprint or
160 // pad specific clearance will be shown.
161 GetBoard()->GetDesignSettings().m_NetSettings->GetDefaultNetclass()->SetClearance( 0 );
162
163 // Don't show the default board solder mask expansion in the footprint editor. Only the
164 // footprint or pad mask expansions settings should be shown.
165 GetBoard()->GetDesignSettings().m_SolderMaskExpansion = 0;
166
167 // Ensure all layers and items are visible:
168 // In footprint editor, some layers have no meaning or cannot be used, but we show all of
169 // them, at least to be able to edit a bad layer
170 GetBoard()->SetVisibleAlls();
171
172 GetGalDisplayOptions().m_axesEnabled = true;
173
174 // In Footprint Editor, set the default paper size to A4 for plot/print
176 SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU( pcbIUScale.IU_PER_MILS ) ) );
177
178 // Create the manager and dispatcher & route draw panel events to the dispatcher
179 setupTools();
181
183 m_treePane = new FOOTPRINT_TREE_PANE( this );
184
188 ReCreateLayerBox( false );
189
191
193 m_appearancePanel = new APPEARANCE_CONTROLS( this, GetCanvas(), true );
194 m_propertiesPanel = new PCB_PROPERTIES_PANEL( this, this );
195
196 // LoadSettings() *after* creating m_LayersManager, because LoadSettings() initialize
197 // parameters in m_LayersManager
198 // NOTE: KifaceSettings() will return PCBNEW_SETTINGS if we started from pcbnew
200
202
203 float proportion = GetFootprintEditorSettings()->m_AuiPanels.properties_splitter;
204 m_propertiesPanel->SetSplitterProportion( proportion );
205
207
208 // Fetch a COPY of the config as a lot of these initializations are going to overwrite our
209 // data.
210 int libWidth = 0;
212
214 {
215 libWidth = cfg->m_LibWidth;
216 aui_cfg = cfg->m_AuiPanels;
217 }
218 else
219 {
220 // keep gcc quiet about uninitalized vars:
221 aui_cfg.appearance_panel_tab = 0;
222 aui_cfg.right_panel_width = -1;
223 }
224
225 m_auimgr.SetManagedWindow( this );
226
227 // Create the infobar pane only after the AUI manager owns this frame. Registering it before
228 // SetManagedWindow() leaves the Top/Layer-1 pane mispositioned once the tabbed center pane
229 // mounts and the perspective restores, so ShowMessage() never reveals it.
231
232 unsigned int auiFlags = wxAUI_MGR_DEFAULT;
233#if !defined( _WIN32 )
234 // Windows cannot redraw the UI fast enough during a live resize and may lead to all kinds
235 // of graphical glitches
236 auiFlags |= wxAUI_MGR_LIVE_RESIZE;
237#endif
238 m_auimgr.SetFlags( auiFlags );
239
240 // Rows; layers 4 - 6
241 m_auimgr.AddPane( m_tbTopMain, EDA_PANE().HToolbar().Name( "TopMainToolbar" )
242 .Top().Layer( 6 ) );
243
244 m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" )
245 .Bottom().Layer( 6 ) );
246
247 // Columns; layers 1 - 3
248 m_auimgr.AddPane( m_treePane, EDA_PANE().Palette().Name( "Footprints" )
249 .Left().Layer( 4 )
250 .Caption( _( "Libraries" ) )
251 // Don't use -1 for don't-change-height on a growable panel; it has side-effects.
252 .MinSize( FromDIP( 250 ), FromDIP( 80 ) )
253 .BestSize( FromDIP( 250 ), -1 ) );
255 .Left().Layer( 3 )
256 .Caption( _( "Properties" ) ).PaneBorder( false )
257 .MinSize( FromDIP( wxSize( 240, 60 ) ) ).BestSize( FromDIP( wxSize( 300, 200 ) ) ) );
258 m_auimgr.AddPane( m_tbLeft, EDA_PANE().VToolbar().Name( "LeftToolbar" )
259 .Left().Layer( 2 ) );
260
261 m_auimgr.AddPane( m_tbRight, EDA_PANE().VToolbar().Name( "RightToolbar" )
262 .Right().Layer(2) );
263 m_auimgr.AddPane( m_appearancePanel, EDA_PANE().Name( "LayersManager" )
264 .Right().Layer( 3 )
265 .Caption( _( "Appearance" ) ).PaneBorder( false )
266 // Don't use -1 for don't-change-height on a growable panel; it has side-effects.
267 .MinSize( FromDIP( 180 ), FromDIP( 80 ) )
268 .BestSize( FromDIP( 180 ), -1 ) );
269 m_auimgr.AddPane( m_selectionFilterPanel, EDA_PANE().Palette().Name( "SelectionFilter" )
270 .Right().Layer( 3 ).Position( 2 )
271 .Caption( _( "Selection Filter" ) ).PaneBorder( false )
272 // Fixed-size pane; -1 for MinSize height is required
273 .MinSize( FromDIP( 180 ), -1 )
274 .BestSize( FromDIP( 180 ), -1 ) );
275
276 // Center: the tabbed-document strip owns the tab bar above a single, never-reparented canvas.
277 // The panel borrows the canvas; the frame keeps ownership through GetCanvas().
278 m_tabsPanel = new EDITOR_TABS_PANEL( this, GetCanvas() );
279
280 m_tabsPanel->onActivateTab =
281 [this]( int aIdx )
282 {
283 // Ignore activation during a full clear, when each tab close re-selects a fallback
284 // that would re-borrow a tab-owned board into m_pcb just before it is freed.
286 return;
287
288 if( aIdx >= 0 && aIdx < static_cast<int>( m_tabContexts.size() ) )
289 activateFootprintTab( m_tabContexts[aIdx].get() );
290 };
291
292 m_tabsPanel->onCloseTabRequested =
293 [this]( int aIdx ) -> bool
294 {
295 return promptAndCloseFootprintTab( aIdx );
296 };
297
298 // onCloseTabRequested installs the successor board atomically, so the panel must not re-activate
299 // the fallback after a close and re-borrow a just-installed or just-freed index.
300 m_tabsPanel->SetSuppressActivateOnClose( true );
301
302 m_tabsPanel->onQueryVisualState =
303 [this]( int aIdx ) -> TAB_VISUAL_STATE
304 {
305 // The panel model owns preview, but the live dirty flag lives on the shared frame
306 // screen folded into the context, so read modified from the context.
307 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
308
309 if( aIdx < 0 || aIdx >= static_cast<int>( entries.size() ) )
310 return TAB_VISUAL_STATE{};
311
312 bool modified = entries[aIdx].modified;
313
314 if( aIdx < (int) m_tabContexts.size() && m_tabContexts[aIdx].get() )
315 modified = m_tabContexts[aIdx]->IsModified();
316
317 return ResolveTabVisualState( entries[aIdx].preview, modified );
318 };
319
320 m_auimgr.AddPane( m_tabsPanel, EDA_PANE().Canvas().Name( "DrawFrame" )
321 .Center() );
322
324
325 m_auimgr.GetPane( "LayersManager" ).Show( m_show_layer_manager_tools );
326 m_auimgr.GetPane( "SelectionFilter" ).Show( m_show_layer_manager_tools );
327 m_auimgr.GetPane( PropertiesPaneName() ).Show( GetSettings()->m_AuiPanels.show_properties );
328
329 // The selection filter doesn't need to grow in the vertical direction when docked
330 m_auimgr.GetPane( "SelectionFilter" ).dock_proportion = 0;
331
334 DragAcceptFiles( true );
335
337
338 // Apply saved visibility stuff at the end
339 wxAuiPaneInfo& treePane = m_auimgr.GetPane( "Footprints" );
340 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
341
342 if( libWidth > 0 )
343 SetAuiPaneSize( m_auimgr, treePane, libWidth, -1 );
344
345 if( aui_cfg.right_panel_width > 0 )
346 SetAuiPaneSize( m_auimgr, layersManager, aui_cfg.right_panel_width, -1 );
347
348 m_appearancePanel->SetTabIndex( aui_cfg.appearance_panel_tab );
349
351 {
352 m_appearancePanel->SetUserLayerPresets( cfg->m_LayerPresets );
353 m_appearancePanel->ApplyLayerPreset( cfg->m_ActiveLayerPreset );
354 }
355
356 // restore the last footprint from the project, if any, after the library has been init'ed
357 // N.B. This needs to happen after the AUI manager has been initialized so that we can
358 // properly call the WX_INFOBAR without crashing on some systems.
360
361 m_apiHandler = std::make_unique<API_HANDLER_FOOTPRINT>( this );
363
364 if( Kiface().IsSingle() )
365 {
366 m_apiHandlerCommon = std::make_unique<API_HANDLER_COMMON>();
368 }
369
370 // This displays the last footprint loaded, if any, so it must be done after restoreLastFootprint()
372
373 GetToolManager()->PostAction( ACTIONS::zoomFitScreen );
375
377
378 // Default shutdown reason until a file is loaded
379 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Footprint changes are unsaved" ) );
380
381 // Catch unhandled accelerator command characters that were no handled by the library tree
382 // panel.
384 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
385
386 // GTK rejects WXK_TAB as a menu accelerator, so handle Ctrl+Tab cycling from the CHAR_HOOK
387 // stream. Binding after the dispatcher runs this handler first so it can consume the event.
388 Bind( wxEVT_CHAR_HOOK, &FOOTPRINT_EDIT_FRAME::OnTabCharHook, this );
389
390 // Ensure the window is on top
391 Raise();
392 Show( true );
393
394 // Register a call to update the toolbar sizes. It can't be done immediately because
395 // it seems to require some sizes calculated that aren't yet (at least on GTK).
396 CallAfter(
397 [this]()
398 {
399 // Ensure the controls on the toolbars all are correctly sized
401 m_treePane->FocusSearchFieldIfExists();
402
403 // Update the angle snap mode toolbar button to reflect the current preference
405 } );
406}
407
408
410{
411 // Hand the borrowed canvas back before the base destructor deletes it, or the later-destroyed
412 // panel would reparent already-freed memory. The canvas then frees exactly once.
413 m_tabsPanel->ReleaseSharedCanvas();
414
415 // Shutdown all running tools
416 if( m_toolManager )
417 m_toolManager->ShutdownAllTools();
418
419 // save the footprint in the PROJECT
421
422 // Clear the watched file
423 setFPWatcher( nullptr );
424
425 // When a tab context owns the active board, null the frame pointer so the base destructor does
426 // not double-free it. A frame-owned bootstrap board is left for the base class to delete.
428 m_pcb = nullptr;
429
430 // We passed ownership of these to wxAuiManager.
431 // delete m_selectionFilterPanel;
432 // delete m_appearancePanel;
433 // delete m_treePane;
434}
435
436
438{
440
441 FOOTPRINT* fp = static_cast<FOOTPRINT*>( GetModel() );
442
443 if( fp )
444 {
445 std::vector<MSG_PANEL_ITEM> msgItems;
446 fp->GetMsgPanelInfo( this, msgItems );
447 SetMsgPanel( msgItems );
448 }
449}
450
451
458
459
461{
462 return m_toolManager->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
463}
464
465
467{
468 // switches currently used canvas (Cairo / OpenGL).
469 PCB_BASE_FRAME::SwitchCanvas( aCanvasType );
470
471 GetCanvas()->GetGAL()->SetAxesEnabled( true );
472
473 // The base class method *does not reinit* the layers manager. We must update the layer
474 // widget to match board visibility states, both layers and render columns, and and some
475 // settings dependent on the canvas.
477}
478
479
485
486
488{
489 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
490 treePane.Show( !IsLibraryTreeShown() );
491
492 if( IsLibraryTreeShown() )
493 {
494 // SetAuiPaneSize also updates m_auimgr
495 SetAuiPaneSize( m_auimgr, treePane, m_editorSettings->m_LibWidth, -1 );
496 }
497 else
498 {
499 m_editorSettings->m_LibWidth = m_treePane->GetSize().x;
500 m_auimgr.Update();
501 }
502}
503
504
506{
507 m_treePane->FocusSearchFieldIfExists();
508}
509
510
512{
514 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
515 wxAuiPaneInfo& selectionFilter = m_auimgr.GetPane( "SelectionFilter" );
516
517 // show auxiliary Vertical layers and visibility manager toolbar
519 layersManager.Show( m_show_layer_manager_tools );
520 selectionFilter.Show( m_show_layer_manager_tools );
521
523 {
524 SetAuiPaneSize( m_auimgr, layersManager, settings->m_AuiPanels.right_panel_width, -1 );
525 }
526 else
527 {
528 settings->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x;
529 m_auimgr.Update();
530 }
531}
532
533
535{
536 return const_cast<wxAuiManager&>( m_auimgr ).GetPane( m_treePane ).IsShown();
537}
538
539
541{
542 // A tab close transiently leaves the frame with no board while UI repaints can still run.
543 if( !GetBoard() )
544 return nullptr;
545
546 return GetBoard()->GetFirstFootprint();
547}
548
549
551{
552 LIB_ID id;
553
554 if( IsLibraryTreeShown() )
556
557 if( id.GetLibNickname().empty() )
558 id = GetLoadedFPID();
559
560 return id;
561}
562
563
565{
566 // The board pointer is transiently null during a tab close while the library tree adapter can
567 // still repaint, so tolerate having no board.
568 if( !GetBoard() )
569 return LIB_ID();
570
571 FOOTPRINT* footprint = GetBoard()->GetFirstFootprint();
572
573 if( footprint )
574 return LIB_ID( footprint->GetFPID().GetLibNickname(), m_footprintNameWhenLoaded );
575 else
576 return LIB_ID();
577}
578
579
581{
582 if( GetBoard() && GetBoard()->GetFirstFootprint() )
583 {
586 }
587
588 GetScreen()->SetContentModified( false );
589
590 // OnModify() mirrors the dirty flag onto the active tab context and the panel model, so clear both
591 // here too. Tab rendering and close prompting read the context's flag, so a save that only cleared
592 // the shared screen would leave the tab starred and re-prompting to save.
593 if( m_activeTab )
594 {
595 m_activeTab->SetModified( false );
596
597 if( int idx = m_tabsPanel->FindTab( m_activeTab->GetTabKey() ); idx >= 0 )
598 m_tabsPanel->MarkModified( idx, false );
599 }
600}
601
602
604{
605 // If we've already vetted closing this window, then we have no FP anymore
606 if( m_isClosing || !GetBoard() )
607 return false;
608
609 FOOTPRINT* footprint = GetBoard()->GetFirstFootprint();
610
611 return ( footprint && footprint->GetLink() != niluuid );
612}
613
614
616{
617 LIB_ID id = GetLoadedFPID();
618
619 if( id.IsValid() )
620 {
622 Prj().SetRString( PROJECT::PCB_FOOTPRINT_EDITOR_FP_NAME, id.GetLibItemName() );
623 }
624}
625
626
628{
629 // Restore the persisted tab set first. The active tab is loaded last so it ends up focused, and
630 // tabs that no longer resolve are silently dropped.
631 if( FOOTPRINT_EDITOR_SETTINGS* cfg = GetSettings(); cfg && !cfg->m_OpenTabs.empty() )
632 {
633 const wxString activeKey = cfg->m_ActiveTab;
634
635 const auto loadTab =
636 [this]( const FOOTPRINT_EDITOR_SETTINGS::OPEN_TAB& aTab ) -> bool
637 {
638 LIB_ID id;
639 id.SetLibNickname( aTab.m_lib );
640 id.SetLibItemName( aTab.m_fpName );
641
642 if( FOOTPRINT* footprint = LoadFootprint( id ) )
643 {
644 AddFootprintToBoard( footprint );
645 findOrCreateFootprintTab( id, aTab.m_preview );
646
647 return true;
648 }
649
650 // LoadFootprint swallows the IO_ERROR when the library no longer resolves, so
651 // log the dropped tab to keep a failed restore diagnosable.
652 wxLogTrace( wxT( "KICAD_FP_TABS" ),
653 wxT( "Dropping persisted footprint tab '%s:%s' (failed to load)" ),
654 aTab.m_lib, aTab.m_fpName );
655
656 return false;
657 };
658
659 const FOOTPRINT_EDITOR_SETTINGS::OPEN_TAB* activeTab = nullptr;
660
661 for( const FOOTPRINT_EDITOR_SETTINGS::OPEN_TAB& tab : cfg->m_OpenTabs )
662 {
663 const wxString key = tab.m_lib + wxT( ":" ) + tab.m_fpName;
664
665 if( key == activeKey )
666 activeTab = &tab;
667 else
668 loadTab( tab );
669 }
670
671 if( activeTab )
672 loadTab( *activeTab );
673
674 if( !m_tabContexts.empty() )
675 return;
676 }
677
678 const wxString& footprintName = Prj().GetRString( PROJECT::PCB_FOOTPRINT_EDITOR_FP_NAME );
679 const wxString& libNickname = Prj().GetRString( PROJECT::PCB_FOOTPRINT_EDITOR_LIB_NICKNAME );
680
681 if( libNickname.Length() && footprintName.Length() )
682 {
683 LIB_ID id;
684 id.SetLibNickname( libNickname );
685 id.SetLibItemName( footprintName );
686
687 FOOTPRINT* footprint = LoadFootprint( id );
688
689 if( footprint )
690 {
691 AddFootprintToBoard( footprint );
692
693 // The last-session footprint is a real document, so promote its tab to permanent.
694 findOrCreateFootprintTab( id, false );
695 }
696 }
697}
698
699
701{
702 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( GetModel() );
703 BOARD& board = *GetBoard();
704
705 // All FPs have these layers enabled
706 LSET enabledLayers = LSET::AllTechMask() | LSET::UserMask();
707
708 const auto configureStackup =
709 [&]( FOOTPRINT_STACKUP aMode, const LSET& aLayerSet )
710 {
711 const LSET cuLayers = aLayerSet & LSET::AllCuMask();
712 board.SetCopperLayerCount( cuLayers.count() );
713
714 switch( aMode )
715 {
717 enabledLayers |= LSET{ F_Cu, In1_Cu, B_Cu };
718 board.SetLayerName( In1_Cu, _( "Inner layers" ) );
719 break;
720
722 // Nothing extra to add
723
724 // Clear layer name defaults
725 board.SetLayerName( In1_Cu, wxEmptyString );
726 break;
727 }
728
729 enabledLayers |= aLayerSet;
730 };
731
732 if( footprint )
733 {
734 configureStackup( footprint->GetStackupMode(), footprint->GetStackupLayers() );
735 }
736 else
737 {
738 // If no footprint is loaded, we assume the default stackup mode
739 configureStackup( FOOTPRINT_STACKUP::EXPAND_INNER_LAYERS, LSET{} );
740 }
741
743 {
744 m_originalFootprintCopy->RunOnChildren(
745 [&]( BOARD_ITEM* child )
746 {
747 LSET childLayers = child->GetLayerSet() & LSET::UserDefinedLayersMask();
748
749 for( PCB_LAYER_ID layer : childLayers )
750 enabledLayers.set( layer );
751 },
753 }
754
755 // Enable the user-configured number of user layers, plus any specifically named layers
757 {
758 int userLayerCount = cfg->m_DesignSettings.GetUserDefinedLayerCount();
759 enabledLayers |= LSET::UserDefinedLayersMask( userLayerCount );
760
761 for( const PCB_LAYER_ID& user : LSET::UserDefinedLayersMask() )
762 {
763 if( cfg->m_DesignSettings.m_UserLayerNames.contains( LSET::Name( user ).ToStdString() ) )
764 enabledLayers.set( user );
765 }
766 }
767
768 board.SetEnabledLayers( enabledLayers );
769
770 // Footprint Editor layer visibility is kept in the view, not the board (because the board
771 // just delegates to the project file, which we don't have).
772 for( const PCB_LAYER_ID& layer : GetBoard()->GetEnabledLayers() )
773 GetCanvas()->GetView()->SetLayerVisible( layer, true );
774}
775
776
778 const FOOTPRINT* aFootprint, bool aIsFromBoard,
779 const std::function<bool( const wxString& )>& aIsLibWritable )
780{
781 if( !aFootprint )
782 return EDIT_NOTICE::NONE;
783
784 if( aIsFromBoard )
786
787 const wxString libName = aFootprint->GetFPID().GetLibNickname();
788
789 // An empty libname is OK - you get that when creating a new footprint from the main menu
790 // In that case. treat is as editable, and the user will be prompted for save-as when saving.
791 if( libName.empty() || aIsLibWritable( libName ) )
792 return EDIT_NOTICE::NONE;
793
795}
796
797
799{
800 // Use CallAfter so that we update the canvas before waiting for the infobar animation
801 CallAfter(
802 [this]()
803 {
804 BOARD* board = GetBoard();
805 FOOTPRINT* fp = board ? board->GetFirstFootprint() : nullptr;
806
807 const EDIT_NOTICE notice = editNoticeFor( fp, IsCurrentFPFromBoard(),
808 [this]( const wxString& aLib )
809 {
811 } );
812
813 // Clear_Pcb() queues this against an empty board and then opens a modal dialog whose
814 // event loop runs it, so there may be no footprint left to describe
815 if( notice == EDIT_NOTICE::NONE )
816 {
817 if( WX_INFOBAR* infobar = GetInfoBar() )
818 infobar->Dismiss();
819
820 return;
821 }
822
823 wxString libName = fp->GetFPID().GetLibNickname();
824 wxString msg, link;
825
826 if( notice == EDIT_NOTICE::FROM_BOARD )
827 {
828 msg.Printf( _( "Editing %s from board. Saving will update the board only." ), fp->GetReference() );
829 link.Printf( _( "Open in library %s" ), UnescapeString( libName ) );
830
831 const auto openLibraryCopy =
832 [this]( wxHyperlinkEvent& aEvent )
833 {
835 };
836
837 if( WX_INFOBAR* infobar = GetInfoBar() )
838 {
839 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, link, wxEmptyString );
840 button->Bind( wxEVT_COMMAND_HYPERLINK, openLibraryCopy );
841
842 infobar->RemoveAllButtons();
843 infobar->AddButton( button );
844 infobar->AddCloseButton();
845 infobar->ShowMessage( msg, wxICON_INFORMATION );
846 }
847 }
848 else
849 {
850 msg.Printf( _( "Editing footprint from read-only library %s." ), UnescapeString( libName ) );
851
852 if( WX_INFOBAR* infobar = GetInfoBar() )
853 {
854 link = _( "Save as editable copy" );
855
856 const auto saveAsEditableCopy =
857 [this]( wxHyperlinkEvent& aEvent )
858 {
859 SaveFootprintAs( GetBoard()->GetFirstFootprint() );
860 GetCanvas()->GetView()->Update( GetBoard()->GetFirstFootprint() );
861 ClearModify();
862
863 // Get rid of the save-will-update-board-only (or any other dismissable warning)
864 WX_INFOBAR* loc_infobar = GetInfoBar();
865
866 if( loc_infobar->IsShownOnScreen() && loc_infobar->HasCloseButton() )
867 loc_infobar->Dismiss();
868
870 SyncLibraryTree( true );
871 };
872
873 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, link, wxEmptyString );
874 button->Bind( wxEVT_COMMAND_HYPERLINK, saveAsEditableCopy );
875
876 infobar->RemoveAllButtons();
877 infobar->AddButton( button );
878 infobar->AddCloseButton();
879 infobar->ShowMessage( msg, wxICON_INFORMATION );
880 }
881 }
882 } );
883}
884
885
887{
888 // Cancel a mid-draw tool before the footprint it points into is freed (#24975).
889 if( GetToolManager() )
891
893
894 m_originalFootprintCopy.reset( static_cast<FOOTPRINT*>( aFootprint->Clone() ) );
895 m_originalFootprintCopy->SetParent( nullptr );
896
898
899 // Mirror the load baseline into the active tab context so it survives a tab switch (the frame
900 // members are only a borrowed view of the active context's baseline).
901 if( m_activeTab )
902 {
903 FOOTPRINT* fp_copy = nullptr;
904
906 fp_copy = static_cast<FOOTPRINT*>( m_originalFootprintCopy->Clone() );
907
908 m_activeTab->SetOriginalFootprintCopy( std::unique_ptr<FOOTPRINT>( fp_copy ) );
909 m_activeTab->SetFootprintNameWhenLoaded( m_footprintNameWhenLoaded );
910 m_activeTab->SetName( aFootprint->GetFPID().GetLibItemName() );
911 }
912
914 // Ensure item UUIDs are valid
915 // ("old" footprints can have null uuids that create issues in fp editor)
916 aFootprint->FixUuids();
917
922}
923
924
926{
927 const bool fromBoard = aFootprint && aFootprint->GetLink() != niluuid;
928
929 if( !aHasTabs || !aFootprint || fromBoard || !aFootprint->GetFPID().IsValid() )
930 return false;
931
932 // A new footprint is parented to the board the tab switch is about to free, so drop the parent
933 // before the switch; ReloadFootprint reparents it to the incoming board
934 aFootprint->SetParent( nullptr );
935
936 return true;
937}
938
939
941{
942 ReloadFootprint( aFootprint );
943
945 setFPWatcher( nullptr );
946 else
947 setFPWatcher( aFootprint );
948}
949
950
952{
953 // Opening from the library is a preview that the next library-open reuses; editing promotes it
954 // to a permanent tab.
955 if( prepareFootprintTabHandoff( aFootprint, m_tabsPanel != nullptr ) )
956 findOrCreateFootprintTab( aFootprint->GetFPID(), true );
957
958 installFootprintOnActiveBoard( aFootprint );
959}
960
961
963{
965 return true;
966
967 return std::any_of( m_tabContexts.begin(), m_tabContexts.end(),
968 [this]( const std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT>& aCtx )
969 {
970 return aCtx->GetBoard() == m_pcb;
971 } );
972}
973
974
976{
977 // Swap the board pointer without the SetBoard delete, since on a tab switch the outgoing board
978 // is owned by its tab context. Reproduce only the side effects SetBoard applies to the incoming
979 // board.
980 if( m_pcb == aBoard )
981 return;
982
983 // The only frame-owned board is the constructor's bootstrap board. Delete it when we first
984 // switch away so it does not leak; tab-owned boards are left to their contexts.
985 if( m_pcb && !activeBoardOwnedByTab() )
986 delete m_pcb;
987
988 m_pcb = aBoard;
989
990 if( GetBoard() )
992
993 if( GetBoard() && GetCanvas() )
994 {
995 if( KIGFX::RENDER_SETTINGS* rs = GetCanvas()->GetView()->GetPainter()->GetSettings() )
996 {
997 rs->SetDashLengthRatio( GetBoard()->GetPlotOptions().GetDashedLineDashRatio() );
998 rs->SetGapLengthRatio( GetBoard()->GetPlotOptions().GetDashedLineGapRatio() );
999 }
1000 }
1001
1002 wxCommandEvent e( EDA_EVT_BOARD_CHANGED );
1003 ProcessEventLocally( e );
1004}
1005
1006
1008{
1009 if( !m_activeTab )
1010 return;
1011
1012 KIGFX::VIEW* view = GetCanvas()->GetView();
1013
1014 EDITOR_TAB_CONTEXT::VIEW_SNAPSHOT& snap = m_activeTab->ViewSnapshot();
1015 snap.scale = view->GetScale();
1016 snap.center = view->GetCenter();
1017 snap.valid = true;
1018
1019 std::vector<KIID>& sel = m_activeTab->SavedSelection();
1020 sel.clear();
1021
1022 for( EDA_ITEM* item : GetCurrentSelection() )
1023 sel.push_back( item->m_Uuid );
1024
1025 // Dirty state lives on the shared frame screen, so fold it into the context to survive the switch.
1026 if( GetScreen() )
1027 m_activeTab->SetModified( GetScreen()->IsContentModified() );
1028
1029 // Swap the raw vectors since UNDO_REDO_CONTAINER is non-copyable; ownership transfers intact.
1030 m_activeTab->UndoList().m_CommandsList.swap( m_undoList.m_CommandsList );
1031 m_activeTab->RedoList().m_CommandsList.swap( m_redoList.m_CommandsList );
1032
1033 m_activeTab = nullptr;
1034}
1035
1036
1038{
1039 if( !aCtx || aCtx == m_activeTab )
1040 return;
1041
1042 installFootprintTabBoard( aCtx, aCtx->GetBoard() );
1043}
1044
1045
1047 BOARD* aBoard )
1048{
1049 // Install the successor board and tool environment before the caller frees the outgoing context
1050 // so no tool Reset() or repaint ever sees a freed or null m_pcb. Never calls the base SetBoard,
1051 // which would delete m_pcb and reset tools while the model still aliases it.
1052
1054
1055 // Drop selection and unwind a mid-draw tool while the outgoing board is still valid (#24975).
1056 if( m_toolManager )
1057 {
1059 m_toolManager->DeactivateTool();
1060 }
1061
1062 m_activeTab = aCtx;
1063
1064 borrowBoardNonDestructive( aBoard );
1065
1066 if( aCtx )
1067 {
1068 m_undoList.m_CommandsList.swap( aCtx->UndoList().m_CommandsList );
1069 m_redoList.m_CommandsList.swap( aCtx->RedoList().m_CommandsList );
1070 }
1071 else
1072 {
1073 // Discard the swapped-in lists with their transient items so nothing references a freed board.
1075 }
1076
1078 ? static_cast<FOOTPRINT*>( aCtx->GetOriginalFootprintCopy()->Clone() )
1079 : nullptr );
1080 m_footprintNameWhenLoaded = aCtx ? aCtx->GetFootprintNameWhenLoaded() : wxString();
1081
1082 // Mirror the incoming tab's board-uuid remap onto the frame so SaveFootprintToBoard saves an
1083 // instance edit back to the originating board items. A library tab has an empty map.
1084 if( aCtx )
1086 else
1087 m_boardFootprintUuids.clear();
1088
1089 if( GetScreen() )
1090 GetScreen()->SetContentModified( aCtx ? aCtx->IsModified() : false );
1091
1092 // Point the tool environment at the incoming board before ResetTools so tools never dereference
1093 // a freed model.
1094 m_toolManager->SetEnvironment( GetBoard(), GetCanvas()->GetView(),
1095 GetCanvas()->GetViewControls(), config(), this );
1096
1099
1101
1102 if( !aCtx )
1103 {
1105 updateInfoBar();
1109 return;
1110 }
1111
1112 const EDITOR_TAB_CONTEXT::VIEW_SNAPSHOT& snap = aCtx->ViewSnapshot();
1113
1114 if( snap.valid )
1115 {
1116 GetCanvas()->GetView()->SetScale( snap.scale );
1117 GetCanvas()->GetView()->SetCenter( snap.center );
1118 }
1119 else
1120 {
1121 // First time this tab is shown there is no saved view
1123 }
1124
1125 if( !aCtx->SavedSelection().empty() )
1126 {
1128
1129 if( selTool )
1130 {
1131 for( const KIID& id : aCtx->SavedSelection() )
1132 {
1133 if( BOARD_ITEM* item = GetBoard()->ResolveItem( id, true ) )
1134 selTool->select( item );
1135 }
1136 }
1137 }
1138
1139 if( m_appearancePanel )
1140 m_appearancePanel->OnBoardChanged();
1141
1142 if( m_propertiesPanel )
1143 m_propertiesPanel->UpdateData();
1144
1146 updateInfoBar();
1150}
1151
1152
1153static std::unique_ptr<BOARD> makeFpHolderBoard()
1154{
1155 auto board = std::make_unique<BOARD>();
1156 board->SetBoardUse( BOARD_USE::FPHOLDER );
1157 board->GetDesignSettings().m_NetSettings->GetDefaultNetclass()->SetClearance( 0 );
1158 board->GetDesignSettings().m_SolderMaskExpansion = 0;
1159 board->SetVisibleAlls();
1160
1161 return board;
1162}
1163
1164
1166{
1167 const wxString lib = aLibId.GetLibNickname();
1168 const wxString name = aLibId.GetLibItemName();
1169 const wxString key = lib + wxT( ":" ) + name;
1170
1171 if( int existing = m_tabsPanel->FindTab( key ); existing >= 0 )
1172 {
1173 m_tabsPanel->AddTab( key, name, aAsPreview );
1174 return m_tabContexts[existing].get();
1175 }
1176
1177 auto ctx = std::make_unique<FOOTPRINT_EDITOR_TAB_CONTEXT>( lib, name, makeFpHolderBoard() );
1178 ctx->SetPreview( aAsPreview );
1179
1180 FOOTPRINT_EDITOR_TAB_CONTEXT* raw = ctx.get();
1181
1182 // Keep m_tabContexts index-aligned with the panel model. A previewed open reuses the preview
1183 // slot in place; otherwise the context is appended. It must be at its final index before AddTab
1184 // fires onActivateTab.
1185 const int reuseSlot = aAsPreview ? m_tabsPanel->Model().PreviewIndex() : -1;
1186
1187 if( reuseSlot >= 0 && reuseSlot < static_cast<int>( m_tabContexts.size() ) )
1188 {
1189 // Tear the active document down while the outgoing board is still alive, before it is
1190 // displaced and freed.
1191 if( m_tabContexts[reuseSlot].get() == m_activeTab )
1192 {
1193 if( m_toolManager )
1195
1197 m_activeTab = nullptr;
1198 }
1199
1200 return placeReusedTabContext( m_tabContexts, reuseSlot, std::move( ctx ),
1201 [&]( const FOOTPRINT_EDITOR_TAB_CONTEXT& aDisplaced )
1202 {
1204 aDisplaced.GetBoard() );
1205 m_tabsPanel->AddTab( key, name, aAsPreview );
1206 } );
1207 }
1208
1209 m_tabContexts.push_back( std::move( ctx ) );
1210
1211 m_tabsPanel->AddTab( key, name, aAsPreview );
1212
1213 return raw;
1214}
1215
1216
1218 std::vector<std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT>>& aContexts, int aSlot,
1219 std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT> aNew,
1220 const std::function<void( const FOOTPRINT_EDITOR_TAB_CONTEXT& )>& aInstallSuccessor )
1221{
1222 // Hold the displaced context, and its still-displayed board, alive across aInstallSuccessor, which
1223 // repoints the canvas VIEW at the incoming board. Freeing the old board first would leave
1224 // VIEW::Clear() dereferencing items from a destroyed board.
1225 std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT> displaced = std::move( aContexts[aSlot] );
1226 aContexts[aSlot] = std::move( aNew );
1227
1228 FOOTPRINT_EDITOR_TAB_CONTEXT* raw = aContexts[aSlot].get();
1229
1230 aInstallSuccessor( *displaced );
1231
1232 return raw;
1233}
1234
1235
1237{
1238 if( !aBoardFootprint )
1239 return nullptr;
1240
1241 const KIID sourceUuid = aBoardFootprint->m_Uuid;
1242 const wxString key = FOOTPRINT_EDITOR_TAB_CONTEXT::MakeInstanceTabKey( sourceUuid );
1243 const wxString reference = aBoardFootprint->GetReference();
1244
1245 // Re-editing the same placed footprint focuses the live tab rather than duplicating it.
1246 if( int existing = m_tabsPanel->FindTab( key ); existing >= 0 )
1247 {
1248 m_tabsPanel->AddTab( key, reference + wxS( " " ) + _( "[from board]" ), false );
1249 return m_tabContexts[existing].get();
1250 }
1251
1252 std::unique_ptr<BOARD> board = makeFpHolderBoard();
1253 board->GetDesignSettings().m_DRCSeverities[DRCE_MISSING_COURTYARD] = RPT_SEVERITY_WARNING;
1254
1255 auto ctx = std::make_unique<FOOTPRINT_EDITOR_TAB_CONTEXT>( sourceUuid, reference, std::move( board ) );
1256 BOARD* ctxBoard = ctx->GetBoard();
1257 std::map<KIID, KIID>& uuidMap = ctx->BoardFootprintUuids();
1258 FOOTPRINT_EDITOR_TAB_CONTEXT* raw = ctx.get();
1259
1260 const auto recordAndUpdateUuid =
1261 [&]( BOARD_ITEM* aItem )
1262 {
1263 KIID newId;
1264 uuidMap[newId] = aItem->m_Uuid;
1265 aItem->SetUuid( newId );
1266 };
1267
1268 // Clone keeps the existing uuids, which the remap then swaps for fresh editor-local ones so
1269 // SaveFootprintToBoard can map them back to the original board items.
1270 FOOTPRINT* clone = static_cast<FOOTPRINT*>( aBoardFootprint->Clone() );
1271 clone->SetParent( ctxBoard );
1272 clone->SetParentGroup( nullptr );
1273 clone->SetLink( aBoardFootprint->m_Uuid );
1274 clone->ClearFlags();
1275 clone->SetLocked( false );
1276
1277 recordAndUpdateUuid( clone );
1278 clone->RunOnChildren(
1279 [&]( BOARD_ITEM* aItem )
1280 {
1281 if( aItem->Type() == PCB_PAD_T )
1282 aItem->SetLocked( false );
1283
1284 aItem->ClearFlags();
1285 recordAndUpdateUuid( aItem );
1286 },
1288
1289 ctxBoard->Add( clone );
1290
1291 // The editor knows nothing of the board's nets, so force the orphaned dummy net on every pad to
1292 // avoid saving a reference to an unknown net into the library cache.
1293 clone->ClearAllNets();
1294
1295 // Normalize placement to the footprint-editor defaults so the editor view matches a library load.
1296 clone->SetPosition( VECTOR2I( 0, 0 ) );
1297
1298 if( clone->GetLayer() != F_Cu )
1299 clone->Flip( clone->GetPosition(), GetPcbNewSettings()->m_FlipDirection );
1300
1301 clone->SetOrientation( ANGLE_0 );
1302 clone->RunOnChildren(
1303 [&]( BOARD_ITEM* aItem )
1304 {
1305 if( aItem->Type() == PCB_TEXT_T )
1306 static_cast<PCB_TEXT*>( aItem )->KeepUpright();
1307 },
1309
1310 m_tabContexts.push_back( std::move( ctx ) );
1311
1312 // Index-aligned with the panel model; the context is at its final index before AddTab fires
1313 // onActivateTab.
1314 m_tabsPanel->AddTab( key, reference + wxS( " " ) + _( "[from board]" ), false );
1315
1316 return raw;
1317}
1318
1319
1321{
1322 std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT> ctx =
1324
1325 const wxString key = ctx->GetTabKey();
1326 const wxString label = ctx->GetDisplayName();
1327 FOOTPRINT_EDITOR_TAB_CONTEXT* raw = ctx.get();
1328
1329 m_tabContexts.push_back( std::move( ctx ) );
1330
1331 // At its final index before AddTab fires onActivateTab, which makes the new tab active
1332 m_tabsPanel->AddTab( key, label, false );
1333
1334 return raw;
1335}
1336
1337
1339 UNDO_REDO_CONTAINER& aRedo )
1340{
1341 // Free the UR_TRANSIENT board items each command owns and the command wrappers. The frame's own
1342 // ClearUndoRedoList() and the bare container destructor delete only the wrappers and leak the
1343 // transient items, so a discarded tab history must come through here.
1344 for( UNDO_REDO_CONTAINER* list : { &aUndo, &aRedo } )
1345 {
1346 for( PICKED_ITEMS_LIST* cmd : list->m_CommandsList )
1347 {
1349 delete cmd;
1350 }
1351
1352 list->m_CommandsList.clear();
1353 }
1354}
1355
1356
1358{
1359 // The context is detached here, so the transient items in its lists are never the live objects.
1361}
1362
1363
1365{
1366 if( aIdx < 0 || aIdx >= static_cast<int>( m_tabContexts.size() ) )
1367 return false;
1368
1370
1371 // The active tab's live dirty state lives on the shared frame screen, so ctx->IsModified() is
1372 // stale for it. Fold the screen state back in so an unsaved active tab still prompts.
1373 if( ctx == m_activeTab && GetScreen() )
1375
1376 if( ctx->IsModified() && !m_silentFootprintTabClose )
1377 {
1378 // Prompt while the closing tab is still fully live so a save reads its real board.
1379 wxString msg = wxString::Format( _( "Save changes to '%s' before closing?" ),
1380 ctx->GetDisplayName() );
1381
1382 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
1383 dlg.SetYesNoCancelLabels( _( "Save" ), _( "Discard Changes" ), _( "Cancel" ) );
1384
1385 switch( dlg.ShowModal() )
1386 {
1387 case wxID_YES:
1388 {
1389 // SaveFootprint reads the active tab's load baseline for rename detection, so an inactive
1390 // tab must be made active first or it saves against the wrong baseline. Restore the prior
1391 // active tab afterwards so closing an inactive tab stays an inactive close, keeping the
1392 // panel's suppressed fallback selection aligned with the live board. Veto the close if the
1393 // save did not complete so the edits and history are not silently dropped.
1394 FOOTPRINT_EDITOR_TAB_CONTEXT* activeBeforeSave = m_activeTab;
1395 const bool activatedForSave = ( ctx != m_activeTab );
1396
1397 if( activatedForSave )
1398 activateFootprintTab( ctx );
1399
1400 const bool saved = SaveFootprint( ctx->GetBoard()->GetFirstFootprint() );
1401
1402 if( activatedForSave && activeBeforeSave )
1403 activateFootprintTab( activeBeforeSave );
1404
1405 if( !saved )
1406 return false;
1407
1408 break;
1409 }
1410
1411 case wxID_NO: break;
1412 default:
1413 case wxID_CANCEL: return false;
1414 }
1415 }
1416
1417 const bool closingActive = ( ctx == m_activeTab );
1418
1419 if( !closingActive )
1420 {
1421 // m_pcb aliases a different live tab's board, so freeing this context dangles nothing.
1423 m_tabContexts.erase( m_tabContexts.begin() + aIdx );
1424 return true;
1425 }
1426
1427 // The closing tab's lists are currently the frame's live lists. Free them now with their
1428 // transient items, so the install's detach swaps empty lists into the closing context.
1430
1431 const int newCount = static_cast<int>( m_tabContexts.size() ) - 1;
1432 const int successorIdx = newCount > 0 ? std::min( aIdx, newCount - 1 ) : -1;
1433
1434 if( successorIdx >= 0 )
1435 {
1436 // Map the successor's post-erase position back to a pre-erase index. Indices above the closed
1437 // one shift down by one after the erase.
1438 const int preEraseSuccessor = successorIdx < aIdx ? successorIdx : successorIdx + 1;
1439
1440 FOOTPRINT_EDITOR_TAB_CONTEXT* successor = m_tabContexts[preEraseSuccessor].get();
1441
1442 installFootprintTabBoard( successor, successor->GetBoard() );
1443 }
1444 else
1445 {
1446 // Last tab: the fresh empty board is frame-owned like the bootstrap board.
1447 installFootprintTabBoard( nullptr, makeFpHolderBoard().release() );
1448 }
1449
1450 // The install swapped m_pcb off the closing board, so erasing the context frees it safely.
1451 m_tabContexts.erase( m_tabContexts.begin() + aIdx );
1452
1453 return true;
1454}
1455
1456
1458{
1459 const wxString lib = aFPID.GetLibNickname();
1460 const wxString name = aFPID.GetLibItemName();
1461 const int idx = m_tabsPanel->FindTab( lib + wxT( ":" ) + name );
1462
1463 if( idx < 0 )
1464 return;
1465
1466 // The caller already confirmed the deletion, so close without re-prompting. The panel selects a
1467 // successor when the closed tab was active.
1469 m_tabsPanel->CloseTab( idx );
1471}
1472
1473
1474void FOOTPRINT_EDIT_FRAME::RenameFootprintTab( const LIB_ID& aOldId, const LIB_ID& aNewId )
1475{
1476 const wxString newLib = aNewId.GetLibNickname();
1477 const wxString newName = aNewId.GetLibItemName();
1478
1479 // An unsaved import is keyed by a session id, not by aOldId, so the save-as that named it promotes
1480 // the active tab instead. A tree-driven rename carries a nickname and never reaches this path
1481 if( m_activeTab && m_activeTab->IsUnsaved() && aOldId.GetLibNickname().empty()
1482 && !newLib.IsEmpty() )
1483 {
1484 const wxString unsavedKey = m_activeTab->GetTabKey();
1485
1486 m_activeTab->PromoteToLibrary( newLib, newName );
1487 m_tabsPanel->RenameTab( unsavedKey, m_activeTab->GetTabKey(), m_activeTab->GetDisplayName() );
1488
1489 return;
1490 }
1491
1492 const wxString oldLib = aOldId.GetLibNickname();
1493 const wxString oldName = aOldId.GetLibItemName();
1494 const wxString oldKey = oldLib + wxT( ":" ) + oldName;
1495 const int idx = m_tabsPanel->FindTab( oldKey );
1496
1497 if( idx < 0 )
1498 return;
1499
1500 if( idx < static_cast<int>( m_tabContexts.size() ) )
1501 {
1502 // A tab switch restores the context's baseline onto the frame, so it must track the rename too
1503 // or the next save would delete the pre-rename library entry
1504 m_tabContexts[idx]->SetName( newName );
1505 m_tabContexts[idx]->SetFootprintNameWhenLoaded( newName );
1506 }
1507
1508 m_tabsPanel->RenameTab( oldKey, newLib + wxT( ":" ) + newName, newName );
1509}
1510
1511
1513{
1514 for( const std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
1515 {
1516 if( ctx.get() != m_activeTab && ctx->IsTransient() && ctx->IsModified() )
1517 return true;
1518 }
1519
1520 return false;
1521}
1522
1523
1525{
1526 // Collect first; saving activates a tab, which mutates m_activeTab and the live board pointer.
1527 std::vector<FOOTPRINT_EDITOR_TAB_CONTEXT*> dirty;
1528
1529 for( const std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
1530 {
1531 // The active tab and the persisted library tabs are handled by the main canCloseWindow check
1532 if( ctx.get() != m_activeTab && ctx->IsTransient() && ctx->IsModified() )
1533 dirty.push_back( ctx.get() );
1534 }
1535
1536 // Saving activates each dirty tab in turn; restore the tab the user was on so a vetoed close leaves
1537 // the editor where it was and a successful close persists the real active tab, not a discarded one.
1538 FOOTPRINT_EDITOR_TAB_CONTEXT* originalActive = m_activeTab;
1539
1540 for( FOOTPRINT_EDITOR_TAB_CONTEXT* ctx : dirty )
1541 {
1542 wxString msg = wxString::Format( _( "Save changes to '%s' before closing?" ), ctx->GetDisplayName() );
1543 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
1544 dlg.SetYesNoCancelLabels( _( "Save" ), _( "Discard Changes" ), _( "Cancel" ) );
1545
1546 const int answer = dlg.ShowModal();
1547
1548 if( answer == wxID_YES )
1549 {
1550 // SaveFootprint reads the active tab's load baseline and uuid remap, so make this tab
1551 // active first; it does not clear the dirty flag, so ClearModify below does it or a
1552 // vetoed close would re-prompt an already-saved tab.
1553 activateFootprintTab( ctx );
1554
1555 if( !SaveFootprint( ctx->GetBoard()->GetFirstFootprint() ) )
1556 {
1557 activateFootprintTab( originalActive );
1558 return false;
1559 }
1560
1561 ClearModify();
1562 }
1563 else if( answer != wxID_NO )
1564 {
1565 activateFootprintTab( originalActive );
1566 return false;
1567 }
1568 }
1569
1570 activateFootprintTab( originalActive );
1571
1572 return true;
1573}
1574
1575
1577{
1578 m_tabsPanel->RefreshTabLabels();
1579}
1580
1581
1583{
1584 wxCHECK( aReplacement, /* void */ );
1585
1586 // Install the fresh frame-owned board and reset the tools against it before any tab board is
1587 // freed, so no ResetTools or repaint sees a freed or null m_pcb.
1588 installFootprintTabBoard( nullptr, aReplacement );
1589
1590 // Tear the strip down without re-prompting to save, since unsaved changes were already handled.
1591 // Suppress the host close callback and tab activation so CloseAll only does panel bookkeeping.
1592 std::function<bool( int )> savedCb = std::move( m_tabsPanel->onCloseTabRequested );
1593 m_tabsPanel->onCloseTabRequested =
1594 []( int )
1595 {
1596 return true;
1597 };
1598
1600 m_tabsPanel->CloseAll();
1602
1603 m_tabsPanel->onCloseTabRequested = std::move( savedCb );
1604
1605 wxASSERT_MSG( m_pcb == aReplacement,
1606 wxT( "m_pcb must alias the frame-owned replacement before contexts are freed" ) );
1607
1608 for( const std::unique_ptr<FOOTPRINT_EDITOR_TAB_CONTEXT>& ctx : m_tabContexts )
1610
1611 m_tabContexts.clear();
1612}
1613
1614
1616{
1617 m_tabsPanel->AdvanceTab( aForward );
1618}
1619
1620
1622{
1623 m_tabsPanel->CloseTab( m_tabsPanel->GetActiveTab() );
1624}
1625
1626
1631
1632
1637
1638
1640{
1641 wxFAIL_MSG( wxT( "Plotting not supported in Footprint Editor" ) );
1642
1644}
1645
1646
1648{
1649 wxFAIL_MSG( wxT( "Plotting not supported in Footprint Editor" ) );
1650}
1651
1652
1660
1661
1669
1670
1672{
1673 // Get our own settings; aCfg will be the PCBNEW_SETTINGS because we're part of the pcbnew
1674 // compile unit
1676
1677 if( cfg )
1678 {
1680
1682
1685
1687 m_selectionFilterPanel->SetCheckboxesFromFilter( cfg->m_SelectionFilter );
1688
1690
1691 for( auto& [source_name, dest_name] : cfg->m_DesignSettings.m_UserLayerNames )
1692 {
1693 wxString wx_source_name = source_name;
1694 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( LSET::NameToLayer( wx_source_name ) );
1695
1696 if( IsUserLayer( layer ) )
1697 GetBoard()->SetLayerName( layer, dest_name );
1698 }
1699
1700 }
1701}
1702
1703
1705{
1706 // Load canvas type from the FOOTPRINT_EDITOR_SETTINGS:
1708
1709 // If we had an OpenGL failure this session, use the fallback GAL but don't update the
1710 // user preference silently:
1711
1714}
1715
1716
1718{
1720
1721 // Get our own settings; aCfg will be the PCBNEW_SETTINGS because we're part of the pcbnew
1722 // compile unit
1724
1725 if( cfg )
1726 {
1728
1731 cfg->m_LibWidth = m_treePane->GetSize().x;
1732
1733 if( TOOL_MANAGER* toolMgr = GetToolManager() )
1734 {
1735 if( PCB_SELECTION_TOOL* selTool = toolMgr->GetTool<PCB_SELECTION_TOOL>() )
1736 cfg->m_SelectionFilter = selTool->GetFilter();
1737 }
1738
1740
1741 if( m_propertiesPanel )
1742 {
1743 cfg->m_AuiPanels.show_properties = m_propertiesPanel->IsShownOnScreen();
1745 cfg->m_AuiPanels.properties_splitter = m_propertiesPanel->SplitterProportion();
1746 }
1747
1749
1750 if( m_appearancePanel )
1751 {
1754 cfg->m_LayerPresets = m_appearancePanel->GetUserLayerPresets();
1755 cfg->m_ActiveLayerPreset = m_appearancePanel->GetActiveLayerPreset();
1756 }
1757
1758 cfg->m_OpenTabs.clear();
1759 cfg->m_ActiveTab.Clear();
1760
1761 const std::vector<EDITOR_TABS_MODEL::ENTRY>& entries = m_tabsPanel->Model().Entries();
1762
1763 for( size_t i = 0; i < m_tabContexts.size(); ++i )
1764 {
1765 const FOOTPRINT_EDITOR_TAB_CONTEXT* ctx = m_tabContexts[i].get();
1766
1767 // Instance and unsaved-import tabs are session-only and never persisted
1768 if( ctx->IsTransient() )
1769 continue;
1770
1771 const bool preview = i < entries.size() && entries[i].preview;
1772
1773 cfg->m_OpenTabs.push_back( { ctx->GetLib(), ctx->GetName(), preview } );
1774
1775 if( ctx == m_activeTab )
1776 cfg->m_ActiveTab = ctx->GetTabKey();
1777 }
1778 }
1779}
1780
1781
1782
1784{
1785 FOOTPRINT_EDITOR_SETTINGS* cfg = const_cast<FOOTPRINT_EDIT_FRAME*>( this )->GetSettings();
1786
1787 return cfg ? cfg->m_RotationAngle : ANGLE_90;
1788}
1789
1790
1791
1793{
1795 return ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME );
1796}
1797
1798
1800{
1801 static MAGNETIC_SETTINGS fallback;
1802
1804 return &cfg->m_MagneticItems;
1805
1806 return &fallback;
1807}
1808
1809
1810const BOX2I FOOTPRINT_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible ) const
1811{
1812 FOOTPRINT* footprint = GetBoard()->GetFirstFootprint();
1813
1814 if( footprint )
1815 {
1816 bool hasGraphicalItem = footprint->Pads().size() || footprint->Zones().size();
1817
1818 if( !hasGraphicalItem )
1819 {
1820 for( const BOARD_ITEM* item : footprint->GraphicalItems() )
1821 {
1822 if( item->Type() == PCB_TEXT_T || item->Type() == PCB_TEXTBOX_T )
1823 continue;
1824
1825 hasGraphicalItem = true;
1826 break;
1827 }
1828 }
1829
1830 if( hasGraphicalItem )
1831 {
1832 return footprint->GetBoundingBox( false );
1833 }
1834 else
1835 {
1836 BOX2I newFootprintBB( { 0, 0 }, { 0, 0 } );
1837 newFootprintBB.Inflate( pcbIUScale.mmToIU( 12 ) );
1838 return newFootprintBB;
1839 }
1840 }
1841
1842 return GetBoardBoundingBox( false );
1843}
1844
1845
1847{
1848 if( IsContentModified() )
1849 {
1850 wxString footprintName = GetBoard()->GetFirstFootprint()->GetReference();
1851 wxString msg = _( "Save changes to '%s' before closing?" );
1852
1853 if( !HandleUnsavedChanges( this, wxString::Format( msg, footprintName ),
1854 [&]() -> bool
1855 {
1856 return SaveFootprint( GetBoard()->GetFirstFootprint() );
1857 } ) )
1858 {
1859 return false;
1860 }
1861 }
1862
1863 if( doClose )
1864 Clear_Pcb( false );
1865
1866 return true;
1867}
1868
1869
1870bool FOOTPRINT_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
1871{
1872 // Shutdown blocks must be determined and vetoed as early as possible, before any modal prompt.
1873 // IsContentModified only sees the active tab, so also account for dirty inactive instance tabs.
1876 && aEvent.GetId() == wxEVT_QUERY_END_SESSION )
1877 {
1878 aEvent.Veto();
1879 return false;
1880 }
1881
1882 if( IsContentModified() )
1883 {
1884 wxString footprintName = GetBoard()->GetFirstFootprint()->GetFPID().GetLibItemName();
1885
1886 if( IsCurrentFPFromBoard() )
1887 footprintName = GetBoard()->GetFirstFootprint()->GetReference();
1888
1889 wxString msg = _( "Save changes to '%s' before closing?" );
1890
1891 if( !HandleUnsavedChanges( this, wxString::Format( msg, footprintName ),
1892 [&]() -> bool
1893 {
1894 return SaveFootprint( GetBoard()->GetFirstFootprint() );
1895 } ) )
1896 {
1897 aEvent.Veto();
1898 return false;
1899 }
1900 }
1901
1902 // Prompt for any dirty inactive instance tabs, which the active-tab check above misses.
1904 {
1905 aEvent.Veto();
1906 return false;
1907 }
1908
1909 PAD_TOOL* padTool = m_toolManager->GetTool<PAD_TOOL>();
1910
1911 if( padTool->InPadEditMode() )
1912 padTool->ExitPadEditMode();
1913
1914 // Save footprint tree column widths
1915 m_adapter->SaveSettings();
1916
1917 return PCB_BASE_EDIT_FRAME::canCloseWindow( aEvent );
1918}
1919
1920
1922{
1923 // No more vetos
1924 GetCanvas()->SetEventDispatcher( nullptr );
1926
1928
1929 if( GetLibTree() )
1931
1932 // Do not show the layer manager during closing to avoid flicker
1933 // on some platforms (Windows) that generate useless redraw of items in
1934 // the Layer Manager
1935 m_auimgr.GetPane( wxT( "LayersManager" ) ).Show( false );
1936 m_auimgr.GetPane( wxT( "SelectionFilter" ) ).Show( false );
1937
1938 Clear_Pcb( false );
1939}
1940
1941
1942void FOOTPRINT_EDIT_FRAME::OnExitKiCad( wxCommandEvent& event )
1943{
1944 Kiway().OnKiCadExit();
1945}
1946
1947
1949{
1950 Close();
1951}
1952
1953
1955{
1956 // call my base class
1958
1959 // We have 2 panes to update.
1960 // For some obscure reason, the AUI manager hides the first modified pane.
1961 // So force show panes
1962 wxAuiPaneInfo& tree_pane_info = m_auimgr.GetPane( m_treePane );
1963 bool tree_shown = tree_pane_info.IsShown();
1964 tree_pane_info.Caption( _( "Libraries" ) );
1965
1966 wxAuiPaneInfo& lm_pane_info = m_auimgr.GetPane( m_appearancePanel );
1967 bool lm_shown = lm_pane_info.IsShown();
1968 lm_pane_info.Caption( _( "Appearance" ) );
1969 wxAuiPaneInfo& sf_pane_info = m_auimgr.GetPane( m_selectionFilterPanel );
1970 sf_pane_info.Caption( _( "Selection Filter" ) );
1971
1972 // update the layer manager
1974
1975 // Now restore the visibility:
1976 lm_pane_info.Show( lm_shown );
1977 tree_pane_info.Show( tree_shown );
1978 m_auimgr.Update();
1979
1981
1982 UpdateTitle();
1983}
1984
1985
1987{
1989
1990 if( m_isClosing )
1991 return;
1992
1993 // An edit promotes the active tab from preview to permanent and flags it dirty. Reflect the
1994 // shared screen's dirty state onto the context and panel model so the tab shows bold + "*" and a
1995 // later library-open opens its own tab instead of replacing this one.
1996 if( m_activeTab )
1997 {
1998 m_activeTab->SetPreview( false );
1999 m_activeTab->SetModified( true );
2000
2001 if( int idx = m_tabsPanel->FindTab( m_activeTab->GetTabKey() ); idx >= 0 )
2002 m_tabsPanel->MarkModified( idx, true );
2003 }
2004
2005 Update3DView( true, true );
2007}
2008
2009
2011{
2012 SetTitle( _( "Footprint Editor" ) );
2013}
2014
2015
2017{
2018 m_appearancePanel->OnBoardChanged();
2019}
2020
2021
2023{
2027 m_propertiesPanel->UpdateData();
2028}
2029
2030
2032{
2034
2036 auto adapter = static_cast<FP_TREE_SYNCHRONIZING_ADAPTER*>( m_adapter.get() );
2037
2038 adapter->AddLibraries( this );
2039}
2040
2041
2042void FOOTPRINT_EDIT_FRAME::SyncLibraryTree( [[maybe_unused]] bool aProgress )
2043{
2044 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "FOOTPRINT_EDIT_FRAME::SyncLibraryTree enter" ) );
2045
2047 auto adapter = static_cast<FP_TREE_SYNCHRONIZING_ADAPTER*>( m_adapter.get() );
2048 LIB_ID target = GetTargetFPID();
2049 bool targetSelected = ( target == GetLibTree()->GetSelectedLibId() );
2050 std::vector<LIB_ID> expanded = GetLibTree()->GetExpandedLibraries();
2051
2052 // Unselect before syncing to avoid null reference in the adapter
2053 // if a selected item is removed during the sync
2054 GetLibTree()->Unselect();
2055
2056 // Sync the LIB_TREE to the FOOTPRINT_INFO list
2057 adapter->Sync( footprints );
2058
2059 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "FOOTPRINT_EDIT_FRAME::SyncLibraryTree Regenerate" ) );
2060 GetLibTree()->Regenerate( true );
2061
2062 // Sync() collapsed the tree, so re-expand the libraries that were open before it.
2063 for( const LIB_ID& libId : expanded )
2064 GetLibTree()->ExpandLibId( libId );
2065
2066 if( target.IsValid() )
2067 {
2068 if( adapter->FindItem( target ) )
2069 {
2070 if( targetSelected )
2071 GetLibTree()->SelectLibId( target );
2072 else
2073 GetLibTree()->CenterLibId( target );
2074 }
2075 else
2076 {
2077 // Try to focus on parent
2078 target.SetLibItemName( wxEmptyString );
2079 GetLibTree()->CenterLibId( target );
2080 }
2081 }
2082
2083 wxLogTrace( wxT( "KICAD_TABS_DBG" ), wxT( "FOOTPRINT_EDIT_FRAME::SyncLibraryTree exit" ) );
2084}
2085
2086
2091
2092
2094{
2095 GetLibTree()->SelectLibId( aLibID );
2096}
2097
2098
2100{
2101 m_appearancePanel->UpdateDisplayOptions();
2102}
2103
2104
2106{
2107 // Create the manager and dispatcher & route draw panel events to the dispatcher
2109 m_toolManager->SetEnvironment( GetBoard(), GetCanvas()->GetView(),
2110 GetCanvas()->GetViewControls(), config(), this );
2111 m_actions = new PCB_ACTIONS();
2113
2115
2116 m_toolManager->RegisterTool( new COMMON_CONTROL );
2117 m_toolManager->RegisterTool( new COMMON_TOOLS );
2118 m_toolManager->RegisterTool( new PCB_SELECTION_TOOL );
2119 m_toolManager->RegisterTool( new ZOOM_TOOL );
2120 m_toolManager->RegisterTool( new EDIT_TOOL );
2121 m_toolManager->RegisterTool( new PCB_EDIT_TABLE_TOOL );
2122 m_toolManager->RegisterTool( new PAD_TOOL );
2123 m_toolManager->RegisterTool( new DRAWING_TOOL );
2124 m_toolManager->RegisterTool( new PCB_POINT_EDITOR );
2125 m_toolManager->RegisterTool( new PCB_CONTROL ); // copy/paste
2126 m_toolManager->RegisterTool( new LIBRARY_EDITOR_CONTROL );
2127 m_toolManager->RegisterTool( new FOOTPRINT_EDITOR_CONTROL );
2128 m_toolManager->RegisterTool( new ALIGN_DISTRIBUTE_TOOL );
2129 m_toolManager->RegisterTool( new PCB_PICKER_TOOL );
2130 m_toolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
2131 m_toolManager->RegisterTool( new ARRAY_TOOL );
2132 m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
2133 m_toolManager->RegisterTool( new PCB_GROUP_TOOL );
2134 m_toolManager->RegisterTool( new CONSTRAINT_EDIT_TOOL );
2135 m_toolManager->RegisterTool( new CONVERT_TOOL );
2136 m_toolManager->RegisterTool( new PROPERTIES_TOOL );
2137 m_toolManager->RegisterTool( new EMBED_TOOL );
2138
2139 for( TOOL_BASE* tool : m_toolManager->Tools() )
2140 {
2141 if( PCB_TOOL_BASE* pcbTool = dynamic_cast<PCB_TOOL_BASE*>( tool ) )
2142 pcbTool->SetIsFootprintEditor( true );
2143 }
2144
2145 m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
2146 m_toolManager->InitTools();
2147
2148 m_toolManager->InvokeTool( "common.InteractiveSelection" );
2149
2150 // Load or reload wizard plugins in case they changed since the last time the frame opened
2151 // Because the board editor has also a plugin python menu,
2152 // call the PCB_EDIT_FRAME RunAction() if the board editor is running
2153 // Otherwise run the current RunAction().
2154 PCB_EDIT_FRAME* pcbframe = static_cast<PCB_EDIT_FRAME*>( Kiway().Player( FRAME_PCB_EDITOR, false ) );
2155
2156 if( pcbframe )
2158 else
2160}
2161
2162
2164{
2166
2167 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
2168 PCB_EDITOR_CONDITIONS cond( this );
2169
2170 wxASSERT( mgr );
2171
2172#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
2173#define CHECK( x ) ACTION_CONDITIONS().Check( x )
2174
2175 auto haveFootprintCond =
2176 [this]( const SELECTION& )
2177 {
2178 return GetBoard() && GetBoard()->GetFirstFootprint() != nullptr;
2179 };
2180
2181 auto footprintTargettedCond =
2182 [this]( const SELECTION& )
2183 {
2184 return !GetTargetFPID().GetLibItemName().empty();
2185 };
2186
2187 auto footprintSelectedInTreeCond =
2188 [this]( const SELECTION& )
2189 {
2191 return !sel.GetLibNickname().empty() && !sel.GetLibItemName().empty();
2192 };
2193
2194 const auto footprintFromBoardCond =
2195 [this]( const SELECTION& )
2196 {
2197 return IsCurrentFPFromBoard();
2198 };
2199
2200 auto pcbFrameExistsCond =
2201 [this]( const SELECTION& )
2202 {
2203 PCB_EDIT_FRAME* frame = dynamic_cast<PCB_EDIT_FRAME*>( Kiway().Player( FRAME_PCB_EDITOR, false ) );
2204
2205 return ( frame != nullptr );
2206 };
2207
2208 auto boardFootprintExistsCond =
2209 [this]( const SELECTION& )
2210 {
2211 PCB_EDIT_FRAME* frame = dynamic_cast<PCB_EDIT_FRAME*>( Kiway().Player( FRAME_PCB_EDITOR, false ) );
2212
2213 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
2214 bool canInsert = frame && editorFootprint && editorFootprint->GetLink() == niluuid;
2215
2216 // If the source was deleted, the footprint can inserted but not updated in the board.
2217 if( frame && editorFootprint && editorFootprint->GetLink() != niluuid )
2218 {
2219 BOARD* mainpcb = frame->GetBoard();
2220 canInsert = true;
2221
2222 // search if the source footprint was not deleted:
2223 for( FOOTPRINT* candidate : mainpcb->Footprints() )
2224 {
2225 if( editorFootprint->GetLink() == candidate->m_Uuid )
2226 {
2227 canInsert = false;
2228 break;
2229 }
2230 }
2231 }
2232
2233 return canInsert;
2234 };
2235
2236 // clang-format off
2237 mgr->SetConditions( ACTIONS::saveAs, ENABLE( footprintTargettedCond ) );
2240 mgr->SetConditions( PCB_ACTIONS::editLibFpInFpEditor,ENABLE( footprintFromBoardCond ) );
2241
2242 mgr->SetConditions( PCB_ACTIONS::saveFpToBoard, ENABLE( boardFootprintExistsCond ) );
2243 mgr->SetConditions( PCB_ACTIONS::loadFpFromBoard, ENABLE( pcbFrameExistsCond ) );
2244
2247
2250
2251 mgr->SetConditions( ACTIONS::cut, ENABLE( cond.HasItems() ) );
2252 mgr->SetConditions( ACTIONS::copy, ENABLE( cond.HasItems() ) );
2259
2266
2270
2275 // clang-format on
2276
2277 auto highContrastCond =
2278 [this]( const SELECTION& )
2279 {
2281 };
2282
2283 auto autoConstraintsCond = [this]( const SELECTION& )
2284 {
2286 return cfg && cfg->m_AutoConstraints;
2287 };
2288
2289 mgr->SetConditions( PCB_ACTIONS::toggleAutoConstraints, CHECK( autoConstraintsCond ) );
2290
2291 auto boardFlippedCond = [this]( const SELECTION& )
2292 {
2294 };
2295
2296 auto libraryTreeCond =
2297 [this](const SELECTION& )
2298 {
2299 return IsLibraryTreeShown();
2300 };
2301
2302 auto layerManagerCond =
2303 [this]( const SELECTION& )
2304 {
2305 return m_auimgr.GetPane( "LayersManager" ).IsShown();
2306 };
2307
2308 auto propertiesCond =
2309 [this] ( const SELECTION& )
2310 {
2311 return m_auimgr.GetPane( PropertiesPaneName() ).IsShown();
2312 };
2313
2314 mgr->SetConditions( ACTIONS::highContrastMode, CHECK( highContrastCond ) );
2315 mgr->SetConditions( PCB_ACTIONS::flipBoard, CHECK( boardFlippedCond ) );
2317
2318 mgr->SetConditions( ACTIONS::showLibraryTree, CHECK( libraryTreeCond ) );
2319 mgr->SetConditions( PCB_ACTIONS::showLayersManager, CHECK( layerManagerCond ) );
2320 mgr->SetConditions( ACTIONS::showProperties, CHECK( propertiesCond ) );
2321
2322 mgr->SetConditions( ACTIONS::print, ENABLE( haveFootprintCond ) );
2323 mgr->SetConditions( PCB_ACTIONS::exportFootprint, ENABLE( haveFootprintCond ) );
2324 mgr->SetConditions( PCB_ACTIONS::placeImportedGraphics, ENABLE( haveFootprintCond ) );
2325
2326 mgr->SetConditions( PCB_ACTIONS::footprintProperties, ENABLE( footprintSelectedInTreeCond || haveFootprintCond ) );
2327 mgr->SetConditions( PCB_ACTIONS::padTable, ENABLE( haveFootprintCond ) );
2328 mgr->SetConditions( PCB_ACTIONS::editTextAndGraphics, ENABLE( haveFootprintCond ) );
2329 mgr->SetConditions( PCB_ACTIONS::checkFootprint, ENABLE( haveFootprintCond ) );
2330 mgr->SetConditions( PCB_ACTIONS::repairFootprint, ENABLE( haveFootprintCond ) );
2331 mgr->SetConditions( PCB_ACTIONS::cleanupGraphics, ENABLE( haveFootprintCond ) );
2332 mgr->SetConditions( ACTIONS::showDatasheet, ENABLE( haveFootprintCond ) );
2333
2334 const auto isArcKeepCenterMode =
2335 [this]( const SELECTION& )
2336 {
2338 };
2339
2340 const auto isArcKeepEndpointMode =
2341 [this]( const SELECTION& )
2342 {
2344 };
2345
2346 const auto isArcKeepRadiusMode =
2347 [this]( const SELECTION& )
2348 {
2350 };
2351
2352 // clang-format off
2353 mgr->SetConditions( ACTIONS::pointEditorArcKeepCenter, CHECK( isArcKeepCenterMode ) );
2354 mgr->SetConditions( ACTIONS::pointEditorArcKeepEndpoint, CHECK( isArcKeepEndpointMode ) );
2355 mgr->SetConditions( ACTIONS::pointEditorArcKeepRadius, CHECK( isArcKeepRadiusMode ) );
2356 // clang-format on
2357
2358// Only enable a tool if the part is edtable
2359#define CURRENT_EDIT_TOOL( action ) \
2360 mgr->SetConditions( action, ACTION_CONDITIONS().Enable( haveFootprintCond ) \
2361 .Check( cond.CurrentTool( action ) ) )
2362
2389
2408
2409#undef CURRENT_EDIT_TOOL
2410#undef ENABLE
2411#undef CHECK
2412}
2413
2414
2416{
2418
2419 // Be sure the axis are enabled
2420 GetCanvas()->GetGAL()->SetAxesEnabled( true );
2421
2422 UpdateView();
2423
2424 // Ensure the m_Layers settings are using the canvas type:
2426}
2427
2428
2430{
2432 m_appearancePanel->CommonSettingsChanged( aFlags );
2433
2435 {
2436 GetGalDisplayOptions().ReadWindowSettings( cfg->m_Window );
2437
2438 GetBoard()->GetDesignSettings() = cfg->m_DesignSettings;
2440 }
2441
2445
2447
2448 if( aFlags & ENVVARS_CHANGED )
2449 SyncLibraryTree( true );
2450
2451 Layout();
2452 SendSizeEvent();
2453}
2454
2455
2456std::unique_ptr<GRID_HELPER> FOOTPRINT_EDIT_FRAME::MakeGridHelper()
2457{
2458 return std::make_unique<PCB_GRID_HELPER>( m_toolManager, GetMagneticItemsSettings() );
2459}
2460
2461
2463{
2464 LIB_ID id = GetLoadedFPID();
2465
2466 if( id.empty() )
2467 {
2468 DisplayErrorMessage( this, _( "No footprint selected." ) );
2469 return;
2470 }
2471
2472 wxFileName fn( id.GetLibItemName() );
2473 fn.SetExt( wxT( "png" ) );
2474
2475 wxString projectPath = wxPathOnly( Prj().GetProjectFullName() );
2476
2477 wxFileDialog dlg( this, _( "Export View as PNG" ), projectPath, fn.GetFullName(),
2478 FILEEXT::PngFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
2479
2481
2482 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetPath().IsEmpty() )
2483 return;
2484
2485 // calling wxYield is mandatory under Linux, after closing the file selector dialog
2486 // to refresh the screen before creating the PNG or JPEG image from screen
2487 wxYield();
2488 this->SaveCanvasImageToFile( dlg.GetPath(), BITMAP_TYPE::PNG );
2489}
const char * name
@ KEEP_ENDPOINTS_OR_START_DIRECTION
Whe editing endpoints, the other end remains in place.
@ KEEP_CENTER_ENDS_ADJUST_ANGLE
When editing endpoints, only the angle is adjusted.
@ KEEP_CENTER_ADJUST_ANGLE_RADIUS
When editing endpoints, the angle and radius are adjusted.
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:100
@ icon_modedit_32
@ icon_modedit_16
@ FPHOLDER
Definition board.h:365
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
static TOOL_ACTION toggleGrid
Definition actions.h:194
static TOOL_ACTION paste
Definition actions.h:76
static TOOL_ACTION unselectAll
Definition actions.h:79
static TOOL_ACTION revert
Definition actions.h:58
static TOOL_ACTION showLibraryTree
Definition actions.h:160
static TOOL_ACTION saveAs
Definition actions.h:55
static TOOL_ACTION copy
Definition actions.h:74
static TOOL_ACTION pluginsReload
Definition actions.h:292
static TOOL_ACTION selectSetLasso
Definition actions.h:217
static TOOL_ACTION selectSetRect
Set lasso selection mode.
Definition actions.h:216
static TOOL_ACTION group
Definition actions.h:235
static TOOL_ACTION pasteSpecial
Definition actions.h:77
static TOOL_ACTION showDatasheet
Definition actions.h:263
static TOOL_ACTION pointEditorArcKeepCenter
Definition actions.h:271
static TOOL_ACTION ungroup
Definition actions.h:236
static TOOL_ACTION toggleBoundingBoxes
Definition actions.h:153
static TOOL_ACTION pointEditorArcKeepRadius
Definition actions.h:273
static TOOL_ACTION undo
Definition actions.h:71
static TOOL_ACTION duplicate
Definition actions.h:80
static TOOL_ACTION highContrastMode
Definition actions.h:151
static TOOL_ACTION embeddedFiles
Definition actions.h:295
static TOOL_ACTION measureTool
Definition actions.h:248
static TOOL_ACTION doDelete
Definition actions.h:81
static TOOL_ACTION selectionTool
Definition actions.h:247
static TOOL_ACTION save
Definition actions.h:54
static TOOL_ACTION zoomFitScreen
Definition actions.h:138
static TOOL_ACTION redo
Definition actions.h:72
static TOOL_ACTION deleteTool
Definition actions.h:82
static TOOL_ACTION zoomTool
Definition actions.h:142
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
static TOOL_ACTION print
Definition actions.h:60
static TOOL_ACTION showProperties
Definition actions.h:262
static TOOL_ACTION cut
Definition actions.h:73
static TOOL_ACTION gridSetOrigin
Definition actions.h:191
static TOOL_ACTION ddAddLibrary
Definition actions.h:63
static TOOL_ACTION toggleGridOverrides
Definition actions.h:195
static TOOL_ACTION selectAll
Definition actions.h:78
static TOOL_ACTION pointEditorArcKeepEndpoint
Definition actions.h:272
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.
wxString m_ColorTheme
Active color theme name.
The array tool.
Definition array_tool.h:44
bool IsContentModified() const
Definition base_screen.h:56
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
BASE_SET & set(size_t pos)
Definition base_set.h:116
Container for design settings for a BOARD object.
std::map< std::string, wxString > m_UserLayerNames
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
void SetLocked(bool aLocked) override
Definition board_item.h:386
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:315
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:373
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1355
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition board.cpp:820
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:599
const FOOTPRINTS & Footprints() const
Definition board.h:421
void DeleteAllFootprints()
Remove all footprints from the deque and free the memory associated with them.
Definition board.cpp:1889
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1158
void SetUserUnits(EDA_UNITS aUnits)
Definition board.h:914
Color settings are a bit different than most of the settings objects in that there can be more than o...
Handle actions that are shared between different applications.
Handles action that are shared between different applications.
Interactive authoring of geometric constraints (issue #2329).
Tool responsible for drawing graphical elements like lines, arcs, circles, etc.
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
UNDO_REDO_CONTAINER m_undoList
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
virtual void UpdateToolbarControlSizes()
Update the sizes of any controls in the toolbars of the frame.
ACTION_TOOLBAR * m_tbRight
TOOLBAR_SETTINGS * m_toolbarSettings
wxAuiManager m_auimgr
virtual void RecreateToolbars()
UNDO_REDO_CONTAINER m_redoList
ACTION_TOOLBAR * m_tbLeft
virtual void OnSize(wxSizeEvent &aEvent)
virtual bool canCloseWindow(wxCloseEvent &aCloseEvent)
virtual void OnDropFiles(wxDropFilesEvent &aEvent)
Handle event fired when a file is dropped to the window.
std::map< const wxString, TOOL_ACTION * > m_acceptedExts
Associate file extensions with action to execute.
ACTION_TOOLBAR * m_tbTopMain
wxString m_aboutTitle
bool m_isClosing
Set by the close window event handler after frames are asked if they can close.
void ReCreateMenuBar()
Recreate the menu bar.
WX_INFOBAR * GetInfoBar()
EDA_DRAW_PANEL_GAL::GAL_TYPE m_canvasType
The current canvas type.
void OnSelectGrid(wxCommandEvent &event)
Command event handler for selecting grid sizes.
void setupUnits(APP_SETTINGS_BASE *aCfg)
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool SaveCanvasImageToFile(const wxString &aFileName, BITMAP_TYPE aBitmapType)
Save the current view as an image file.
virtual void SwitchCanvas(EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType)
Change the current rendering backend.
virtual void OnSelectZoom(wxCommandEvent &event)
Set the zoom factor when selected by the zoom list box in the main tool bar.
GAL_DISPLAY_OPTIONS_IMPL & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
static bool m_openGLFailureOccured
Has any failure occurred when switching to OpenGL in any EDA_DRAW_FRAME?
static const wxString PropertiesPaneName()
EDA_MSG_PANEL * m_messagePanel
void SetCanvas(EDA_DRAW_PANEL_GAL *aPanel)
virtual void SetScreen(BASE_SCREEN *aScreen)
virtual void UpdateMsgPanel()
Redraw the message panel.
EDA_DRAW_PANEL_GAL::GAL_TYPE loadCanvasTypeSetting()
Return the canvas type stored in the application settings.
PROPERTIES_PANEL * m_propertiesPanel
bool m_showBorderAndTitleBlock
static constexpr GAL_TYPE GAL_FALLBACK
void StopDrawing()
Prevent the GAL canvas from further drawing until it is recreated or StartDrawing() is called.
void ForceRefresh()
Force a redraw.
@ GAL_TYPE_OPENGL
OpenGL implementation.
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
void SetEventDispatcher(TOOL_DISPATCHER *aEventDispatcher)
Set a dispatcher that processes events and forwards them to tools.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:154
virtual void SetParentGroup(EDA_GROUP *aGroup)
Definition eda_item.h:113
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:89
Specialization of the wxAuiPaneInfo class for KiCad panels.
SELECTION_CONDITION NoActiveTool()
Create a functor testing if there are no tools active in the frame.
SELECTION_CONDITION BoundingBoxes()
SELECTION_CONDITION RedoAvailable()
Create a functor that tests if there are any items in the redo queue.
SELECTION_CONDITION CurrentTool(const TOOL_ACTION &aTool)
Create a functor testing if the specified tool is the current active tool in the frame.
virtual SELECTION_CONDITION UndoAvailable()
Create a functor that tests if there are any items in the undo queue.
SELECTION_CONDITION GridVisible()
Create a functor testing if the grid is visible in a frame.
SELECTION_CONDITION ContentModified()
Create a functor that tests if the content of the frame is modified.
SELECTION_CONDITION GridOverrides()
Create a functor testing if the grid overrides wires is enabled in a frame.
The tab strip plus the single shared GAL canvas.
VIEW_SNAPSHOT & ViewSnapshot()
std::vector< KIID > & SavedSelection()
Selection saved as resolved KIIDs, restored after the view is rebuilt.
UNDO_REDO_CONTAINER & RedoList()
UNDO_REDO_CONTAINER & UndoList()
The interactive edit tool.
Definition edit_tool.h:54
Module editor specific tools.
BOARD_DESIGN_SETTINGS m_DesignSettings
Only some of these settings are actually used for footprint editing.
wxString m_ActiveTab
Tab key ("lib:fpName") of the tab that was active when the editor last closed.
std::vector< LAYER_PRESET > m_LayerPresets
PCB_SELECTION_FILTER_OPTIONS m_SelectionFilter
One open footprint tab owning its fp-holder board, lent to the frame by raw pointer while active.
std::map< KIID, KIID > & BoardFootprintUuids()
Editor-to-board UUID remap captured at load, used by SaveFootprintToBoard to restore the original boa...
bool IsTransient() const
True for a tab that is session-only and never persisted.
BOARD * GetBoard() const
The fp-holder board owned by this context.
wxString GetDisplayName() const override
Short label shown on the tab.
static wxString MakeInstanceTabKey(const KIID &aSourceUuid)
De-duplication key for a placed board footprint, in a namespace disjoint from library keys.
static std::unique_ptr< FOOTPRINT_EDITOR_TAB_CONTEXT > MakeUnsaved(std::unique_ptr< BOARD > aBoard)
Construct a tab for an imported footprint that has no library identity yet.
const wxString & GetFootprintNameWhenLoaded() const
bool IsModified() const override
True only when dirty and the board actually holds a footprint to edit.
FOOTPRINT * GetOriginalFootprintCopy() const
Baseline clone captured at load, used to detect edits and to revert.
wxString GetTabKey() const override
Stable identity for persistence and de-duplication.
void CloseFootprintEditor(wxCommandEvent &Event)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const override
Return the BOARD_DESIGN_SETTINGS for the open project.
void setupUIConditions() override
Setup the UI conditions for the various actions and their controls in this frame.
void ActivateGalCanvas() override
Use to start up the GAL drawing canvas.
void detachTabsForFullClear(BOARD *aReplacement)
Install aReplacement as the active document non-destructively, then drop every tab context and free t...
FOOTPRINT_EDITOR_TAB_CONTEXT * createUnsavedFootprintTab()
Open a session-only tab for an imported footprint over a fresh fp-holder board and make it the active...
void HardRedraw() override
Refresh the library tree and redraw the window.
void updateInfoBar()
Update the infobar for the currently-active tab.
static const wxChar * GetFootprintEditorFrameName()
void SyncLibraryTree(bool aProgress)
Synchronize the footprint library tree to the current state of the footprint library table.
BOARD * m_protectedBorrowedBoard
Board still owned by a displaced preview context while AddTab() synchronously installs its successor.
EDIT_NOTICE
The infobar notice that applies to the footprint being edited.
@ READ_ONLY_LIB
Editing a footprint whose library cannot be written.
@ FROM_BOARD
Editing a footprint pulled off a board, so saving updates the board only.
@ NONE
Nothing to report, so any existing notice is dismissed.
FOOTPRINT_EDITOR_TAB_CONTEXT * m_activeTab
void OnSaveFootprintAsPng(wxCommandEvent &event)
bool SaveFootprintAs(FOOTPRINT *aFootprint)
void FocusLibraryTreeInput() override
bool promptToSaveInactiveTransientTabs()
Prompt to save each dirty session-only tab that is not the active one, since the active tab's unsaved...
BOARD_ITEM_CONTAINER * GetModel() const override
void ReCreateLayerBox(bool aForceResizeToolbar=true)
Re create the layer Box by clearing the old list, and building a new one from the new layers names an...
LIB_TREE * GetLibTree() const override
bool canCloseWindow(wxCloseEvent &Event) override
void UpdateMsgPanel() override
Redraw the message panel.
LIB_ID GetTargetFPID() const
Return the LIB_ID of the part selected in the footprint tree, or the loaded part if there is no selec...
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
APP_SETTINGS_BASE * config() const override
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
void refreshFootprintTabState()
Re-query and re-render the tab labels from the active context's modified state.
EDITOR_TABS_PANEL * m_tabsPanel
FOOTPRINT_EDITOR_TAB_CONTEXT * findOrCreateFootprintInstanceTab(FOOTPRINT *aBoardFootprint)
Find or create the instance tab for a placed board footprint and make it the active tab.
void detachActiveFootprintTab()
Snapshot the active tab's view/selection, fold the dirty state back into it, and clear m_activeTab.
void SetPlotSettings(const PCB_PLOT_PARAMS &aSettings) override
bool SaveFootprint(FOOTPRINT *aFootprint)
Save in an existing library a given footprint.
void OnTabCharHook(wxKeyEvent &aEvent)
Cycle footprint tabs from the CHAR_HOOK stream, since GTK cannot register WXK_TAB as a menu accelerat...
void CloseFootprintTab(const LIB_ID &aFPID)
Close the open tab for aFPID, if any, without prompting and leaving the other tabs open.
std::unique_ptr< API_HANDLER_FOOTPRINT > m_apiHandler
void initLibraryTree()
Make sure the footprint info list is loaded (with a progress dialog) and then initialize the footprin...
bool m_silentFootprintTabClose
While true, promptAndCloseFootprintTab() skips the unsaved-changes dialog.
static EDIT_NOTICE editNoticeFor(const FOOTPRINT *aFootprint, bool aIsFromBoard, const std::function< bool(const wxString &)> &aIsLibWritable)
Decide which infobar notice applies to aFootprint.
std::map< KIID, KIID > m_boardFootprintUuids
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
std::unique_ptr< API_HANDLER_COMMON > m_apiHandlerCommon
void ShowChangedLanguage() override
Update visible items after a language change.
void resolveCanvasType() override
Determines the Canvas type to load (with prompt if required) and initializes m_canvasType.
void CommonSettingsChanged(int aFlags) override
Called after the preferences dialog is run.
bool IsContentModified() const override
Get if any footprints or libraries have been modified but not saved.
void UpdateUserInterface()
Update the layer manager and other widgets from the board setup (layer and items visibility,...
wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > m_adapter
bool IsLibraryTreeShown() const override
FOOTPRINT_EDITOR_SETTINGS * m_editorSettings
const BOX2I GetDocumentExtents(bool aIncludeAllVisible=true) const override
Return bounding box of document with option to not include some items.
bool Clear_Pcb(bool doAskAboutUnsavedChanges)
Delete all and reinitialize the current board.
Definition initpcb.cpp:104
void RenameFootprintTab(const LIB_ID &aOldId, const LIB_ID &aNewId)
Update the open tab for aOldId, if any, to the renamed footprint aNewId so its label and key track th...
static FOOTPRINT_EDITOR_TAB_CONTEXT * placeReusedTabContext(std::vector< std::unique_ptr< FOOTPRINT_EDITOR_TAB_CONTEXT > > &aContexts, int aSlot, std::unique_ptr< FOOTPRINT_EDITOR_TAB_CONTEXT > aNew, const std::function< void(const FOOTPRINT_EDITOR_TAB_CONTEXT &)> &aInstallSuccessor)
Replace the tab context at aSlot with aNew, running aInstallSuccessor before the displaced context is...
void borrowBoardNonDestructive(BOARD *aBoard)
Swap the frame's borrowed board pointer to aBoard without deleting the previous board,...
FOOTPRINT_EDIT_FRAME(KIWAY *aKiway, wxWindow *aParent)
protected so only friend PCB::IFACE::CreateWindow() can act as sole factory.
SELECTION & GetCurrentSelection() override
Get the current selection from the canvas area.
void AdvanceFootprintTab(bool aForward)
Advance the active tab forward or backward in MRU order.
bool CanCloseFPFromBoard(bool doClose)
void activateFootprintTab(FOOTPRINT_EDITOR_TAB_CONTEXT *aCtx)
Make aCtx the active tab, borrowing its board without deleting the outgoing one.
void freeFootprintTabUndoRedo(FOOTPRINT_EDITOR_TAB_CONTEXT &aCtx)
Free the transient board items a detached context's lists own before it is destroyed,...
void SetActiveLayer(PCB_LAYER_ID aLayer) override
void AddFootprintToBoard(FOOTPRINT *aFootprint) override
Override from PCB_BASE_EDIT_FRAME which adds a footprint to the editor's dummy board,...
bool activeBoardOwnedByTab() const
True when a tab context owns the frame's borrowed board, so the frame must not delete it.
void OnModify() override
Must be called after a footprint change in order to set the "modify" flag of the current screen and p...
std::vector< std::unique_ptr< FOOTPRINT_EDITOR_TAB_CONTEXT > > m_tabContexts
void CloseActiveFootprintTab()
Request closing the active tab, prompting to save if it is modified.
FOOTPRINT_TREE_PANE * m_treePane
std::unique_ptr< GRID_HELPER > MakeGridHelper() override
void OnDisplayOptionsChanged() override
void FocusOnLibID(const LIB_ID &aLibID)
const PCB_PLOT_PARAMS & GetPlotSettings() const override
Return the PCB_PLOT_PARAMS for the BOARD owned by this frame.
bool m_suppressTabActivation
Set while a full clear tears the tab strip down so the panel's close-driven re-activation does not re...
static bool prepareFootprintTabHandoff(FOOTPRINT *aFootprint, bool aHasTabs)
Decide whether aFootprint opens in its own tab and, if so, detach it from the board it arrived parent...
std::unique_ptr< FOOTPRINT > m_originalFootprintCopy
void ReloadFootprint(FOOTPRINT *aFootprint) override
Override from PCB_BASE_FRAME which reloads the footprint from the library without setting the footpri...
EDA_ANGLE GetRotationAngle() const override
Return the angle used for rotate operations.
void RefreshLibraryTree()
Redisplay the library tree.
void installFootprintTabBoard(FOOTPRINT_EDITOR_TAB_CONTEXT *aCtx, BOARD *aBoard)
Install aBoard as the active document non-destructively, wiring the tool environment and resetting th...
void OnExitKiCad(wxCommandEvent &aEvent)
bool promptAndCloseFootprintTab(int aIdx)
Prompt to save if needed, then drop the tab context at aIdx.
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
MAGNETIC_SETTINGS * GetMagneticItemsSettings() override
bool hasDirtyInactiveTransientTabs() const
True if any non-active session-only tab has unsaved edits.
FOOTPRINT_EDITOR_SETTINGS * GetSettings()
FOOTPRINT_EDITOR_TAB_CONTEXT * findOrCreateFootprintTab(const LIB_ID &aLibId, bool aAsPreview)
Find or create the tab for aLibId over its own fp-holder board and make it the active tab.
void SwitchCanvas(EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType) override
Switch the currently used canvas (Cairo / OpenGL).
void freeUndoRedoCommandsWithItems(UNDO_REDO_CONTAINER &aUndo, UNDO_REDO_CONTAINER &aRedo)
Free both the transient board items and the command wrappers in the given lists.
void installFootprintOnActiveBoard(FOOTPRINT *aFootprint)
Replace the active board's footprint with aFootprint and re-point the file watcher at it.
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Helper to retrieve the current color settings.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
bool IsFootprintLibWritable(const wxString &aNickname)
Return true if the library given by aNickname is writable.
Footprint Editor pane with footprint library tree.
bool FixUuids()
Old footprints do not always have a valid UUID (some can be set to null uuid) However null UUIDs,...
void SetPosition(const VECTOR2I &aPos) override
void SetLink(const KIID &aLink)
Definition footprint.h:1192
void SetLocked(bool isLocked) override
Set the #MODULE_is_LOCKED bit in the m_ModuleStatus.
Definition footprint.h:660
ZONES & Zones()
Definition footprint.h:381
void SetOrientation(const EDA_ANGLE &aNewAngle)
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
EDA_ITEM * Clone() const override
Invoke a function on all children.
std::deque< PAD * > & Pads()
Definition footprint.h:375
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition footprint.h:420
const LIB_ID & GetFPID() const
Definition footprint.h:444
const LSET & GetStackupLayers() const
Definition footprint.h:508
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
void ClearAllNets()
Clear (i.e.
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
KIID GetLink() const
Definition footprint.h:1191
const wxString & GetReference() const
Definition footprint.h:857
FOOTPRINT_STACKUP GetStackupMode() const
Definition footprint.h:501
VECTOR2I GetPosition() const override
Definition footprint.h:406
DRAWINGS & GraphicalItems()
Definition footprint.h:378
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void AddLibraries(EDA_BASE_FRAME *aParent)
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(FOOTPRINT_EDIT_FRAME *aFrame, FOOTPRINT_LIBRARY_ADAPTER *aLibs)
void ReadWindowSettings(WINDOW_SETTINGS &aCfg)
Read GAL config options from application-level config.
void RegisterHandler(API_HANDLER *aHandler)
Adds a new request handler to the server.
void DeregisterHandler(API_HANDLER *aHandler)
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:38
int ShowModal() override
Definition kidialog.cpp:89
bool m_axesEnabled
Crosshair drawing mode.
void SetAxesEnabled(bool aAxesEnabled)
Enable drawing the axes.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition pcb_view.cpp:87
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
double GetScale() const
Definition view.h:281
const VECTOR2D & GetCenter() const
Return the center point of this VIEW (in world space coordinates).
Definition view.h:351
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition view.cpp:637
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition view.cpp:844
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:405
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition view.cpp:663
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition view.h:657
Definition kiid.h:46
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:311
void OnKiCadExit()
Definition kiway.cpp:786
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:388
Module editor specific tools.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition lib_id.cpp:124
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition lib_id.h:108
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:83
void RefreshLibTree()
Refresh the tree (mainly to update highlighting and asterisking)
Definition lib_tree.cpp:493
void CenterLibId(const LIB_ID &aLibId)
Ensure that an item is visible (preferably centered).
Definition lib_tree.cpp:383
void ShutdownPreviews()
Definition lib_tree.cpp:283
void ShowChangedLanguage()
Definition lib_tree.cpp:300
std::vector< LIB_ID > GetExpandedLibraries() const
Definition lib_tree.cpp:403
void SelectLibId(const LIB_ID &aLibId)
Select an item in the tree widget.
Definition lib_tree.cpp:371
LIB_TREE_MODEL_ADAPTER::SORT_MODE GetSortMode() const
Definition lib_tree.h:154
void Unselect()
Unselect currently selected item in wxDataViewCtrl.
Definition lib_tree.cpp:389
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:310
void ExpandLibId(const LIB_ID &aLibId)
Expand and item i the tree widget.
Definition lib_tree.cpp:397
void Regenerate(bool aKeepState)
Regenerate the tree.
Definition lib_tree.cpp:475
void SetSortMode(LIB_TREE_MODEL_ADAPTER::SORT_MODE aMode)
Save/restore the sorting mode.
Definition lib_tree.h:153
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
static const LSET & UserMask()
Definition lset.cpp:686
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
Definition lset.cpp:113
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition lset.cpp:672
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
Definition lset.cpp:700
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:184
void ExitPadEditMode()
Definition pad_tool.cpp:802
bool InPadEditMode()
Definition pad_tool.h:59
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:75
Gather all the actions that are shared by tools.
Definition pcb_actions.h:49
static TOOL_ACTION drawRuleArea
static TOOL_ACTION drawBezier
static TOOL_ACTION placeText
static TOOL_ACTION drawOrthogonalDimension
static TOOL_ACTION drawRectangle
static TOOL_ACTION setAnchor
static TOOL_ACTION padDisplayMode
static TOOL_ACTION placeReferenceImage
static TOOL_ACTION showLayersManager
static TOOL_ACTION addConstraintVertical
static TOOL_ACTION drawCircle
static TOOL_ACTION mirrorH
Mirroring of selected items.
static TOOL_ACTION exportFootprint
static TOOL_ACTION drawEllipseArc
static TOOL_ACTION drawTable
static TOOL_ACTION drawTextBox
static TOOL_ACTION addConstraintPerpendicular
static TOOL_ACTION drawPolygon
static TOOL_ACTION placePad
Activation of the drawing tool (placing a PAD)
static TOOL_ACTION drawRadialDimension
static TOOL_ACTION padTable
static TOOL_ACTION editTextAndGraphics
static TOOL_ACTION drawLeader
static TOOL_ACTION addConstraintAngular
static TOOL_ACTION addConstraintArcAngle
static TOOL_ACTION angleSnapModeChanged
Notification event when angle mode changes.
static TOOL_ACTION addConstraintHorizontal
static TOOL_ACTION drawEllipse
static TOOL_ACTION ddImportFootprint
static TOOL_ACTION placeImportedGraphics
static TOOL_ACTION addConstraintCollinear
static TOOL_ACTION drawArc
static TOOL_ACTION graphicsOutlines
Display footprint graphics as outlines.
static TOOL_ACTION addConstraintEqualRadius
static TOOL_ACTION addConstraintTangent
static TOOL_ACTION loadFpFromBoard
static TOOL_ACTION drawCenterDimension
static TOOL_ACTION addConstraintFixedLength
static TOOL_ACTION footprintProperties
static TOOL_ACTION flipBoard
static TOOL_ACTION toggleAutoConstraints
Toggle authoring constraints automatically while drawing.
static TOOL_ACTION textOutlines
Display texts as lines.
static TOOL_ACTION checkFootprint
static TOOL_ACTION placeBarcode
static TOOL_ACTION placePoint
static TOOL_ACTION editLibFpInFpEditor
static TOOL_ACTION addConstraintSymmetric
static TOOL_ACTION addConstraintFixedPosition
Ground a point, and the cluster holding it.
static TOOL_ACTION mirrorV
static TOOL_ACTION addConstraintPointOnLine
static TOOL_ACTION repairFootprint
static TOOL_ACTION saveFpToBoard
static TOOL_ACTION addConstraintCoincident
static TOOL_ACTION drawLine
static TOOL_ACTION cleanupGraphics
static TOOL_ACTION rotateCw
Rotation of selected objects.
static TOOL_ACTION rotateCcw
static TOOL_ACTION addConstraintParallel
static TOOL_ACTION drawAlignedDimension
static TOOL_ACTION addConstraintFixedRadius
static TOOL_ACTION addConstraintEqualLength
static TOOL_ACTION addConstraintMidpoint
static TOOL_ACTION addConstraintConcentric
void ClearListAndDeleteItems(PICKED_ITEMS_LIST *aList)
virtual void SetBoard(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr) override
Set the #m_Pcb member in such as way as to ensure deleting any previous BOARD.
void configureToolbars() override
PCB_BASE_EDIT_FRAME(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName)
APPEARANCE_CONTROLS * m_appearancePanel
PANEL_SELECTION_FILTER * m_selectionFilterPanel
void ActivateGalCanvas() override
Set the #m_Pcb member in such as way as to ensure deleting any previous BOARD.
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
virtual const PCB_PLOT_PARAMS & GetPlotSettings() const
Return the PCB_PLOT_PARAMS for the BOARD owned by this frame.
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
void setFPWatcher(FOOTPRINT *aFootprint)
Create or removes a watcher on the specified footprint.
PCBNEW_SETTINGS * GetPcbNewSettings() const
void OnModify() override
Must be called after a change in order to set the "modify" flag and update other data structures and ...
const PAGE_INFO & GetPageSettings() const override
BOX2I GetBoardBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
EDA_ITEM * ResolveItem(const KIID &aId, bool aAllowNullptrReturn=false) const override
Fetch an item by KIID.
FOOTPRINT * LoadFootprint(const LIB_ID &aFootprintId)
Attempt to load aFootprintId from the footprint library table.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual void SetPageSettings(const PAGE_INFO &aPageSettings) override
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
virtual void AddFootprintToBoard(FOOTPRINT *aFootprint)
Add the given footprint to the board.
PCB_DISPLAY_OPTIONS m_displayOptions
FOOTPRINT_EDITOR_SETTINGS * GetFootprintEditorSettings() const
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
Handle actions that are shared between different frames in PcbNew.
Definition pcb_control.h:43
bool m_FlipBoardView
true if the board is flipped to show the mirrored view
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
void UpdateColors()
Update the color settings in the painter and GAL.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void DisplayBoard(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr)
Add all items from the current board to the VIEW, so they can be displayed by GAL.
Group generic conditions for PCB editor states.
SELECTION_CONDITION PadFillDisplay()
Create a functor that tests if the frame fills the pads.
SELECTION_CONDITION HasItems()
Create a functor that tests if there are items in the board.
SELECTION_CONDITION GraphicsFillDisplay()
Create a functor that tests if the frame fills graphics items.
SELECTION_CONDITION TextFillDisplay()
Create a functor that tests if the frame fills text items.
The main frame for Pcbnew.
Generic tool for picking an item.
Parameters and options when plotting/printing a board.
Tool that displays edit points allowing to modify items by dragging the points.
The selection tool: currently supports:
void select(EDA_ITEM *aItem) override
Take necessary action mark an item as selected.
Tool useful for viewing footprints.
KICAD_API_SERVER & GetApiServer()
Definition pgm_base.h:142
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:124
A holder to handle information on schematic or board items.
The interactive edit tool.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
@ PCB_FOOTPRINT_EDITOR_FP_NAME
Definition project.h:226
@ PCB_FOOTPRINT_EDITOR_LIB_NICKNAME
Definition project.h:227
virtual void SetRString(RSTRING_T aStringId, const wxString &aString)
Store a "retained string", which is any session and project specific string identified in enum RSTRIN...
Definition project.cpp:355
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition project.cpp:366
Action handler for the Properties panel.
RAII class that sets an value at construction and resets it to the original value at destruction.
static SELECTION_CONDITION HasType(KICAD_T aType)
Create a functor that tests if among the selected items there is at least one of a given type.
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
T * GetAppSettings(const char *aFilename)
Return a handle to the a given settings by type.
TOOL_MANAGER * m_toolManager
TOOL_DISPATCHER * m_toolDispatcher
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
ACTIONS * m_actions
Base abstract interface for all kinds of tools.
Definition tool_base.h:62
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
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.
void ResetTools(TOOL_BASE::RESET_REASON aReason)
Reset all tools (i.e.
A holder to handle a list of undo (or redo) commands.
std::vector< PICKED_ITEMS_LIST * > m_CommandsList
EDA_UNITS GetUserUnits() const
bool empty() const
Definition utf8.h:105
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:77
bool HasCloseButton() const
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:146
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
#define CHECK(x)
#define ENABLE(x)
static bool empty(const wxTextEntryBase *aCtrl)
@ DRCE_MISSING_COURTYARD
Definition drc_item.h:64
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
#define KICAD_DEFAULT_DRAWFRAME_STYLE
#define FOOTPRINT_EDIT_FRAME_NAME
@ RECURSE
Definition eda_item.h:49
FOOTPRINT_STACKUP
Definition footprint.h:143
@ EXPAND_INNER_LAYERS
The 'normal' stackup handling, where there is a single inner layer (In1) and rule areas using it expa...
Definition footprint.h:148
@ CUSTOM_LAYERS
Stackup handling where the footprint can have any number of copper layers, and objects on those layer...
Definition footprint.h:153
static std::unique_ptr< BOARD > makeFpHolderBoard()
#define CURRENT_EDIT_TOOL(action)
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
a few functions useful in geometry calculations.
static const std::string KiCadFootprintLibPathExtension
static const std::string KiCadFootprintFileExtension
static wxString PngFileWildcard()
@ ID_ON_GRID_SELECT
Definition id.h:113
@ ID_ON_ZOOM_SELECT
Definition id.h:112
PROJECT & Prj()
Definition kicad.cpp:728
EVT_MENU(ID_COMPARE_PROJECT_BRANCHES, KICAD_MANAGER_FRAME::OnCompareProjectBranches) KICAD_MANAGER_FRAME
TAB_VISUAL_STATE ResolveTabVisualState(bool aPreview, bool aModified)
Resolve a tab's decorations from its document state flags.
KIID niluuid(0)
bool IsUserLayer(PCB_LAYER_ID aLayerId)
Test whether a layer is a non copper and a non tech layer.
Definition layer_ids.h:765
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ B_Cu
Definition layer_ids.h:61
@ F_SilkS
Definition layer_ids.h:96
@ In1_Cu
Definition layer_ids.h:62
@ F_Cu
Definition layer_ids.h:60
This file contains miscellaneous commonly used macros and functions.
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:34
void SetShutdownBlockReason(wxWindow *aWindow, const wxString &aReason)
Sets the block reason why the window/application is preventing OS shutdown.
Definition unix/app.cpp:102
bool SupportsShutdownBlockReason()
Whether or not the window supports setting a shutdown block reason.
Definition unix/app.cpp:91
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:521
#define _HKI(x)
Definition page_info.cpp:40
@ ID_FPEDIT_SAVE_PNG
Definition pcbnew_id.h:81
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
@ RPT_SEVERITY_WARNING
#define DEFAULT_THEME
T * GetToolbarSettings(const wxString &aFilename)
T * GetAppSettings(const char *aFilename)
KIWAY Kiway(KFCTL_STANDALONE)
wxString UnescapeString(const wxString &aSource)
View snapshot captured on detach, restored on activate.
One open tab persisted across sessions.
Visual decorations derived from document state: preview is italic, modified is bold with a leading as...
#define ENVVARS_CHANGED
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:104
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:86
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:85
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:80
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
Definition of file extensions used in Kicad.
void SetAuiPaneSize(wxAuiManager &aManager, wxAuiPaneInfo &aPane, int aWidth, int aHeight)
Sets the size of an AUI pane, working around http://trac.wxwidgets.org/ticket/13180.