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 <dick@softplc.com>
6 * Copyright (C) 2015-2016 Wayne Stambaugh <stambaughw@gmail.com>
7 * Copyright (C) 1992-2021 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 along
20 * with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "tools/convert_tool.h"
24 #include "tools/drawing_tool.h"
25 #include "tools/edit_tool.h"
26 #include "tools/footprint_editor_control.h"
27 #include "tools/pad_tool.h"
28 #include "tools/pcb_actions.h"
29 #include "tools/pcb_control.h"
30 #include "tools/pcb_picker_tool.h"
31 #include "tools/placement_tool.h"
32 #include "tools/pcb_point_editor.h"
33 #include "tools/pcb_selection_tool.h"
34 #include <python/scripting/pcb_scripting_tool.h>
35 #include <3d_viewer/eda_3d_viewer_frame.h>
36 #include <bitmaps.h>
37 #include <board.h>
38 #include <footprint.h>
39 #include <confirm.h>
40 #include <dialogs/panel_fp_editor_color_settings.h>
41 #include <dialogs/panel_fp_editor_defaults.h>
42 #include <dialogs/panel_display_options.h>
43 #include <dialogs/panel_edit_options.h>
44 #include <footprint_edit_frame.h>
45 #include <footprint_editor_settings.h>
46 #include <footprint_info_impl.h>
47 #include <footprint_tree_pane.h>
48 #include <fp_lib_table.h>
49 #include <plugins/kicad/pcb_plugin.h>
50 #include <kiface_base.h>
51 #include <kiplatform/app.h>
52 #include <kiway.h>
53 #include <macros.h>
54 #include <panel_hotkeys_editor.h>
55 #include <pcb_draw_panel_gal.h>
56 #include <pcb_edit_frame.h>
57 #include <pcbnew.h>
58 #include <pcbnew_id.h>
59 #include <pgm_base.h>
60 #include <project.h>
61 #include <settings/settings_manager.h>
62 #include <tool/action_toolbar.h>
63 #include <tool/common_control.h>
64 #include <tool/common_tools.h>
65 #include <tool/selection.h>
66 #include <tool/tool_dispatcher.h>
67 #include <tool/tool_manager.h>
68 #include <tool/zoom_tool.h>
69 #include <tools/pcb_editor_conditions.h>
70 #include <tools/pcb_viewer_tools.h>
71 #include <tools/group_tool.h>
72 #include <tools/position_relative_tool.h>
73 #include <widgets/appearance_controls.h>
74 #include <widgets/infobar.h>
75 #include <widgets/lib_tree.h>
76 #include <widgets/paged_dialog.h>
77 #include <widgets/panel_selection_filter.h>
78 #include <widgets/wx_progress_reporters.h>
79 #include <wildcards_and_files_ext.h>
80 #include <wx/filedlg.h>
81 #include <wx/treebook.h>
82 #include <widgets/wx_aui_utils.h>
83
BEGIN_EVENT_TABLE(FOOTPRINT_EDIT_FRAME,PCB_BASE_FRAME)84 BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
85 EVT_MENU( wxID_CLOSE, FOOTPRINT_EDIT_FRAME::CloseFootprintEditor )
86 EVT_MENU( wxID_EXIT, FOOTPRINT_EDIT_FRAME::OnExitKiCad )
87
88 EVT_SIZE( FOOTPRINT_EDIT_FRAME::OnSize )
89
90 EVT_CHOICE( ID_ON_ZOOM_SELECT, FOOTPRINT_EDIT_FRAME::OnSelectZoom )
91 EVT_CHOICE( ID_ON_GRID_SELECT, FOOTPRINT_EDIT_FRAME::OnSelectGrid )
92
93 EVT_TOOL( ID_FPEDIT_SAVE_PNG, FOOTPRINT_EDIT_FRAME::OnSaveFootprintAsPng )
94
95 EVT_TOOL( ID_LOAD_FOOTPRINT_FROM_BOARD, FOOTPRINT_EDIT_FRAME::LoadFootprintFromBoard )
96 EVT_TOOL( ID_ADD_FOOTPRINT_TO_BOARD, FOOTPRINT_EDIT_FRAME::SaveFootprintToBoard )
97
98 // Horizontal toolbar
99 EVT_MENU( ID_GRID_SETTINGS, FOOTPRINT_EDIT_FRAME::OnGridSettings )
100 EVT_COMBOBOX( ID_TOOLBARH_PCB_SELECT_LAYER, FOOTPRINT_EDIT_FRAME::SelectLayer )
101
102 // UI update events.
103 EVT_UPDATE_UI( ID_LOAD_FOOTPRINT_FROM_BOARD,
104 FOOTPRINT_EDIT_FRAME::OnUpdateLoadFootprintFromBoard )
105 EVT_UPDATE_UI( ID_ADD_FOOTPRINT_TO_BOARD,
106 FOOTPRINT_EDIT_FRAME::OnUpdateSaveFootprintToBoard )
107 EVT_UPDATE_UI( ID_TOOLBARH_PCB_SELECT_LAYER, FOOTPRINT_EDIT_FRAME::OnUpdateLayerSelectBox )
108 END_EVENT_TABLE()
109
110
111 FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
112 PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_FOOTPRINT_EDITOR, wxEmptyString,
113 wxDefaultPosition, wxDefaultSize,
114 KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintEditorFrameName() ),
115 m_show_layer_manager_tools( true )
116 {
117 m_showBorderAndTitleBlock = false; // true to show the frame references
118 m_aboutTitle = _( "KiCad Footprint Editor" );
119 m_selLayerBox = nullptr;
120 m_editorSettings = nullptr;
121
122 // Give an icon
123 wxIcon icon;
124 wxIconBundle icon_bundle;
125
126 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
127 icon_bundle.AddIcon( icon );
128 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit_32 ) );
129 icon_bundle.AddIcon( icon );
130 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit_16 ) );
131 icon_bundle.AddIcon( icon );
132
133 SetIcons( icon_bundle );
134
135 // Create GAL canvas
136 m_canvasType = loadCanvasTypeSetting();
137
138 PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_frameSize,
139 GetGalDisplayOptions(), m_canvasType );
140 SetCanvas( drawPanel );
141 SetBoard( new BOARD() );
142
143 // This board will only be used to hold a footprint for editing
144 GetBoard()->SetBoardUse( BOARD_USE::FPHOLDER );
145
146 // In Footprint Editor, the default net clearance is not known (it depends on the actual
147 // board). So we do not show the default clearance, by setting it to 0. The footprint or
148 // pad specific clearance will be shown.
149 GetBoard()->GetDesignSettings().GetDefault()->SetClearance( 0 );
150
151 // Don't show the default board solder mask clearance in the footprint editor. Only the
152 // footprint or pad clearance setting should be shown if it is not 0.
153 GetBoard()->GetDesignSettings().m_SolderMaskMargin = 0;
154
155 // restore the last footprint from the project, if any
156 restoreLastFootprint();
157
158 // Ensure all layers and items are visible:
159 // In footprint editor, some layers have no meaning or cannot be used, but we show all of
160 // them, at least to be able to edit a bad layer
161 GetBoard()->SetVisibleAlls();
162
163 // However the "no net" mark on pads is useless, because there are no nets in footprint
164 // editor: make it non visible.
165 GetBoard()->SetElementVisibility( LAYER_NO_CONNECTS, false );
166
167 GetGalDisplayOptions().m_axesEnabled = true;
168
169 // In Footprint Editor, set the default paper size to A4 for plot/print
170 SetPageSettings( PAGE_INFO( PAGE_INFO::A4 ) );
171 SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU() ) );
172
173 // Create the manager and dispatcher & route draw panel events to the dispatcher
174 setupTools();
175 setupUIConditions();
176
177 initLibraryTree();
178 m_treePane = new FOOTPRINT_TREE_PANE( this );
179
180 ReCreateMenuBar();
181 ReCreateHToolbar();
182 ReCreateVToolbar();
183 ReCreateOptToolbar();
184
185 m_selectionFilterPanel = new PANEL_SELECTION_FILTER( this );
186 m_appearancePanel = new APPEARANCE_CONTROLS( this, GetCanvas(), true );
187
188 // LoadSettings() *after* creating m_LayersManager, because LoadSettings() initialize
189 // parameters in m_LayersManager
190 // NOTE: KifaceSettings() will return PCBNEW_SETTINGS if we started from pcbnew
191 LoadSettings( GetSettings() );
192
193 // Must be set after calling LoadSettings() to be sure these parameters are not dependent
194 // on what is read in stored settings. Enable one internal layer, because footprints
195 // support keepout areas that can be on internal layers only (therefore on the first internal
196 // layer). This is needed to handle these keepout in internal layers only.
197 GetBoard()->SetCopperLayerCount( 3 );
198 GetBoard()->SetEnabledLayers( GetBoard()->GetEnabledLayers().set( In1_Cu ) );
199 GetBoard()->SetVisibleLayers( GetBoard()->GetEnabledLayers() );
200 GetBoard()->SetLayerName( In1_Cu, _( "Inner layers" ) );
201
202 SetActiveLayer( F_SilkS );
203
204 m_auimgr.SetManagedWindow( this );
205
206 CreateInfoBar();
207
208 unsigned int auiFlags = wxAUI_MGR_DEFAULT;
209 #if !defined( _WIN32 )
210 // Windows cannot redraw the UI fast enough during a live resize and may lead to all kinds
211 // of graphical glitches
212 auiFlags |= wxAUI_MGR_LIVE_RESIZE;
213 #endif
214 m_auimgr.SetFlags( auiFlags );
215
216 // Rows; layers 4 - 6
217 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" )
218 .Top().Layer( 6 ) );
219 m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" )
220 .Bottom().Layer( 6 ) );
221
222 // Columns; layers 1 - 3
223 m_auimgr.AddPane( m_optionsToolBar, EDA_PANE().VToolbar().Name( "OptToolbar" )
224 .Left().Layer( 3 ) );
225 m_auimgr.AddPane( m_treePane, EDA_PANE().Palette().Name( "Footprints" )
226 .Left().Layer(2)
227 .Caption( _( "Libraries" ) )
228 .MinSize( 250, 400 ).Resizable() );
229
230 m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" )
231 .Right().Layer(2) );
232
233 m_auimgr.AddPane( m_appearancePanel, EDA_PANE().Name( "LayersManager" )
234 .Right().Layer( 3 )
235 .Caption( _( "Appearance" ) ).PaneBorder( false )
236 .MinSize( 180, -1 ).BestSize( 180, -1 ) );
237 m_auimgr.AddPane( m_selectionFilterPanel, EDA_PANE().Palette().Name( "SelectionFilter" )
238 .Right().Layer( 3 ).Position( 2 )
239 .Caption( _( "Selection Filter" ) ).PaneBorder( false )
240 .MinSize( 160, -1 ).BestSize( m_selectionFilterPanel->GetBestSize() ) );
241
242 // Center
243 m_auimgr.AddPane( GetCanvas(), EDA_PANE().Canvas().Name( "DrawFrame" )
244 .Center() );
245
246 m_auimgr.GetPane( "LayersManager" ).Show( m_show_layer_manager_tools );
247 m_auimgr.GetPane( "SelectionFilter" ).Show( m_show_layer_manager_tools );
248
249 // The selection filter doesn't need to grow in the vertical direction when docked
250 m_auimgr.GetPane( "SelectionFilter" ).dock_proportion = 0;
251
252 ActivateGalCanvas();
253
254 FinishAUIInitialization();
255
256 if( m_editorSettings->m_LibWidth > 0 )
257 {
258 wxAuiPaneInfo& treePane = m_auimgr.GetPane( "Footprints" );
259
260 // wxAUI hack: force width by setting MinSize() and then Fixed()
261 // thanks to ZenJu http://trac.wxwidgets.org/ticket/13180
262 treePane.MinSize( m_editorSettings->m_LibWidth, -1 );
263 treePane.Fixed();
264 m_auimgr.Update();
265
266 // now make it resizable again
267 treePane.Resizable();
268 m_auimgr.Update();
269
270 // Note: DO NOT call m_auimgr.Update() anywhere after this; it will nuke the size
271 // back to minimum.
272 treePane.MinSize( 250, -1 );
273 }
274
275 // Apply saved visibility stuff at the end
276 FOOTPRINT_EDITOR_SETTINGS* cfg = GetSettings();
277 m_appearancePanel->SetUserLayerPresets( cfg->m_LayerPresets );
278 m_appearancePanel->ApplyLayerPreset( cfg->m_ActiveLayerPreset );
279
280 if( cfg->m_AuiPanels.right_panel_width > 0 )
281 {
282 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
283 SetAuiPaneSize( m_auimgr, layersManager, cfg->m_AuiPanels.right_panel_width, -1 );
284 }
285
286 m_appearancePanel->SetTabIndex( cfg->m_AuiPanels.appearance_panel_tab );
287
288 GetToolManager()->RunAction( ACTIONS::zoomFitScreen, false );
289 UpdateTitle();
290 setupUnits( GetSettings() );
291
292 resolveCanvasType();
293
294 // Default shutdown reason until a file is loaded
295 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Footprint changes are unsaved" ) );
296
297 // Catch unhandled accelerator command characters that were no handled by the library tree
298 // panel.
299 Bind( wxEVT_CHAR, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
300 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
301
302 // Ensure the window is on top
303 Raise();
304 Show( true );
305
306 // Register a call to update the toolbar sizes. It can't be done immediately because
307 // it seems to require some sizes calculated that aren't yet (at least on GTK).
308 CallAfter( [&]()
309 {
310 // Ensure the controls on the toolbars all are correctly sized
311 UpdateToolbarControlSizes();
312 } );
313 }
314
315
~FOOTPRINT_EDIT_FRAME()316 FOOTPRINT_EDIT_FRAME::~FOOTPRINT_EDIT_FRAME()
317 {
318 // Shutdown all running tools
319 if( m_toolManager )
320 m_toolManager->ShutdownAllTools();
321
322 // save the footprint in the PROJECT
323 retainLastFootprint();
324
325 delete m_selectionFilterPanel;
326 delete m_appearancePanel;
327 }
328
329
IsContentModified() const330 bool FOOTPRINT_EDIT_FRAME::IsContentModified() const
331 {
332 return GetScreen() && GetScreen()->IsContentModified() && GetBoard() && GetBoard()->GetFirstFootprint();
333 }
334
335
GetCurrentSelection()336 SELECTION& FOOTPRINT_EDIT_FRAME::GetCurrentSelection()
337 {
338 return m_toolManager->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
339 }
340
341
SwitchCanvas(EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType)342 void FOOTPRINT_EDIT_FRAME::SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType )
343 {
344 // switches currently used canvas (Cairo / OpenGL).
345 PCB_BASE_FRAME::SwitchCanvas( aCanvasType );
346
347 GetCanvas()->GetGAL()->SetAxesEnabled( true );
348
349 // The base class method *does not reinit* the layers manager. We must update the layer
350 // widget to match board visibility states, both layers and render columns, and and some
351 // settings dependent on the canvas.
352 UpdateUserInterface();
353 }
354
355
HardRedraw()356 void FOOTPRINT_EDIT_FRAME::HardRedraw()
357 {
358 SyncLibraryTree( true );
359 GetCanvas()->ForceRefresh();
360 }
361
362
ToggleSearchTree()363 void FOOTPRINT_EDIT_FRAME::ToggleSearchTree()
364 {
365 wxAuiPaneInfo& treePane = m_auimgr.GetPane( m_treePane );
366 treePane.Show( !IsSearchTreeShown() );
367 m_auimgr.Update();
368 }
369
370
ToggleLayersManager()371 void FOOTPRINT_EDIT_FRAME::ToggleLayersManager()
372 {
373 FOOTPRINT_EDITOR_SETTINGS* settings = GetSettings();
374 wxAuiPaneInfo& layersManager = m_auimgr.GetPane( "LayersManager" );
375 wxAuiPaneInfo& selectionFilter = m_auimgr.GetPane( "SelectionFilter" );
376
377 // show auxiliary Vertical layers and visibility manager toolbar
378 m_show_layer_manager_tools = !m_show_layer_manager_tools;
379 layersManager.Show( m_show_layer_manager_tools );
380 selectionFilter.Show( m_show_layer_manager_tools );
381
382 if( m_show_layer_manager_tools )
383 {
384 SetAuiPaneSize( m_auimgr, layersManager, settings->m_AuiPanels.right_panel_width, -1 );
385 }
386 else
387 {
388 settings->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x;
389 m_auimgr.Update();
390 }
391 }
392
393
IsSearchTreeShown() const394 bool FOOTPRINT_EDIT_FRAME::IsSearchTreeShown() const
395 {
396 return const_cast<wxAuiManager&>( m_auimgr ).GetPane( m_treePane ).IsShown();
397 }
398
399
GetModel() const400 BOARD_ITEM_CONTAINER* FOOTPRINT_EDIT_FRAME::GetModel() const
401 {
402 return GetBoard()->GetFirstFootprint();
403 }
404
405
GetTreeFPID() const406 LIB_ID FOOTPRINT_EDIT_FRAME::GetTreeFPID() const
407 {
408 return m_treePane->GetLibTree()->GetSelectedLibId();
409 }
410
411
GetCurrentTreeNode() const412 LIB_TREE_NODE* FOOTPRINT_EDIT_FRAME::GetCurrentTreeNode() const
413 {
414 return m_treePane->GetLibTree()->GetCurrentTreeNode();
415 }
416
417
GetTargetFPID() const418 LIB_ID FOOTPRINT_EDIT_FRAME::GetTargetFPID() const
419 {
420 LIB_ID id;
421
422 if( IsSearchTreeShown() )
423 id = GetTreeFPID();
424
425 if( id.GetLibNickname().empty() )
426 id = GetLoadedFPID();
427
428 return id;
429 }
430
431
GetLoadedFPID() const432 LIB_ID FOOTPRINT_EDIT_FRAME::GetLoadedFPID() const
433 {
434 FOOTPRINT* footprint = GetBoard()->GetFirstFootprint();
435
436 if( footprint )
437 return LIB_ID( footprint->GetFPID().GetLibNickname(), m_footprintNameWhenLoaded );
438 else
439 return LIB_ID();
440 }
441
442
ClearModify()443 void FOOTPRINT_EDIT_FRAME::ClearModify()
444 {
445 if( GetBoard()->GetFirstFootprint() )
446 m_footprintNameWhenLoaded = GetBoard()->GetFirstFootprint()->GetFPID().GetLibItemName();
447
448 GetScreen()->SetContentModified( false );
449 }
450
451
IsCurrentFPFromBoard() const452 bool FOOTPRINT_EDIT_FRAME::IsCurrentFPFromBoard() const
453 {
454 FOOTPRINT* footprint = GetBoard()->GetFirstFootprint();
455
456 return ( footprint && footprint->GetLink() != niluuid );
457 }
458
459
retainLastFootprint()460 void FOOTPRINT_EDIT_FRAME::retainLastFootprint()
461 {
462 LIB_ID id = GetLoadedFPID();
463
464 if( id.IsValid() )
465 {
466 Prj().SetRString( PROJECT::PCB_FOOTPRINT_EDITOR_LIB_NICKNAME, id.GetLibNickname() );
467 Prj().SetRString( PROJECT::PCB_FOOTPRINT_EDITOR_FP_NAME, id.GetLibItemName() );
468 }
469 }
470
471
restoreLastFootprint()472 void FOOTPRINT_EDIT_FRAME::restoreLastFootprint()
473 {
474 const wxString& footprintName = Prj().GetRString( PROJECT::PCB_FOOTPRINT_EDITOR_FP_NAME );
475 const wxString& libNickname = Prj().GetRString( PROJECT::PCB_FOOTPRINT_EDITOR_LIB_NICKNAME );
476
477 if( libNickname.Length() && footprintName.Length() )
478 {
479 LIB_ID id;
480 id.SetLibNickname( libNickname );
481 id.SetLibItemName( footprintName );
482
483 FOOTPRINT* footprint = loadFootprint( id );
484
485 if( footprint )
486 AddFootprintToBoard( footprint );
487 }
488 }
489
490
AddFootprintToBoard(FOOTPRINT * aFootprint)491 void FOOTPRINT_EDIT_FRAME::AddFootprintToBoard( FOOTPRINT* aFootprint )
492 {
493 m_revertModule.reset( (FOOTPRINT*) aFootprint->Clone() );
494
495 m_footprintNameWhenLoaded = aFootprint->GetFPID().GetLibItemName();
496
497 PCB_BASE_EDIT_FRAME::AddFootprintToBoard( aFootprint );
498 // Ensure item UUIDs are valide
499 // ("old" footprints can have null uuids that create issues in fp editor)
500 aFootprint->FixUuids();
501
502 if( IsCurrentFPFromBoard() )
503 {
504 wxString msg;
505 msg.Printf( _( "Editing %s from board. Saving will update the board only." ),
506 aFootprint->GetReference() );
507
508 GetInfoBar()->RemoveAllButtons();
509 GetInfoBar()->AddCloseButton();
510 GetInfoBar()->ShowMessage( msg, wxICON_INFORMATION );
511 }
512
513 UpdateMsgPanel();
514 }
515
516
GetFootprintEditorFrameName()517 const wxChar* FOOTPRINT_EDIT_FRAME::GetFootprintEditorFrameName()
518 {
519 return FOOTPRINT_EDIT_FRAME_NAME;
520 }
521
522
GetDesignSettings() const523 BOARD_DESIGN_SETTINGS& FOOTPRINT_EDIT_FRAME::GetDesignSettings() const
524 {
525 return GetBoard()->GetDesignSettings();
526 }
527
528
GetPlotSettings() const529 const PCB_PLOT_PARAMS& FOOTPRINT_EDIT_FRAME::GetPlotSettings() const
530 {
531 wxFAIL_MSG( "Plotting not supported in Footprint Editor" );
532
533 return PCB_BASE_FRAME::GetPlotSettings();
534 }
535
536
SetPlotSettings(const PCB_PLOT_PARAMS & aSettings)537 void FOOTPRINT_EDIT_FRAME::SetPlotSettings( const PCB_PLOT_PARAMS& aSettings )
538 {
539 wxFAIL_MSG( "Plotting not supported in Footprint Editor" );
540 }
541
542
GetSettings()543 FOOTPRINT_EDITOR_SETTINGS* FOOTPRINT_EDIT_FRAME::GetSettings()
544 {
545 if( !m_editorSettings )
546 m_editorSettings = Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>();
547
548 return m_editorSettings;
549 }
550
551
config() const552 APP_SETTINGS_BASE* FOOTPRINT_EDIT_FRAME::config() const
553 {
554 return m_editorSettings ? m_editorSettings
555 : Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>();
556 }
557
558
LoadSettings(APP_SETTINGS_BASE * aCfg)559 void FOOTPRINT_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
560 {
561 // aCfg will be the PCBNEW_SETTINGS
562 FOOTPRINT_EDITOR_SETTINGS* cfg = GetSettings();
563
564 PCB_BASE_FRAME::LoadSettings( cfg );
565
566 GetDesignSettings() = cfg->m_DesignSettings;
567
568 m_displayOptions = cfg->m_Display;
569 m_show_layer_manager_tools = cfg->m_AuiPanels.show_layer_manager;
570
571 GetToolManager()->GetTool<PCB_SELECTION_TOOL>()->GetFilter() = cfg->m_SelectionFilter;
572 m_selectionFilterPanel->SetCheckboxesFromFilter( cfg->m_SelectionFilter );
573 }
574
575
SaveSettings(APP_SETTINGS_BASE * aCfg)576 void FOOTPRINT_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
577 {
578 GetGalDisplayOptions().m_axesEnabled = true;
579
580 // aCfg will be the PCBNEW_SETTINGS
581 FOOTPRINT_EDITOR_SETTINGS* cfg = GetSettings();
582
583 PCB_BASE_FRAME::SaveSettings( cfg );
584
585 cfg->m_DesignSettings = GetDesignSettings();
586 cfg->m_Display = m_displayOptions;
587 cfg->m_LibWidth = m_treePane->GetSize().x;
588 cfg->m_SelectionFilter = GetToolManager()->GetTool<PCB_SELECTION_TOOL>()->GetFilter();
589 cfg->m_LayerPresets = m_appearancePanel->GetUserLayerPresets();
590 cfg->m_ActiveLayerPreset = m_appearancePanel->GetActiveLayerPreset();
591
592 cfg->m_AuiPanels.show_layer_manager = m_show_layer_manager_tools;
593 cfg->m_AuiPanels.right_panel_width = m_appearancePanel->GetSize().x;
594 cfg->m_AuiPanels.appearance_panel_tab = m_appearancePanel->GetTabIndex();
595
596 GetSettingsManager()->SaveColorSettings( GetColorSettings(), "board" );
597 }
598
599
GetColorSettings() const600 COLOR_SETTINGS* FOOTPRINT_EDIT_FRAME::GetColorSettings() const
601 {
602 wxString currentTheme = GetFootprintEditorSettings()->m_ColorTheme;
603 return Pgm().GetSettingsManager().GetColorSettings( currentTheme );
604 }
605
606
GetMagneticItemsSettings()607 MAGNETIC_SETTINGS* FOOTPRINT_EDIT_FRAME::GetMagneticItemsSettings()
608 {
609 // Get the actual frame settings for magnetic items
610 FOOTPRINT_EDITOR_SETTINGS* cfg = GetSettings();
611 wxCHECK( cfg, nullptr );
612 return &cfg->m_MagneticItems;
613 }
614
615
GetDocumentExtents(bool aIncludeAllVisible) const616 const BOX2I FOOTPRINT_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible ) const
617 {
618 FOOTPRINT* footprint = GetBoard()->GetFirstFootprint();
619
620 if( footprint )
621 {
622 bool hasGraphicalItem = footprint->Pads().size() || footprint->Zones().size();
623
624 if( !hasGraphicalItem )
625 {
626 for( const BOARD_ITEM* item : footprint->GraphicalItems() )
627 {
628 if( item->Type() == PCB_FP_TEXT_T )
629 continue;
630
631 hasGraphicalItem = true;
632 break;
633 }
634 }
635
636 if( hasGraphicalItem )
637 {
638 return footprint->GetBoundingBox( false, false );
639 }
640 else
641 {
642 BOX2I newFootprintBB( { 0, 0 }, { 0, 0 } );
643 newFootprintBB.Inflate( Millimeter2iu( 12 ) );
644 return newFootprintBB;
645 }
646 }
647
648 return GetBoardBoundingBox( false );
649 }
650
651
canCloseWindow(wxCloseEvent & aEvent)652 bool FOOTPRINT_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
653 {
654 if( IsContentModified() )
655 {
656 // Shutdown blocks must be determined and vetoed as early as possible
657 if( KIPLATFORM::APP::SupportsShutdownBlockReason() &&
658 aEvent.GetId() == wxEVT_QUERY_END_SESSION )
659 {
660 aEvent.Veto();
661 return false;
662 }
663
664 wxString footprintName = GetBoard()->GetFirstFootprint()->GetFPID().GetLibItemName();
665 wxString msg = _( "Save changes to '%s' before closing?" );
666
667 if( !HandleUnsavedChanges( this, wxString::Format( msg, footprintName ),
668 [&]() -> bool
669 {
670 return SaveFootprint( GetBoard()->GetFirstFootprint() );
671 } ) )
672 {
673 aEvent.Veto();
674 return false;
675 }
676 }
677
678 return PCB_BASE_EDIT_FRAME::canCloseWindow( aEvent );
679 }
680
681
doCloseWindow()682 void FOOTPRINT_EDIT_FRAME::doCloseWindow()
683 {
684 // No more vetos
685 GetCanvas()->SetEventDispatcher( nullptr );
686 GetCanvas()->StopDrawing();
687
688 // Do not show the layer manager during closing to avoid flicker
689 // on some platforms (Windows) that generate useless redraw of items in
690 // the Layer Manager
691 m_auimgr.GetPane( "LayersManager" ).Show( false );
692 m_auimgr.GetPane( "SelectionFilter" ).Show( false );
693
694 Clear_Pcb( false );
695
696 SETTINGS_MANAGER* mgr = GetSettingsManager();
697
698 if( mgr->IsProjectOpen() && wxFileName::IsDirWritable( Prj().GetProjectPath() ) )
699 {
700 GFootprintList.WriteCacheToFile( Prj().GetProjectPath() + "fp-info-cache" );
701 }
702
703 mgr->FlushAndRelease( GetSettings() );
704 }
705
706
OnExitKiCad(wxCommandEvent & event)707 void FOOTPRINT_EDIT_FRAME::OnExitKiCad( wxCommandEvent& event )
708 {
709 Kiway().OnKiCadExit();
710 }
711
712
CloseFootprintEditor(wxCommandEvent & Event)713 void FOOTPRINT_EDIT_FRAME::CloseFootprintEditor( wxCommandEvent& Event )
714 {
715 Close();
716 }
717
718
OnUpdateLoadFootprintFromBoard(wxUpdateUIEvent & aEvent)719 void FOOTPRINT_EDIT_FRAME::OnUpdateLoadFootprintFromBoard( wxUpdateUIEvent& aEvent )
720 {
721 PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
722
723 aEvent.Enable( frame && frame->GetBoard()->GetFirstFootprint() != nullptr );
724 }
725
726
OnUpdateSaveFootprintToBoard(wxUpdateUIEvent & aEvent)727 void FOOTPRINT_EDIT_FRAME::OnUpdateSaveFootprintToBoard( wxUpdateUIEvent& aEvent )
728 {
729 PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB_EDITOR, false );
730
731 FOOTPRINT* editorFootprint = GetBoard()->GetFirstFootprint();
732 bool canInsert = frame && editorFootprint && editorFootprint->GetLink() == niluuid;
733
734 // If the source was deleted, the footprint can inserted but not updated in the board.
735 if( frame && editorFootprint && editorFootprint->GetLink() != niluuid )
736 {
737 BOARD* mainpcb = frame->GetBoard();
738 canInsert = true;
739
740 // search if the source footprint was not deleted:
741 for( FOOTPRINT* candidate : mainpcb->Footprints() )
742 {
743 if( editorFootprint->GetLink() == candidate->m_Uuid )
744 {
745 canInsert = false;
746 break;
747 }
748 }
749 }
750
751 aEvent.Enable( canInsert );
752 }
753
754
ShowChangedLanguage()755 void FOOTPRINT_EDIT_FRAME::ShowChangedLanguage()
756 {
757 // call my base class
758 PCB_BASE_EDIT_FRAME::ShowChangedLanguage();
759
760 // We have 2 panes to update.
761 // For some obscure reason, the AUI manager hides the first modified pane.
762 // So force show panes
763 wxAuiPaneInfo& tree_pane_info = m_auimgr.GetPane( m_treePane );
764 bool tree_shown = tree_pane_info.IsShown();
765 tree_pane_info.Caption( _( "Libraries" ) );
766
767 wxAuiPaneInfo& lm_pane_info = m_auimgr.GetPane( m_appearancePanel );
768 bool lm_shown = lm_pane_info.IsShown();
769 lm_pane_info.Caption( _( "Appearance" ) );
770
771 // update the layer manager
772 m_appearancePanel->OnBoardChanged();
773 UpdateUserInterface();
774
775 // Now restore the visibility:
776 lm_pane_info.Show( lm_shown );
777 tree_pane_info.Show( tree_shown );
778 m_auimgr.Update();
779 }
780
781
OnModify()782 void FOOTPRINT_EDIT_FRAME::OnModify()
783 {
784 PCB_BASE_FRAME::OnModify();
785 Update3DView( true, true );
786 m_treePane->GetLibTree()->RefreshLibTree();
787
788 if( !GetTitle().StartsWith( "*" ) )
789 UpdateTitle();
790 }
791
792
UpdateTitle()793 void FOOTPRINT_EDIT_FRAME::UpdateTitle()
794 {
795 wxString title;
796 LIB_ID fpid = GetLoadedFPID();
797 FOOTPRINT* footprint = GetBoard()->GetFirstFootprint();
798 bool writable = true;
799
800 if( IsCurrentFPFromBoard() )
801 {
802 if( IsContentModified() )
803 title = wxT( "*" );
804
805 title += footprint->GetReference();
806 title += wxS( " " ) + wxString::Format( _( "[from %s]" ),
807 Prj().GetProjectName() + "." + PcbFileExtension );
808 }
809 else if( fpid.IsValid() )
810 {
811 try
812 {
813 writable = Prj().PcbFootprintLibs()->IsFootprintLibWritable( fpid.GetLibNickname() );
814 }
815 catch( const IO_ERROR& )
816 {
817 // best efforts...
818 }
819
820 // Note: don't used GetLoadedFPID(); footprint name may have been edited
821 if( IsContentModified() )
822 title = wxT( "*" );
823
824 title += FROM_UTF8( footprint->GetFPID().Format().c_str() );
825
826 if( !writable )
827 title += wxS( " " ) + _( "[Read Only]" );
828 }
829 else if( !fpid.GetLibItemName().empty() )
830 {
831 // Note: don't used GetLoadedFPID(); footprint name may have been edited
832 if( IsContentModified() )
833 title = wxT( "*" );
834
835 title += FROM_UTF8( footprint->GetFPID().GetLibItemName().c_str() );
836 title += wxS( " " ) + _( "[Unsaved]" );
837 }
838 else
839 {
840 title = _( "[no footprint loaded]" );
841 }
842
843 title += wxT( " \u2014 " ) + _( "Footprint Editor" );
844
845 SetTitle( title );
846 }
847
848
UpdateUserInterface()849 void FOOTPRINT_EDIT_FRAME::UpdateUserInterface()
850 {
851 m_appearancePanel->OnBoardChanged();
852 }
853
854
UpdateView()855 void FOOTPRINT_EDIT_FRAME::UpdateView()
856 {
857 GetCanvas()->UpdateColors();
858 GetCanvas()->DisplayBoard( GetBoard() );
859 m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
860 UpdateTitle();
861 }
862
863
initLibraryTree()864 void FOOTPRINT_EDIT_FRAME::initLibraryTree()
865 {
866 FP_LIB_TABLE* fpTable = Prj().PcbFootprintLibs();
867
868 WX_PROGRESS_REPORTER progressReporter( this, _( "Loading Footprint Libraries" ), 2 );
869
870 if( GFootprintList.GetCount() == 0 )
871 GFootprintList.ReadCacheFromFile( Prj().GetProjectPath() + "fp-info-cache" );
872
873 GFootprintList.ReadFootprintFiles( fpTable, nullptr, &progressReporter );
874 progressReporter.Show( false );
875
876 if( GFootprintList.GetErrorCount() )
877 GFootprintList.DisplayErrors( this );
878
879 m_adapter = FP_TREE_SYNCHRONIZING_ADAPTER::Create( this, fpTable );
880 auto adapter = static_cast<FP_TREE_SYNCHRONIZING_ADAPTER*>( m_adapter.get() );
881
882 adapter->AddLibraries();
883 }
884
885
SyncLibraryTree(bool aProgress)886 void FOOTPRINT_EDIT_FRAME::SyncLibraryTree( bool aProgress )
887 {
888 FP_LIB_TABLE* fpTable = Prj().PcbFootprintLibs();
889 auto adapter = static_cast<FP_TREE_SYNCHRONIZING_ADAPTER*>( m_adapter.get() );
890 LIB_ID target = GetTargetFPID();
891 bool targetSelected = ( target == m_treePane->GetLibTree()->GetSelectedLibId() );
892
893 // Sync FOOTPRINT_INFO list to the libraries on disk
894 if( aProgress )
895 {
896 WX_PROGRESS_REPORTER progressReporter( this, _( "Updating Footprint Libraries" ), 2 );
897 GFootprintList.ReadFootprintFiles( fpTable, nullptr, &progressReporter );
898 progressReporter.Show( false );
899 }
900 else
901 {
902 GFootprintList.ReadFootprintFiles( fpTable, nullptr, nullptr );
903 }
904
905 // Sync the LIB_TREE to the FOOTPRINT_INFO list
906 adapter->Sync();
907
908 m_treePane->GetLibTree()->Unselect();
909 m_treePane->GetLibTree()->Regenerate( true );
910
911 if( target.IsValid() )
912 {
913 if( adapter->FindItem( target ) )
914 {
915 if( targetSelected )
916 m_treePane->GetLibTree()->SelectLibId( target );
917 else
918 m_treePane->GetLibTree()->CenterLibId( target );
919 }
920 else
921 {
922 // Try to focus on parent
923 target.SetLibItemName( wxEmptyString );
924 m_treePane->GetLibTree()->CenterLibId( target );
925 }
926 }
927 }
928
929
RegenerateLibraryTree()930 void FOOTPRINT_EDIT_FRAME::RegenerateLibraryTree()
931 {
932 LIB_ID target = GetTargetFPID();
933
934 m_treePane->GetLibTree()->Regenerate( true );
935
936 if( target.IsValid() )
937 m_treePane->GetLibTree()->CenterLibId( target );
938 }
939
940
RefreshLibraryTree()941 void FOOTPRINT_EDIT_FRAME::RefreshLibraryTree()
942 {
943 m_treePane->GetLibTree()->RefreshLibTree();
944 }
945
946
FocusOnLibID(const LIB_ID & aLibID)947 void FOOTPRINT_EDIT_FRAME::FocusOnLibID( const LIB_ID& aLibID )
948 {
949 m_treePane->GetLibTree()->SelectLibId( aLibID );
950 }
951
952
OnDisplayOptionsChanged()953 void FOOTPRINT_EDIT_FRAME::OnDisplayOptionsChanged()
954 {
955 m_appearancePanel->UpdateDisplayOptions();
956 }
957
958
InstallPreferences(PAGED_DIALOG * aParent,PANEL_HOTKEYS_EDITOR * aHotkeysPanel)959 void FOOTPRINT_EDIT_FRAME::InstallPreferences( PAGED_DIALOG* aParent,
960 PANEL_HOTKEYS_EDITOR* aHotkeysPanel )
961 {
962 wxTreebook* book = aParent->GetTreebook();
963
964 book->AddPage( new wxPanel( book ), _( "Footprint Editor" ) );
965 book->AddSubPage( new PANEL_DISPLAY_OPTIONS( this, aParent ), _( "Display Options" ) );
966 book->AddSubPage( new PANEL_EDIT_OPTIONS( this, aParent ), _( "Editing Options" ) );
967 book->AddSubPage( new PANEL_FP_EDITOR_COLOR_SETTINGS( this, book ), _( "Colors" ) );
968 book->AddSubPage( new PANEL_FP_EDITOR_DEFAULTS( this, aParent ), _( "Default Values" ) );
969
970 aHotkeysPanel->AddHotKeys( GetToolManager() );
971 }
972
973
setupTools()974 void FOOTPRINT_EDIT_FRAME::setupTools()
975 {
976 // Create the manager and dispatcher & route draw panel events to the dispatcher
977 m_toolManager = new TOOL_MANAGER;
978 m_toolManager->SetEnvironment( GetBoard(), GetCanvas()->GetView(),
979 GetCanvas()->GetViewControls(), config(), this );
980 m_actions = new PCB_ACTIONS();
981 m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager );
982
983 GetCanvas()->SetEventDispatcher( m_toolDispatcher );
984
985 m_toolManager->RegisterTool( new COMMON_CONTROL );
986 m_toolManager->RegisterTool( new COMMON_TOOLS );
987 m_toolManager->RegisterTool( new PCB_SELECTION_TOOL );
988 m_toolManager->RegisterTool( new ZOOM_TOOL );
989 m_toolManager->RegisterTool( new EDIT_TOOL );
990 m_toolManager->RegisterTool( new PAD_TOOL );
991 m_toolManager->RegisterTool( new DRAWING_TOOL );
992 m_toolManager->RegisterTool( new PCB_POINT_EDITOR );
993 m_toolManager->RegisterTool( new PCB_CONTROL ); // copy/paste
994 m_toolManager->RegisterTool( new FOOTPRINT_EDITOR_CONTROL );
995 m_toolManager->RegisterTool( new ALIGN_DISTRIBUTE_TOOL );
996 m_toolManager->RegisterTool( new PCB_PICKER_TOOL );
997 m_toolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
998 m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
999 m_toolManager->RegisterTool( new GROUP_TOOL );
1000 m_toolManager->RegisterTool( new CONVERT_TOOL );
1001 m_toolManager->RegisterTool( new SCRIPTING_TOOL );
1002
1003 m_toolManager->GetTool<PCB_SELECTION_TOOL>()->SetIsFootprintEditor( true );
1004 m_toolManager->GetTool<EDIT_TOOL>()->SetIsFootprintEditor( true );
1005 m_toolManager->GetTool<PAD_TOOL>()->SetIsFootprintEditor( true );
1006 m_toolManager->GetTool<DRAWING_TOOL>()->SetIsFootprintEditor( true );
1007 m_toolManager->GetTool<PCB_POINT_EDITOR>()->SetIsFootprintEditor( true );
1008 m_toolManager->GetTool<PCB_CONTROL>()->SetIsFootprintEditor( true );
1009 m_toolManager->GetTool<PCB_PICKER_TOOL>()->SetIsFootprintEditor( true );
1010 m_toolManager->GetTool<POSITION_RELATIVE_TOOL>()->SetIsFootprintEditor( true );
1011 m_toolManager->GetTool<GROUP_TOOL>()->SetIsFootprintEditor( true );
1012 m_toolManager->GetTool<SCRIPTING_TOOL>()->SetIsFootprintEditor( true );
1013
1014 m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
1015 m_toolManager->InitTools();
1016
1017 m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" );
1018 }
1019
1020
setupUIConditions()1021 void FOOTPRINT_EDIT_FRAME::setupUIConditions()
1022 {
1023 PCB_BASE_EDIT_FRAME::setupUIConditions();
1024
1025 ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
1026 PCB_EDITOR_CONDITIONS cond( this );
1027
1028 wxASSERT( mgr );
1029
1030 #define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
1031 #define CHECK( x ) ACTION_CONDITIONS().Check( x )
1032
1033 auto haveFootprintCond =
1034 [this]( const SELECTION& )
1035 {
1036 return GetBoard()->GetFirstFootprint() != nullptr;
1037 };
1038
1039 auto footprintTargettedCond =
1040 [this]( const SELECTION& )
1041 {
1042 return !GetTargetFPID().GetLibItemName().empty();
1043 };
1044
1045 mgr->SetConditions( ACTIONS::saveAs, ENABLE( footprintTargettedCond ) );
1046 mgr->SetConditions( ACTIONS::revert, ENABLE( cond.ContentModified() ) );
1047 mgr->SetConditions( ACTIONS::save, ENABLE( SELECTION_CONDITIONS::ShowAlways ) );
1048
1049 mgr->SetConditions( ACTIONS::undo, ENABLE( cond.UndoAvailable() ) );
1050 mgr->SetConditions( ACTIONS::redo, ENABLE( cond.RedoAvailable() ) );
1051
1052 mgr->SetConditions( ACTIONS::toggleGrid, CHECK( cond.GridVisible() ) );
1053 mgr->SetConditions( ACTIONS::toggleCursorStyle, CHECK( cond.FullscreenCursor() ) );
1054 mgr->SetConditions( ACTIONS::millimetersUnits, CHECK( cond.Units( EDA_UNITS::MILLIMETRES ) ) );
1055 mgr->SetConditions( ACTIONS::inchesUnits, CHECK( cond.Units( EDA_UNITS::INCHES ) ) );
1056 mgr->SetConditions( ACTIONS::milsUnits, CHECK( cond.Units( EDA_UNITS::MILS ) ) );
1057
1058 mgr->SetConditions( ACTIONS::cut, ENABLE( cond.HasItems() ) );
1059 mgr->SetConditions( ACTIONS::copy, ENABLE( cond.HasItems() ) );
1060 mgr->SetConditions( ACTIONS::paste, ENABLE( SELECTION_CONDITIONS::Idle && cond.NoActiveTool() ) );
1061 mgr->SetConditions( ACTIONS::pasteSpecial, ENABLE( SELECTION_CONDITIONS::Idle && cond.NoActiveTool() ) );
1062 mgr->SetConditions( ACTIONS::doDelete, ENABLE( cond.HasItems() ) );
1063 mgr->SetConditions( ACTIONS::duplicate, ENABLE( cond.HasItems() ) );
1064 mgr->SetConditions( ACTIONS::selectAll, ENABLE( cond.HasItems() ) );
1065
1066 auto haveAtLeastOneGroupCond =
1067 []( const SELECTION& aSel )
1068 {
1069 for( EDA_ITEM* item : aSel )
1070 {
1071 if( item->Type() == PCB_GROUP_T )
1072 return true;
1073 }
1074
1075 return false;
1076 };
1077
1078 mgr->SetConditions( PCB_ACTIONS::rotateCw, ENABLE( cond.HasItems() ) );
1079 mgr->SetConditions( PCB_ACTIONS::rotateCcw, ENABLE( cond.HasItems() ) );
1080 mgr->SetConditions( PCB_ACTIONS::mirror, ENABLE( cond.HasItems() ) );
1081 mgr->SetConditions( PCB_ACTIONS::group, ENABLE( SELECTION_CONDITIONS::MoreThan( 1 ) ) );
1082 mgr->SetConditions( PCB_ACTIONS::ungroup, ENABLE( haveAtLeastOneGroupCond ) );
1083
1084 mgr->SetConditions( PCB_ACTIONS::padDisplayMode, CHECK( !cond.PadFillDisplay() ) );
1085 mgr->SetConditions( PCB_ACTIONS::textOutlines, CHECK( !cond.TextFillDisplay() ) );
1086 mgr->SetConditions( PCB_ACTIONS::graphicsOutlines, CHECK( !cond.GraphicsFillDisplay() ) );
1087
1088 mgr->SetConditions( ACTIONS::zoomTool, CHECK( cond.CurrentTool( ACTIONS::zoomTool ) ) );
1089 mgr->SetConditions( ACTIONS::selectionTool, CHECK( cond.CurrentTool( ACTIONS::selectionTool ) ) );
1090
1091 mgr->SetConditions( PCB_ACTIONS::checkFootprint, ENABLE( cond.HasItems() ) );
1092 mgr->SetConditions( PCB_ACTIONS::repairFootprint, ENABLE( cond.HasItems() ) );
1093
1094
1095 auto highContrastCond =
1096 [this]( const SELECTION& )
1097 {
1098 return GetDisplayOptions().m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL;
1099 };
1100
1101 auto boardFlippedCond =
1102 [this]( const SELECTION& )
1103 {
1104 return GetCanvas()->GetView()->IsMirroredX();
1105 };
1106
1107 auto footprintTreeCond =
1108 [this](const SELECTION& )
1109 {
1110 return IsSearchTreeShown();
1111 };
1112
1113 auto layerManagerCond =
1114 [this]( const SELECTION& )
1115 {
1116 return m_auimgr.GetPane( "LayersManager" ).IsShown();
1117 };
1118
1119 mgr->SetConditions( ACTIONS::highContrastMode, CHECK( highContrastCond ) );
1120 mgr->SetConditions( PCB_ACTIONS::flipBoard, CHECK( boardFlippedCond ) );
1121 mgr->SetConditions( PCB_ACTIONS::showFootprintTree, CHECK( footprintTreeCond ) );
1122 mgr->SetConditions( PCB_ACTIONS::showLayersManager, CHECK( layerManagerCond ) );
1123
1124 mgr->SetConditions( ACTIONS::print, ENABLE( haveFootprintCond ) );
1125 mgr->SetConditions( PCB_ACTIONS::exportFootprint, ENABLE( haveFootprintCond ) );
1126 mgr->SetConditions( PCB_ACTIONS::footprintProperties, ENABLE( haveFootprintCond ) );
1127 mgr->SetConditions( PCB_ACTIONS::cleanupGraphics, ENABLE( haveFootprintCond ) );
1128 mgr->SetConditions( PCB_ACTIONS::placeImportedGraphics, ENABLE( haveFootprintCond ) );
1129
1130
1131 // Only enable a tool if the part is edtable
1132 #define CURRENT_EDIT_TOOL( action ) mgr->SetConditions( action, \
1133 ACTION_CONDITIONS().Enable( haveFootprintCond ).Check( cond.CurrentTool( action ) ) )
1134
1135 CURRENT_EDIT_TOOL( ACTIONS::deleteTool );
1136 CURRENT_EDIT_TOOL( ACTIONS::measureTool );
1137 CURRENT_EDIT_TOOL( PCB_ACTIONS::placePad );
1138 CURRENT_EDIT_TOOL( PCB_ACTIONS::drawLine );
1139 CURRENT_EDIT_TOOL( PCB_ACTIONS::drawRectangle );
1140 CURRENT_EDIT_TOOL( PCB_ACTIONS::drawCircle );
1141 CURRENT_EDIT_TOOL( PCB_ACTIONS::drawArc );
1142 CURRENT_EDIT_TOOL( PCB_ACTIONS::drawPolygon );
1143 CURRENT_EDIT_TOOL( PCB_ACTIONS::drawRuleArea );
1144 CURRENT_EDIT_TOOL( PCB_ACTIONS::placeText );
1145 CURRENT_EDIT_TOOL( PCB_ACTIONS::setAnchor );
1146 CURRENT_EDIT_TOOL( PCB_ACTIONS::gridSetOrigin );
1147
1148 #undef CURRENT_EDIT_TOOL
1149 #undef ENABLE
1150 #undef CHECK
1151 }
1152
1153
ActivateGalCanvas()1154 void FOOTPRINT_EDIT_FRAME::ActivateGalCanvas()
1155 {
1156 PCB_BASE_EDIT_FRAME::ActivateGalCanvas();
1157
1158 // Be sure the axis are enabled
1159 GetCanvas()->GetGAL()->SetAxesEnabled( true );
1160
1161 UpdateView();
1162
1163 // Ensure the m_Layers settings are using the canvas type:
1164 UpdateUserInterface();
1165 }
1166
1167
CommonSettingsChanged(bool aEnvVarsChanged,bool aTextVarsChanged)1168 void FOOTPRINT_EDIT_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
1169 {
1170 PCB_BASE_EDIT_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
1171
1172 GetCanvas()->GetView()->UpdateAllLayersColor();
1173 GetCanvas()->ForceRefresh();
1174
1175 UpdateUserInterface();
1176
1177 if( aEnvVarsChanged )
1178 SyncLibraryTree( true );
1179
1180 Layout();
1181 SendSizeEvent();
1182 }
1183
1184
OnSaveFootprintAsPng(wxCommandEvent & event)1185 void FOOTPRINT_EDIT_FRAME::OnSaveFootprintAsPng( wxCommandEvent& event )
1186 {
1187 wxString fullFileName;
1188
1189 LIB_ID id = GetLoadedFPID();
1190
1191 if( id.empty() )
1192 {
1193 wxMessageBox( _( "No footprint selected." ) );
1194 return;
1195 }
1196
1197 wxFileName fn( id.GetLibItemName() );
1198 fn.SetExt( "png" );
1199
1200 wxString projectPath = wxPathOnly( Prj().GetProjectFullName() );
1201
1202 wxFileDialog dlg( this, _( "Footprint Image File Name" ), projectPath,
1203 fn.GetFullName(), PngFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1204
1205 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetPath().IsEmpty() )
1206 return;
1207
1208 // calling wxYield is mandatory under Linux, after closing the file selector dialog
1209 // to refresh the screen before creating the PNG or JPEG image from screen
1210 wxYield();
1211 SaveCanvasImageToFile( this, dlg.GetPath() );
1212 }
1213