KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eda_base_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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 2023 CERN (www.cern.ch)
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU 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, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
28#include "kicad_manager_frame.h"
29#include <eda_base_frame.h>
30#include <nlohmann/json.hpp>
31
32#include <advanced_config.h>
33#include <bitmaps.h>
34#include <bitmap_store.h>
35#include <dialog_shim.h>
42#include <eda_dde.h>
43#include <file_history.h>
44#include <id.h>
45#include <kiface_base.h>
46#include <hotkeys_basic.h>
48#include <paths.h>
49#include <local_history.h>
50#include <confirm.h>
52#include <pgm_base.h>
57#include <tool/action_manager.h>
58#include <tool/action_menu.h>
59#include <tool/action_toolbar.h>
60#include <tool/actions.h>
61#include <tool/common_control.h>
62#include <tool/tool_manager.h>
65#include <trace_helpers.h>
68#include <widgets/wx_infobar.h>
71#include <widgets/wx_grid.h>
72#include <widgets/wx_treebook.h>
73#include <wx/app.h>
74#include <wx/config.h>
75#include <wx/display.h>
76#include <wx/stdpaths.h>
77#include <wx/string.h>
78#include <wx/msgdlg.h>
79#include <wx/wupdlock.h>
80#include <kiplatform/app.h>
81#include <kiplatform/io.h>
82#include <kiplatform/ui.h>
83
84#include <nlohmann/json.hpp>
85
86#include <functional>
87#include <kiface_ids.h>
88
89#ifdef KICAD_IPC_API
90#include <api/api_server.h>
91#endif
92
93
94// Minimum window size
95static const wxSize minSizeLookup( FRAME_T aFrameType, wxWindow* aWindow )
96{
97 switch( aFrameType )
98 {
100 return wxWindow::FromDIP( wxSize( 406, 354 ), aWindow );
101
102 default:
103 return wxWindow::FromDIP( wxSize( 500, 400 ), aWindow );
104 }
105}
106
107
108static const wxSize defaultSize( FRAME_T aFrameType, wxWindow* aWindow )
109{
110 switch( aFrameType )
111 {
113 return wxWindow::FromDIP( wxSize( 850, 540 ), aWindow );
114
115 default:
116 return wxWindow::FromDIP( wxSize( 1280, 720 ), aWindow );
117 }
118}
119
120
121BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
122 // These event table entries are needed to handle events from the mac application menu
123 EVT_MENU( wxID_ABOUT, EDA_BASE_FRAME::OnKicadAbout )
124 EVT_MENU( wxID_PREFERENCES, EDA_BASE_FRAME::OnPreferences )
125
126 EVT_CHAR_HOOK( EDA_BASE_FRAME::OnCharHook )
127 EVT_MENU_OPEN( EDA_BASE_FRAME::OnMenuEvent )
128 EVT_MENU_CLOSE( EDA_BASE_FRAME::OnMenuEvent )
129 EVT_MENU_HIGHLIGHT_ALL( EDA_BASE_FRAME::OnMenuEvent )
130 EVT_MOVE( EDA_BASE_FRAME::OnMove )
131 EVT_SIZE( EDA_BASE_FRAME::OnSize )
132 EVT_MAXIMIZE( EDA_BASE_FRAME::OnMaximize )
133
134 EVT_SYS_COLOUR_CHANGED( EDA_BASE_FRAME::onSystemColorChange )
135 EVT_ICONIZE( EDA_BASE_FRAME::onIconize )
136
138 END_EVENT_TABLE()
139
140
142{
143 m_ident = aFrameType;
144 m_maximizeByDefault = false;
145 m_infoBar = nullptr;
146 m_settingsManager = nullptr;
147 m_fileHistory = nullptr;
148 m_supportsAutoSave = false;
149 m_autoSavePending = false;
151 m_isClosing = false;
152 m_isNonUserClose = false;
153 m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
154 m_autoSaveRequired = false;
157 m_frameSize = defaultSize( aFrameType, this );
158 m_displayIndex = -1;
159
160 m_auimgr.SetArtProvider( new WX_AUI_DOCK_ART() );
161
163
164 // Set a reasonable minimal size for the frame
165 wxSize minSize = minSizeLookup( aFrameType, this );
166 SetSizeHints( minSize.x, minSize.y, -1, -1, -1, -1 );
167
168 // Store dimensions of the user area of the main window.
169 GetClientSize( &m_frameSize.x, &m_frameSize.y );
170
171 Connect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER,
172 wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) );
173
174 // hook wxEVT_CLOSE_WINDOW so we can call SaveSettings(). This function seems
175 // to be called before any other hook for wxCloseEvent, which is necessary.
176 Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
177
178 initExitKey();
179}
180
181
182EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle,
183 const wxPoint& aPos, const wxSize& aSize, long aStyle,
184 const wxString& aFrameName, KIWAY* aKiway,
185 const EDA_IU_SCALE& aIuScale ) :
186 wxFrame( aParent, wxID_ANY, aTitle, aPos, aSize, aStyle, aFrameName ),
187 TOOLS_HOLDER(),
188 KIWAY_HOLDER( aKiway, KIWAY_HOLDER::FRAME ),
189 UNITS_PROVIDER( aIuScale, EDA_UNITS::MM )
190{
191 m_tbTopMain = nullptr;
192 m_tbTopAux = nullptr;
193 m_tbRight = nullptr;
194 m_tbLeft = nullptr;
195
196 commonInit( aFrameType );
197
198 Bind( wxEVT_DPI_CHANGED,
199 [&]( wxDPIChangedEvent& aEvent )
200 {
201#ifdef __WXMSW__
202 // Workaround to update toolbar sizes on MSW
203 if( m_auimgr.GetManagedWindow() )
204 {
205 wxAuiPaneInfoArray& panes = m_auimgr.GetAllPanes();
206
207 for( size_t ii = 0; ii < panes.GetCount(); ii++ )
208 {
209 wxAuiPaneInfo& pinfo = panes.Item( ii );
210 pinfo.best_size = pinfo.window->GetSize();
211
212 // But we still shouldn't make it too small.
213 pinfo.best_size.IncTo( pinfo.window->GetBestSize() );
214 pinfo.best_size.IncTo( pinfo.min_size );
215 }
216
217 m_auimgr.Update();
218 }
219#endif
220
221 aEvent.Skip();
222 } );
223}
224
225
226wxWindow* findQuasiModalDialog( wxWindow* aParent )
227{
228 for( wxWindow* child : aParent->GetChildren() )
229 {
230 if( DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( child ) )
231 {
232 if( dlg->IsQuasiModal() )
233 return dlg;
234
235 if( wxWindow* nestedDlg = findQuasiModalDialog( child ) )
236 return nestedDlg;
237 }
238 }
239
240 return nullptr;
241}
242
243
245{
246 if( wxWindow* dlg = ::findQuasiModalDialog( this ) )
247 return dlg;
248
249 // FIXME: CvPcb is currently implemented on top of KIWAY_PLAYER rather than DIALOG_SHIM,
250 // so we have to look for it separately.
251 if( m_ident == FRAME_SCH )
252 {
253 wxWindow* cvpcb = wxWindow::FindWindowByName( wxS( "CvpcbFrame" ) );
254
255 if( cvpcb )
256 return cvpcb;
257 }
258
259 return nullptr;
260}
261
262
263void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event )
264{
265 // Guard against re-entrant close events. GTK can deliver a second wxEVT_CLOSE_WINDOW
266 // while we are still processing the first one (e.g. during Destroy() calls), which leads
267 // to use-after-free crashes when child objects have already been torn down.
268 if( m_isClosing )
269 return;
270
271 // Don't allow closing when a quasi-modal is open.
272 wxWindow* quasiModal = findQuasiModalDialog();
273
274 if( quasiModal )
275 {
276 // Raise and notify; don't give the user a warning regarding "quasi-modal dialogs"
277 // when they have no idea what those are.
278 quasiModal->Raise();
279 wxBell();
280
281 if( event.CanVeto() )
282 event.Veto();
283
284 return;
285 }
286
287
288 if( event.GetId() == wxEVT_QUERY_END_SESSION
289 || event.GetId() == wxEVT_END_SESSION )
290 {
291 // End session means the OS is going to terminate us
292 m_isNonUserClose = true;
293 }
294
295 if( canCloseWindow( event ) )
296 {
297 m_isClosing = true;
298
299 if( m_infoBar )
300 m_infoBar->Dismiss();
301
302 APP_SETTINGS_BASE* cfg = config();
303
304 if( cfg )
305 SaveSettings( cfg ); // virtual, wxFrame specific
306
308
309 // Destroy (safe delete frame) this frame only in non modal mode.
310 // In modal mode, the caller will call Destroy().
311 if( !IsModal() )
312 Destroy();
313 }
314 else
315 {
316 if( event.CanVeto() )
317 event.Veto();
318 }
319}
320
321
323{
324 Disconnect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER,
325 wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) );
326 Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
327
328 delete m_autoSaveTimer;
329 delete m_fileHistory;
330
332
334
336}
337
338
339bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent )
340{
341#ifdef __WXMAC__
342 // Apple in its infinite wisdom will raise a disabled window before even passing
343 // us the event, so we have no way to stop it. Instead, we have to catch an
344 // improperly ordered disabled window and quasi-modal dialog here and reorder
345 // them.
346 if( !IsEnabled() && IsActive() )
347 {
348 wxWindow* dlg = findQuasiModalDialog();
349
350 if( dlg )
351 dlg->Raise();
352 }
353#endif
354
355#ifdef __WXMSW__
356 // When changing DPI to a lower value, somehow, called from wxNonOwnedWindow::HandleDPIChange,
357 // our sizers compute a min size that is larger than the old frame size. wx then sets this wrong size.
358 // This shouldn't be needed since the OS have already sent a size event.
359 // Avoid this wx behaviour by pretending we've processed the event even if we use Skip in handlers.
360 if( aEvent.GetEventType() == wxEVT_DPI_CHANGED )
361 {
362 wxFrame::ProcessEvent( aEvent );
363 return true;
364 }
365#endif
366
367 if( !wxFrame::ProcessEvent( aEvent ) )
368 return false;
369
370 if( Pgm().m_Quitting )
371 return true;
372
373 if( !m_isClosing && m_supportsAutoSave && IsShownOnScreen() && IsActive()
375 && GetAutoSaveInterval() > 0 )
376 {
377 if( !m_autoSavePending )
378 {
379 wxLogTrace( traceAutoSave, wxT( "Starting auto save timer." ) );
380 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
381 m_autoSavePending = true;
382 }
383 else if( m_autoSaveTimer->IsRunning() )
384 {
385 wxLogTrace( traceAutoSave, wxT( "Stopping auto save timer." ) );
386 m_autoSaveTimer->Stop();
387 m_autoSavePending = false;
388 }
389 }
390
391 return true;
392}
393
394
399
400
401void EDA_BASE_FRAME::onAutoSaveTimer( wxTimerEvent& aEvent )
402{
403 // Don't stomp on someone else's timer event.
404 if( aEvent.GetId() != ID_AUTO_SAVE_TIMER )
405 {
406 aEvent.Skip();
407 return;
408 }
409
410 if( !doAutoSave() )
411 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
412}
413
414
416{
417 m_autoSaveRequired = false;
418 m_autoSavePending = false;
419
420 // Use registered saver callbacks to snapshot editor state into .history and only commit
421 // if there are material changes.
422 if( !Prj().IsReadOnly() )
423 Kiway().LocalHistory().RunRegisteredSaversAndCommit( Prj().GetProjectPath(), wxS( "Autosave" ) );
424
425 return true;
426}
427
428
429void EDA_BASE_FRAME::OnCharHook( wxKeyEvent& aKeyEvent )
430{
431 wxLogTrace( kicadTraceKeyEvent, wxS( "EDA_BASE_FRAME::OnCharHook %s" ), dump( aKeyEvent ) );
432
433 // Key events can be filtered here.
434 // Currently no filtering is made.
435 aKeyEvent.Skip();
436}
437
438
439void EDA_BASE_FRAME::OnMenuEvent( wxMenuEvent& aEvent )
440{
441 if( !m_toolDispatcher )
442 aEvent.Skip();
443 else
444 m_toolDispatcher->DispatchWxEvent( aEvent );
445}
446
447
449{
451 std::placeholders::_1,
452 this,
453 aConditions );
454
455 m_uiUpdateMap[aID] = evtFunc;
456
457 Bind( wxEVT_UPDATE_UI, evtFunc, aID );
458}
459
460
462{
463 const auto it = m_uiUpdateMap.find( aID );
464
465 if( it == m_uiUpdateMap.end() )
466 return;
467
468 Unbind( wxEVT_UPDATE_UI, it->second, aID );
469}
470
471
472void EDA_BASE_FRAME::HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAME* aFrame,
473 ACTION_CONDITIONS aCond )
474{
475 bool checkRes = false;
476 bool enableRes = true;
477 bool showRes = true;
478 bool isCut = aEvent.GetId() == ACTIONS::cut.GetUIId();
479 bool isCopy = aEvent.GetId() == ACTIONS::copy.GetUIId();
480 bool isPaste = aEvent.GetId() == ACTIONS::paste.GetUIId();
481 SELECTION& selection = aFrame->GetCurrentSelection();
482
483 try
484 {
485 checkRes = aCond.checkCondition( selection );
486 enableRes = aCond.enableCondition( selection );
487 showRes = aCond.showCondition( selection );
488 }
489 catch( std::exception& )
490 {
491 // Something broke with the conditions, just skip the event.
492 aEvent.Skip();
493 return;
494 }
495
496 if( showRes && aEvent.GetId() == ACTIONS::undo.GetUIId() )
497 {
498 wxString msg = _( "Undo" );
499
500 if( enableRes )
501 msg += wxS( " " ) + aFrame->GetUndoActionDescription();
502
503 aEvent.SetText( msg );
504 }
505 else if( showRes && aEvent.GetId() == ACTIONS::redo.GetUIId() )
506 {
507 wxString msg = _( "Redo" );
508
509 if( enableRes )
510 msg += wxS( " " ) + aFrame->GetRedoActionDescription();
511
512 aEvent.SetText( msg );
513 }
514
515 if( isCut || isCopy || isPaste )
516 {
517 wxWindow* focus = wxWindow::FindFocus();
518 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
519
520 if( textEntry && isCut && textEntry->CanCut() )
521 enableRes = true;
522 else if( textEntry && isCopy && textEntry->CanCopy() )
523 enableRes = true;
524 else if( textEntry && isPaste && textEntry->CanPaste() )
525 enableRes = true;
526 else if( dynamic_cast<WX_GRID*>( focus ) )
527 enableRes = false; // Must disable menu in order to get command as CharHook event
528 }
529
530 aEvent.Enable( enableRes );
531 aEvent.Show( showRes );
532
533 if( aEvent.IsCheckable() )
534 aEvent.Check( checkRes );
535}
536
537
539{
540 // Setup the conditions to check a language menu item
541 auto isCurrentLang =
542 [] ( const SELECTION& aSel, int aLangIdentifier )
543 {
544 return Pgm().GetSelectedLanguageIdentifier() == aLangIdentifier;
545 };
546
547 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
548 {
550 cond.Check( std::bind( isCurrentLang, std::placeholders::_1,
551 LanguagesList[ii].m_WX_Lang_Identifier ) );
552 RegisterUIUpdateHandler( LanguagesList[ii].m_KI_Lang_Identifier, cond );
553 }
554}
555
556
558 const ACTION_TOOLBAR_CONTROL_FACTORY& aControlFactory )
559{
560 m_toolbarControlFactories.emplace( aControlDesc.GetName(), aControlFactory );
561}
562
563
565{
566 for( auto& control : m_toolbarControlFactories )
567 {
568 if( control.first == aName )
569 return &control.second;
570 }
571
572 return nullptr;
573}
574
575
579
580
582{
583 if( m_tbLeft )
584 m_tbLeft->SelectAction( aAction );
585
586 if( m_tbTopMain )
587 m_tbTopMain->SelectAction( aAction );
588
589 if( m_tbTopAux )
590 m_tbTopAux->SelectAction( aAction );
591
592 if( m_tbRight )
593 m_tbRight->SelectAction( aAction );
594}
595
596
598{
599 wxWindowUpdateLocker dummy( this );
600
601 wxASSERT( m_toolbarSettings );
602
603 std::optional<TOOLBAR_CONFIGURATION> tbConfig;
604
605 // Drawing tools (typically on right edge of window)
606 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::RIGHT, config()->m_CustomToolbars );
607
608 if( tbConfig.has_value() )
609 {
610 if( !m_tbRight )
611 {
612 m_tbRight =
613 new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
614 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
615 m_tbRight->SetAuiManager( &m_auimgr );
616 }
617
618 m_tbRight->ApplyConfiguration( tbConfig.value() );
619 }
620
621 // Options (typically on left edge of window)
622 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::LEFT, config()->m_CustomToolbars );
623
624 if( tbConfig.has_value() )
625 {
626 if( !m_tbLeft )
627 {
628 m_tbLeft = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
629 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
630 m_tbLeft->SetAuiManager( &m_auimgr );
631 }
632
633 m_tbLeft->ApplyConfiguration( tbConfig.value() );
634 }
635
636 // Top main toolbar (the top one)
637 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::TOP_MAIN, config()->m_CustomToolbars );
638
639 if( tbConfig.has_value() )
640 {
641 if( !m_tbTopMain )
642 {
643 m_tbTopMain = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
644 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT | wxAUI_TB_HORIZONTAL
645 | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
646 m_tbTopMain->SetAuiManager( &m_auimgr );
647 }
648
649 m_tbTopMain->ApplyConfiguration( tbConfig.value() );
650 }
651
652 // Top aux toolbar (the bottom one)
653 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::TOP_AUX, config()->m_CustomToolbars );
654
655 if( tbConfig.has_value() )
656 {
657 if( !m_tbTopAux )
658 {
659 m_tbTopAux = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
660 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT | wxAUI_TB_HORIZONTAL
661 | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
662 m_tbTopAux->SetAuiManager( &m_auimgr );
663 }
664
665 m_tbTopAux->ApplyConfiguration( tbConfig.value() );
666 }
667}
668
669
671{
672 if( m_tbTopMain )
673 m_tbTopMain->UpdateControlWidths();
674
675 if( m_tbRight )
676 m_tbRight->UpdateControlWidths();
677
678 if( m_tbLeft )
679 m_tbLeft->UpdateControlWidths();
680
681 if( m_tbTopAux )
682 m_tbTopAux->UpdateControlWidths();
683
684}
685
686
688{
689 if( m_tbTopMain )
690 m_auimgr.GetPane( m_tbTopMain ).MaxSize( m_tbTopMain->GetSize() );
691
692 if( m_tbRight )
693 m_auimgr.GetPane( m_tbRight ).MaxSize( m_tbRight->GetSize() );
694
695 if( m_tbLeft )
696 m_auimgr.GetPane( m_tbLeft ).MaxSize( m_tbLeft->GetSize() );
697
698 if( m_tbTopAux )
699 m_auimgr.GetPane( m_tbTopAux ).MaxSize( m_tbTopAux->GetSize() );
700
701 m_auimgr.Update();
702}
703
704
706{
713
714 CallAfter( [this]()
715 {
716 if( !m_isClosing )
718 } );
719}
720
721
722void EDA_BASE_FRAME::AddStandardHelpMenu( wxMenuBar* aMenuBar )
723{
724 COMMON_CONTROL* commonControl = m_toolManager->GetTool<COMMON_CONTROL>();
725 ACTION_MENU* helpMenu = new ACTION_MENU( false, commonControl );
726
727 helpMenu->Add( ACTIONS::help );
728 helpMenu->Add( ACTIONS::gettingStarted );
729 helpMenu->Add( ACTIONS::listHotKeys );
730 helpMenu->Add( ACTIONS::getInvolved );
731 helpMenu->Add( ACTIONS::donate );
732 helpMenu->Add( ACTIONS::reportBug );
733
734 helpMenu->AppendSeparator();
735 helpMenu->Add( ACTIONS::about );
736
737 aMenuBar->Append( helpMenu, _( "&Help" ) );
738}
739
740
741
743{
744 wxString menuItemLabel = aAction.GetMenuLabel();
745 wxMenuBar* menuBar = GetMenuBar();
746
747 for( size_t ii = 0; ii < menuBar->GetMenuCount(); ++ii )
748 {
749 for( wxMenuItem* menuItem : menuBar->GetMenu( ii )->GetMenuItems() )
750 {
751 if( menuItem->GetItemLabelText() == menuItemLabel )
752 {
753 wxString menuTitleLabel = menuBar->GetMenuLabelText( ii );
754
755 menuTitleLabel.Replace( wxS( "&" ), wxS( "&&" ) );
756 menuItemLabel.Replace( wxS( "&" ), wxS( "&&" ) );
757
758 return wxString::Format( _( "Run: %s > %s" ),
759 menuTitleLabel,
760 menuItemLabel );
761 }
762 }
763 }
764
765 return wxString::Format( _( "Run: %s" ), aAction.GetFriendlyName() );
766};
767
768
770{
772
773 if( GetMenuBar() )
774 {
776 GetMenuBar()->Refresh();
777 }
778}
779
780
782{
784
785 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
786
787#ifdef KICAD_IPC_API
788 bool running = Pgm().GetApiServer().Running();
789
790 if( running && !settings->m_Api.enable_server )
791 Pgm().GetApiServer().Stop();
792 else if( !running && settings->m_Api.enable_server )
793 Pgm().GetApiServer().Start();
794#endif
795
796 if( m_fileHistory )
797 {
798 int historySize = settings->m_System.file_history_size;
799 m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) );
800 }
801
802 if( Pgm().GetCommonSettings()->m_Backup.enabled )
803 Kiway().LocalHistory().Init( Prj().GetProjectPath() );
804
806 ThemeChanged();
807
808 if( GetMenuBar() )
809 {
810 // For icons in menus, icon scaling & hotkeys
812 GetMenuBar()->Refresh();
813 }
814
815 // Update the toolbars
817}
818
819
821{
823
824 // Update all the toolbars to have new icons
825 wxAuiPaneInfoArray panes = m_auimgr.GetAllPanes();
826
827 for( size_t i = 0; i < panes.GetCount(); ++i )
828 {
829 if( ACTION_TOOLBAR* toolbar = dynamic_cast<ACTION_TOOLBAR*>( panes[i].window ) )
830 toolbar->RefreshBitmaps();
831 }
832}
833
834
835void EDA_BASE_FRAME::OnSize( wxSizeEvent& aEvent )
836{
837#ifdef __WXMAC__
838 int currentDisplay = wxDisplay::GetFromWindow( this );
839
840 if( m_displayIndex >= 0 && currentDisplay >= 0 && currentDisplay != m_displayIndex )
841 {
842 wxLogTrace( traceDisplayLocation, wxS( "OnSize: current display changed %d to %d" ),
843 m_displayIndex, currentDisplay );
844 m_displayIndex = currentDisplay;
846 }
847#endif
848
849 aEvent.Skip();
850}
851
852
853void EDA_BASE_FRAME::LoadWindowState( const wxString& aFileName )
854{
855 if( !Pgm().GetCommonSettings()->m_Session.remember_open_files )
856 return;
857
858 const PROJECT_FILE_STATE* state = Prj().GetLocalSettings().GetFileState( aFileName );
859
860 if( state != nullptr )
861 {
862 LoadWindowState( state->window );
863 }
864}
865
866
868{
869 bool wasDefault = false;
870
871 m_framePos.x = aState.pos_x;
872 m_framePos.y = aState.pos_y;
873 m_frameSize.x = aState.size_x;
874 m_frameSize.y = aState.size_y;
875
876 wxLogTrace( traceDisplayLocation, wxS( "Config position (%d, %d) with size (%d, %d)" ),
878
879 // Ensure minimum size is set if the stored config was zero-initialized
880 wxSize minSize = minSizeLookup( m_ident, this );
881
882 if( m_frameSize.x < minSize.x || m_frameSize.y < minSize.y )
883 {
885 wasDefault = true;
886
887 wxLogTrace( traceDisplayLocation, wxS( "Using minimum size (%d, %d)" ),
889 }
890
891 wxLogTrace( traceDisplayLocation, wxS( "Number of displays: %d" ), wxDisplay::GetCount() );
892
893 if( aState.display >= wxDisplay::GetCount() )
894 {
895 wxLogTrace( traceDisplayLocation, wxS( "Previous display not found" ) );
896
897 // If it isn't attached, use the first display
898 // Warning wxDisplay has 2 ctor variants. the parameter needs a type:
899 const unsigned int index = 0;
900 wxDisplay display( index );
901 wxRect clientSize = display.GetGeometry();
902
903 m_framePos = wxDefaultPosition;
904
905 // Ensure the window fits on the display, since the other one could have been larger
906 if( m_frameSize.x > clientSize.width )
907 m_frameSize.x = clientSize.width;
908
909 if( m_frameSize.y > clientSize.height )
910 m_frameSize.y = clientSize.height;
911 }
912 else
913 {
914 wxPoint upperRight( m_framePos.x + m_frameSize.x, m_framePos.y );
915 wxPoint upperLeft( m_framePos.x, m_framePos.y );
916
917 wxDisplay display( aState.display );
918 wxRect clientSize = display.GetClientArea();
919
920 int yLimTop = clientSize.y;
921 int yLimBottom = clientSize.y + clientSize.height;
922 int xLimLeft = clientSize.x;
923 int xLimRight = clientSize.x + clientSize.width;
924
925 if( upperLeft.x > xLimRight || // Upper left corner too close to right edge of screen
926 upperRight.x < xLimLeft || // Upper right corner too close to left edge of screen
927 upperLeft.y < yLimTop || // Upper corner too close to the bottom of the screen
928 upperLeft.y > yLimBottom )
929 {
930 m_framePos = wxDefaultPosition;
931 wxLogTrace( traceDisplayLocation, wxS( "Resetting to default position" ) );
932 }
933 }
934
935 wxLogTrace( traceDisplayLocation, wxS( "Final window position (%d, %d) with size (%d, %d)" ),
937
938 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
939
940 // Center the window if we reset to default
941 if( m_framePos.x == -1 )
942 {
943 wxLogTrace( traceDisplayLocation, wxS( "Centering window" ) );
944 Center();
945 m_framePos = GetPosition();
946 }
947
948 // Record the frame sizes in an un-maximized state
951
952 // Maximize if we were maximized before
953 if( aState.maximized || ( wasDefault && m_maximizeByDefault ) )
954 {
955 wxLogTrace( traceDisplayLocation, wxS( "Maximizing window" ) );
956 Maximize();
957 }
958
959 m_displayIndex = wxDisplay::GetFromWindow( this );
960}
961
962
964{
965 wxDisplay display( wxDisplay::GetFromWindow( this ) );
966 wxRect clientSize = display.GetClientArea();
967 wxPoint pos = GetPosition();
968 wxSize size = GetWindowSize();
969
970 wxLogTrace( traceDisplayLocation,
971 wxS( "ensureWindowIsOnScreen: clientArea (%d, %d) w %d h %d" ),
972 clientSize.x, clientSize.y,
973 clientSize.width, clientSize.height );
974
975 if( pos.y < clientSize.y )
976 {
977 wxLogTrace( traceDisplayLocation,
978 wxS( "ensureWindowIsOnScreen: y pos %d below minimum, setting to %d" ), pos.y,
979 clientSize.y );
980 pos.y = clientSize.y;
981 }
982
983 if( pos.x < clientSize.x )
984 {
985 wxLogTrace( traceDisplayLocation,
986 wxS( "ensureWindowIsOnScreen: x pos %d is off the client rect, setting to %d" ),
987 pos.x, clientSize.x );
988 pos.x = clientSize.x;
989 }
990
991 if( pos.x + size.x - clientSize.x > clientSize.width )
992 {
993 int newWidth = clientSize.width - ( pos.x - clientSize.x );
994 wxLogTrace( traceDisplayLocation,
995 wxS( "ensureWindowIsOnScreen: effective width %d above available %d, setting "
996 "to %d" ), pos.x + size.x, clientSize.width, newWidth );
997 size.x = newWidth;
998 }
999
1000 if( pos.y + size.y - clientSize.y > clientSize.height )
1001 {
1002 int newHeight = clientSize.height - ( pos.y - clientSize.y );
1003 wxLogTrace( traceDisplayLocation,
1004 wxS( "ensureWindowIsOnScreen: effective height %d above available %d, setting "
1005 "to %d" ), pos.y + size.y, clientSize.height, newHeight );
1006 size.y = newHeight;
1007 }
1008
1009 wxLogTrace( traceDisplayLocation, wxS( "Updating window position (%d, %d) with size (%d, %d)" ),
1010 pos.x, pos.y, size.x, size.y );
1011
1012 SetSize( pos.x, pos.y, size.x, size.y );
1013}
1014
1015
1017{
1018 LoadWindowState( aCfg->state );
1019
1020 m_perspective = aCfg->perspective;
1021 m_auiLayoutState = std::make_unique<nlohmann::json>( aCfg->aui_state );
1022 m_mruPath = aCfg->mru_path;
1023
1025}
1026
1027
1029{
1030 if( IsIconized() )
1031 return;
1032
1033 // If the window is maximized, we use the saved window size from before it was maximized
1034 if( IsMaximized() )
1035 {
1038 }
1039 else
1040 {
1042 m_framePos = GetPosition();
1043 }
1044
1045 aCfg->state.pos_x = m_framePos.x;
1046 aCfg->state.pos_y = m_framePos.y;
1047 aCfg->state.size_x = m_frameSize.x;
1048 aCfg->state.size_y = m_frameSize.y;
1049 aCfg->state.maximized = IsMaximized();
1050 aCfg->state.display = wxDisplay::GetFromWindow( this );
1051
1052 wxLogTrace( traceDisplayLocation, wxS( "Saving window maximized: %s" ),
1053 IsMaximized() ? wxS( "true" ) : wxS( "false" ) );
1054 wxLogTrace( traceDisplayLocation, wxS( "Saving config position (%d, %d) with size (%d, %d)" ),
1056
1057 // Once this is fully implemented, wxAuiManager will be used to maintain
1058 // the persistence of the main frame and all it's managed windows and
1059 // all of the legacy frame persistence position code can be removed.
1060#if wxCHECK_VERSION( 3, 3, 0 )
1061 {
1062 WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
1063 nlohmann::json state = serializer.Serialize();
1064
1065 if( state.is_null() || state.empty() )
1066 aCfg->aui_state = nlohmann::json();
1067 else
1068 aCfg->aui_state = state;
1069
1070 aCfg->perspective.clear();
1071 }
1072#else
1073 aCfg->perspective = m_auimgr.SavePerspective().ToStdString();
1074 aCfg->aui_state = nlohmann::json();
1075#endif
1076
1077 aCfg->mru_path = m_mruPath;
1078}
1079
1080
1082{
1084
1085 // Get file history size from common settings
1086 int fileHistorySize = Pgm().GetCommonSettings()->m_System.file_history_size;
1087
1088 // Load the recently used files into the history menu
1089 m_fileHistory = new FILE_HISTORY( (unsigned) std::max( 1, fileHistorySize ),
1091 m_fileHistory->Load( *aCfg );
1092}
1093
1094
1096{
1097 wxCHECK( config(), /* void */ );
1098
1100
1101 bool fileOpen = m_isClosing && m_isNonUserClose;
1102
1103 wxString currentlyOpenedFile = GetCurrentFileName();
1104
1105 if( Pgm().GetCommonSettings()->m_Session.remember_open_files && !currentlyOpenedFile.IsEmpty() )
1106 {
1107 wxFileName rfn( currentlyOpenedFile );
1108 rfn.MakeRelativeTo( Prj().GetProjectPath() );
1109 Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &aCfg->m_Window, fileOpen );
1110 }
1111
1112 // Save the recently used files list
1113 if( m_fileHistory )
1114 {
1115 // Save the currently opened file in the file history
1116 if( !currentlyOpenedFile.IsEmpty() )
1117 UpdateFileHistory( currentlyOpenedFile );
1118
1119 m_fileHistory->Save( *aCfg );
1120 }
1121}
1122
1123
1128
1129
1131{
1132 // KICAD_MANAGER_FRAME overrides this
1133 return Kiface().KifaceSettings();
1134}
1135
1136
1138{
1139 return Kiface().KifaceSearch();
1140}
1141
1142
1144{
1145 return Kiface().GetHelpFileName();
1146}
1147
1148
1149void EDA_BASE_FRAME::PrintMsg( const wxString& text )
1150{
1151 SetStatusText( text );
1152}
1153
1154
1156{
1157#if defined( __WXOSX_MAC__ )
1159#else
1160 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
1161
1162 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) ).Top().Layer(1) );
1163#endif
1164}
1165
1166
1168{
1169#if defined( __WXOSX_MAC__ )
1170 m_auimgr.Update();
1171#else
1172 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
1173 // hiding it.
1174 m_auimgr.Update();
1175
1176 // We don't want the infobar displayed right away
1177 m_auimgr.GetPane( wxS( "InfoBar" ) ).Hide();
1178 m_auimgr.Update();
1179#endif
1180}
1181
1182
1184{
1185 if( !ADVANCED_CFG::GetCfg().m_EnableUseAuiPerspective )
1186 return;
1187
1188 bool restored = false;
1189
1190#if wxCHECK_VERSION( 3, 3, 0 )
1191 if( m_auiLayoutState && !m_auiLayoutState->is_null() && !m_auiLayoutState->empty() )
1192 {
1193 WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
1194
1195 if( serializer.Deserialize( *m_auiLayoutState ) )
1196 restored = true;
1197 }
1198#endif
1199
1200 /*
1201 * Legacy loading of the string AUI perspective (if it exists). This is needed for
1202 * wx 3.2 or the first settings upgrade when wx 3.3 is used in KiCad (e.g., 9.0->10.0 for Windows and macOS).
1203 */
1204 if( !restored && !m_perspective.IsEmpty() )
1205 {
1206 m_auimgr.LoadPerspective( m_perspective );
1207
1208 // Workaround for wx 3.2: LoadPerspective() hides all panes first, then shows only
1209 // those in the saved string. If toolbar names changed or new toolbars were added,
1210 // they'd stay hidden. Ensure all toolbars are visible after restore.
1211 wxAuiPaneInfoArray& panes = m_auimgr.GetAllPanes();
1212
1213 for( size_t i = 0; i < panes.GetCount(); ++i )
1214 {
1215 if( panes.Item( i ).IsToolbar() )
1216 panes.Item( i ).Show( true );
1217 }
1218 }
1219}
1220
1221
1222void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
1223 INFOBAR_MESSAGE_TYPE aType )
1224{
1225 m_infoBar->RemoveAllButtons();
1226
1227 if( aShowCloseButton )
1228 m_infoBar->AddCloseButton();
1229
1230 GetInfoBar()->ShowMessageFor( aErrorMsg, 8000, wxICON_ERROR, aType );
1231}
1232
1233
1234void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
1235 std::function<void(void)> aCallback )
1236{
1237 m_infoBar->RemoveAllButtons();
1238
1239 if( aShowCloseButton )
1240 m_infoBar->AddCloseButton();
1241
1242 if( aCallback )
1243 m_infoBar->SetCallback( aCallback );
1244
1245 GetInfoBar()->ShowMessageFor( aErrorMsg, 6000, wxICON_ERROR );
1246}
1247
1248
1249void EDA_BASE_FRAME::ShowInfoBarWarning( const wxString& aWarningMsg, bool aShowCloseButton )
1250{
1251 m_infoBar->RemoveAllButtons();
1252
1253 if( aShowCloseButton )
1254 m_infoBar->AddCloseButton();
1255
1256 GetInfoBar()->ShowMessageFor( aWarningMsg, 6000, wxICON_WARNING );
1257}
1258
1259
1260void EDA_BASE_FRAME::ShowInfoBarMsg( const wxString& aMsg, bool aShowCloseButton )
1261{
1262 m_infoBar->RemoveAllButtons();
1263
1264 if( aShowCloseButton )
1265 m_infoBar->AddCloseButton();
1266
1267 GetInfoBar()->ShowMessageFor( aMsg, 8000, wxICON_INFORMATION );
1268}
1269
1270
1271void EDA_BASE_FRAME::UpdateFileHistory( const wxString& FullFileName, FILE_HISTORY* aFileHistory )
1272{
1273 if( !aFileHistory )
1274 aFileHistory = m_fileHistory;
1275
1276 wxASSERT( aFileHistory );
1277
1278 aFileHistory->AddFileToHistory( FullFileName );
1279
1280 // Update the menubar to update the file history menu
1281 if( !m_isClosing && GetMenuBar() )
1282 {
1284 GetMenuBar()->Refresh();
1285 }
1286}
1287
1288
1289wxString EDA_BASE_FRAME::GetFileFromHistory( int cmdId, const wxString& type, FILE_HISTORY* aFileHistory )
1290{
1291 if( !aFileHistory )
1292 aFileHistory = m_fileHistory;
1293
1294 wxASSERT( aFileHistory );
1295
1296 int baseId = aFileHistory->GetBaseId();
1297
1298 wxASSERT( cmdId >= baseId && cmdId < baseId + (int) aFileHistory->GetCount() );
1299 int i = cmdId - baseId;
1300
1301 wxString fn = aFileHistory->GetHistoryFile( i );
1302
1303 if( !wxFileName::FileExists( fn ) )
1304 {
1305 KICAD_MESSAGE_DIALOG dlg( this, wxString::Format( _( "File '%s' was not found.\n" ), fn ), _( "Error" ),
1306 wxYES_NO | wxYES_DEFAULT | wxICON_ERROR | wxCENTER );
1307
1308 dlg.SetExtendedMessage( _( "Do you want to remove it from list of recently opened files?" ) );
1309 dlg.SetYesNoLabels( KICAD_MESSAGE_DIALOG::ButtonLabel( _( "Remove" ) ),
1310 KICAD_MESSAGE_DIALOG::ButtonLabel( _( "Keep" ) ) );
1311
1312 if( dlg.ShowModal() == wxID_YES )
1313 aFileHistory->RemoveFileFromHistory( i );
1314
1315 fn.Clear();
1316 }
1317
1318 // Update the menubar to update the file history menu
1319 if( GetMenuBar() )
1320 {
1322 GetMenuBar()->Refresh();
1323 }
1324
1325 return fn;
1326}
1327
1328
1330{
1331 wxASSERT( m_fileHistory );
1332
1333 m_fileHistory->ClearFileHistory();
1334
1335 // Update the menubar to update the file history menu
1336 if( GetMenuBar() )
1337 {
1339 GetMenuBar()->Refresh();
1340 }
1341}
1342
1343
1344void EDA_BASE_FRAME::OnKicadAbout( wxCommandEvent& event )
1345{
1346 void ShowAboutDialog( EDA_BASE_FRAME * aParent ); // See AboutDialog_main.cpp
1347 ShowAboutDialog( this );
1348}
1349
1350
1351void EDA_BASE_FRAME::OnPreferences( wxCommandEvent& event )
1352{
1353 ShowPreferences( wxEmptyString, wxEmptyString );
1354}
1355
1356
1357void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParentPage )
1358{
1359 PAGED_DIALOG dlg( this, _( "Preferences" ), true, true, wxEmptyString,
1360 wxWindow::FromDIP( wxSize( 980, 560 ), nullptr ) );
1361
1362 dlg.SetEvtHandlerEnabled( false );
1363
1364 {
1365 WX_BUSY_INDICATOR busy_cursor;
1366
1367 WX_TREEBOOK* book = dlg.GetTreebook();
1368 PANEL_HOTKEYS_EDITOR* hotkeysPanel = new PANEL_HOTKEYS_EDITOR( this, book );
1369 std::vector<int> expand;
1370
1371 wxWindow* kicadMgr_window = wxWindow::FindWindowByName( KICAD_MANAGER_FRAME_NAME );
1372
1373 if( KICAD_MANAGER_FRAME* kicadMgr = static_cast<KICAD_MANAGER_FRAME*>( kicadMgr_window ) )
1374 {
1375 ACTION_MANAGER* actionMgr = kicadMgr->GetToolManager()->GetActionManager();
1376
1377 for( const auto& [name, action] : actionMgr->GetActions() )
1378 hotkeysPanel->ActionsList().push_back( action );
1379 }
1380
1381 book->AddLazyPage(
1382 []( wxWindow* aParent ) -> wxWindow*
1383 {
1384 return new PANEL_COMMON_SETTINGS( aParent );
1385 },
1386 _( "Common" ) );
1387
1388 book->AddLazyPage(
1389 []( wxWindow* aParent ) -> wxWindow*
1390 {
1391 return new PANEL_MOUSE_SETTINGS( aParent );
1392 }, _( "Mouse and Touchpad" ) );
1393
1394#if defined(__linux__) || defined(__FreeBSD__)
1395 book->AddLazyPage(
1396 [] ( wxWindow* aParent ) -> wxWindow*
1397 {
1398 return new PANEL_SPACEMOUSE( aParent );
1399 }, _( "SpaceMouse" ) );
1400#endif
1401
1402 book->AddPage( hotkeysPanel, _( "Hotkeys" ) );
1403
1404 book->AddLazyPage(
1405 []( wxWindow* aParent ) -> wxWindow*
1406 {
1407 return new PANEL_GIT_REPOS( aParent );
1408 }, _( "Version Control" ) );
1409
1410#ifdef KICAD_USE_SENTRY
1411 book->AddLazyPage(
1412 []( wxWindow* aParent ) -> wxWindow*
1413 {
1414 return new PANEL_DATA_COLLECTION( aParent );
1415 }, _( "Data Collection" ) );
1416#endif
1417
1418#define LAZY_CTOR( key ) \
1419 [this, kiface]( wxWindow* aParent ) \
1420 { \
1421 return kiface->CreateKiWindow( aParent, key, &Kiway() ); \
1422 }
1423
1424 // If a dll is not loaded, the loader will show an error message.
1425
1426 try
1427 {
1428 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_SCH ) )
1429 {
1430 kiface->GetActions( hotkeysPanel->ActionsList() );
1431
1433 expand.push_back( (int) book->GetPageCount() );
1434
1435 book->AddPage( new wxPanel( book ), _( "Symbol Editor" ) );
1436 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_DISP_OPTIONS ), _( "Display Options" ) );
1437 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_GRIDS ), _( "Grids" ) );
1438 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_OPTIONS ), _( "Editing Options" ) );
1439 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_COLORS ), _( "Colors" ) );
1440 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_TOOLBARS ), _( "Toolbars" ) );
1441
1442 if( GetFrameType() == FRAME_SCH )
1443 expand.push_back( (int) book->GetPageCount() );
1444
1445 book->AddPage( new wxPanel( book ), _( "Schematic Editor" ) );
1446 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DISP_OPTIONS ), _( "Display Options" ) );
1447 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_GRIDS ), _( "Grids" ) );
1448 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_EDIT_OPTIONS ), _( "Editing Options" ) );
1449 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_COLORS ), _( "Colors" ) );
1450 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_TOOLBARS ), _( "Toolbars" ) );
1451 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) );
1452 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DATA_SOURCES ), _( "Data Sources" ) );
1453 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_SIMULATOR ), _( "Simulator" ) );
1454 }
1455 }
1456 catch( ... )
1457 {
1458 }
1459
1460 try
1461 {
1462 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_PCB ) )
1463 {
1464 kiface->GetActions( hotkeysPanel->ActionsList() );
1465
1467 expand.push_back( (int) book->GetPageCount() );
1468
1469 book->AddPage( new wxPanel( book ), _( "Footprint Editor" ) );
1470 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DISPLAY_OPTIONS ), _( "Display Options" ) );
1471 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_GRIDS ), _( "Grids" ) );
1472 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_ORIGINS_AXES ), _( "Origins & Axes" ) );
1473 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_EDIT_OPTIONS ), _( "Editing Options" ) );
1474 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_COLORS ), _( "Colors" ) );
1475 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_TOOLBARS ), _( "Toolbars" ) );
1476 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_FIELDS ), _( "Footprint Defaults" ) );
1477 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_GRAPHICS_VALUES ), _( "Graphics Defaults" ) );
1478 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_USER_LAYER_NAMES ), _( "User Layer Names" ) );
1479
1481 expand.push_back( (int) book->GetPageCount() );
1482
1483 book->AddPage( new wxPanel( book ), _( "PCB Editor" ) );
1484 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_DISPLAY_OPTS ), _( "Display Options" ) );
1485 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_GRIDS ), _( "Grids" ) );
1486 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ORIGINS_AXES ), _( "Origins & Axes" ) );
1487 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_EDIT_OPTIONS ), _( "Editing Options" ) );
1488 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_COLORS ), _( "Colors" ) );
1489 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_TOOLBARS ), _( "Toolbars" ) );
1490 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ACTION_PLUGINS ), _( "Plugins" ) );
1491
1493 expand.push_back( (int) book->GetPageCount() );
1494
1495 book->AddPage( new wxPanel( book ), _( "3D Viewer" ) );
1496 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_DISPLAY_OPTIONS ), _( "General" ) );
1497 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_TOOLBARS ), _( "Toolbars" ) );
1498 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_OPENGL ), _( "Realtime Renderer" ) );
1499 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_RAYTRACING ), _( "Raytracing Renderer" ) );
1500 }
1501 }
1502 catch( ... )
1503 {
1504 }
1505
1506 try
1507 {
1508 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_GERBVIEW ) )
1509 {
1510 kiface->GetActions( hotkeysPanel->ActionsList() );
1511
1512 if( GetFrameType() == FRAME_GERBER )
1513 expand.push_back( (int) book->GetPageCount() );
1514
1515 book->AddPage( new wxPanel( book ), _( "Gerber Viewer" ) );
1516 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
1517 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_COLORS ), _( "Colors" ) );
1518 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_TOOLBARS ), _( "Toolbars" ) );
1519 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_GRIDS ), _( "Grids" ) );
1520 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
1521 }
1522 }
1523 catch( ... )
1524 {
1525 }
1526
1527 try
1528 {
1529 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_PL_EDITOR ) )
1530 {
1531 kiface->GetActions( hotkeysPanel->ActionsList() );
1532
1533 if( GetFrameType() == FRAME_PL_EDITOR )
1534 expand.push_back( (int) book->GetPageCount() );
1535
1536 book->AddPage( new wxPanel( book ), _( "Drawing Sheet Editor" ) );
1537 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
1538 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_GRIDS ), _( "Grids" ) );
1539 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_COLORS ), _( "Colors" ) );
1540 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_TOOLBARS ), _( "Toolbars" ) );
1541
1542 book->AddLazyPage(
1543 []( wxWindow* aParent ) -> wxWindow*
1544 {
1545 return new PANEL_PACKAGES_AND_UPDATES( aParent );
1546 }, _( "Packages and Updates" ) );
1547 }
1548 }
1549 catch( ... )
1550 {
1551 }
1552
1553#ifdef KICAD_IPC_API
1554 book->AddPage( new PANEL_PLUGIN_SETTINGS( book ), _( "Plugins" ) );
1555#endif
1556
1557 book->AddPage( new PANEL_MAINTENANCE( book, this ), _( "Maintenance" ) );
1558
1559 // Update all of the action hotkeys. The process of loading the actions through
1560 // the KiFACE will only get us the default hotkeys
1561 ReadHotKeyConfigIntoActions( wxEmptyString, hotkeysPanel->ActionsList() );
1562
1563 for( size_t i = 0; i < book->GetPageCount(); ++i )
1564 book->GetPage( i )->Layout();
1565
1566 for( int page : expand )
1567 book->ExpandNode( page );
1568
1569 if( !aStartPage.IsEmpty() )
1570 dlg.SetInitialPage( aStartPage, aStartParentPage );
1571
1572 dlg.SetEvtHandlerEnabled( true );
1573#undef LAZY_CTOR
1574 }
1575
1576 if( dlg.ShowModal() == wxID_OK )
1577 {
1578 // Update our grids that are cached in the tool
1579 m_toolManager->ResetTools( TOOL_BASE::REDRAW );
1582 }
1583
1584}
1585
1586
1587void EDA_BASE_FRAME::OnDropFiles( wxDropFilesEvent& aEvent )
1588{
1589 Raise();
1590
1591 wxString* files = aEvent.GetFiles();
1592
1593 for( int nb = 0; nb < aEvent.GetNumberOfFiles(); nb++ )
1594 {
1595 const wxFileName fn = wxFileName( files[nb] );
1596 wxString ext = fn.GetExt();
1597
1598 // Alias all gerber files as GerberFileExtension
1601
1602 if( m_acceptedExts.find( ext.ToStdString() ) != m_acceptedExts.end() )
1603 m_AcceptedFiles.emplace_back( fn );
1604 }
1605
1607 m_AcceptedFiles.clear();
1608}
1609
1610
1612{
1613 for( const wxFileName& file : m_AcceptedFiles )
1614 {
1615 wxString fn = file.GetFullPath();
1616 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( file.GetExt() ), &fn );
1617 }
1618}
1619
1620
1621bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
1622{
1623 wxString msg;
1624 wxFileName fn = aFileName;
1625
1626 // Check for absence of a file path with a file name. Unfortunately KiCad
1627 // uses paths relative to the current project path without the ./ part which
1628 // confuses wxFileName. Making the file name path absolute may be less than
1629 // elegant but it solves the problem.
1630 if( fn.GetPath().IsEmpty() && fn.HasName() )
1631 fn.MakeAbsolute();
1632
1633 wxCHECK_MSG( fn.IsOk(), false,
1634 wxT( "File name object is invalid. Bad programmer!" ) );
1635 wxCHECK_MSG( !fn.GetPath().IsEmpty(), false,
1636 wxT( "File name object path <" ) + fn.GetFullPath() +
1637 wxT( "> is not set. Bad programmer!" ) );
1638
1639 if( fn.IsDir() && !fn.IsDirWritable() )
1640 {
1641 msg.Printf( _( "Insufficient permissions to folder '%s'." ), fn.GetPath() );
1642 }
1643 else if( !fn.FileExists() && !fn.IsDirWritable() )
1644 {
1645 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1646 }
1647 else if( fn.FileExists() && !fn.IsFileWritable() )
1648 {
1649 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1650 }
1651
1652 if( !msg.IsEmpty() )
1653 {
1654 if( aVerbose )
1655 DisplayErrorMessage( this, msg );
1656
1657 return false;
1658 }
1659
1660 return true;
1661}
1662
1663
1665{
1666 // This function should be overridden in child classes
1667 return false;
1668}
1669
1670
1672{
1673 wxAcceleratorEntry entries[1];
1674 entries[0].Set( wxACCEL_CTRL, int( 'Q' ), wxID_EXIT );
1675 wxAcceleratorTable accel( 1, entries );
1676 SetAcceleratorTable( accel );
1677}
1678
1679
1685
1686
1688{
1689 m_undoList.PushCommand( aNewitem );
1690
1691 // Delete the extra items, if count max reached
1692 if( m_undoRedoCountMax > 0 )
1693 {
1694 int extraitems = GetUndoCommandCount() - m_undoRedoCountMax;
1695
1696 if( extraitems > 0 )
1697 ClearUndoORRedoList( UNDO_LIST, extraitems );
1698 }
1699}
1700
1701
1703{
1704 m_redoList.PushCommand( aNewitem );
1705
1706 // Delete the extra items, if count max reached
1707 if( m_undoRedoCountMax > 0 )
1708 {
1709 int extraitems = GetRedoCommandCount() - m_undoRedoCountMax;
1710
1711 if( extraitems > 0 )
1712 ClearUndoORRedoList( REDO_LIST, extraitems );
1713 }
1714}
1715
1716
1721
1722
1727
1728
1730{
1731 if( GetUndoCommandCount() > 0 )
1732 return m_undoList.m_CommandsList.back()->GetDescription();
1733
1734 return wxEmptyString;
1735}
1736
1737
1739{
1740 if( GetRedoCommandCount() > 0 )
1741 return m_redoList.m_CommandsList.back()->GetDescription();
1742
1743 return wxEmptyString;
1744}
1745
1746
1748{
1749 m_autoSaveRequired = true;
1750}
1751
1752
1754{
1755 SetUserUnits( aUnits );
1757
1758 wxCommandEvent e( EDA_EVT_UNITS_CHANGED );
1759 e.SetInt( static_cast<int>( aUnits ) );
1760 e.SetClientData( this );
1761 ProcessEventLocally( e );
1762}
1763
1764
1765void EDA_BASE_FRAME::OnMaximize( wxMaximizeEvent& aEvent )
1766{
1767 // When we maximize the window, we want to save the old information
1768 // so that we can add it to the settings on next window load.
1769 // Contrary to the documentation, this event seems to be generated
1770 // when the window is also being unmaximized on OSX, so we only
1771 // capture the size information when we maximize the window when on OSX.
1772#ifdef __WXOSX__
1773 if( !IsMaximized() )
1774#endif
1775 {
1777 m_normalFramePos = GetPosition();
1778 wxLogTrace( traceDisplayLocation,
1779 "Maximizing window - Saving position (%d, %d) with size (%d, %d)",
1782 }
1783
1784 // Skip event to actually maximize the window
1785 aEvent.Skip();
1786}
1787
1788
1790{
1791#if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 2, 9 )
1792 wxSize winSize = GetSize();
1793
1794 // GTK includes the window decorations in the normal GetSize call,
1795 // so we have to use a GTK-specific sizing call that returns the
1796 // non-decorated window size.
1798 {
1799 int width = 0;
1800 int height = 0;
1801 GTKDoGetSize( &width, &height );
1802
1803 winSize.Set( width, height );
1804 }
1805#else
1806 wxSize winSize = GetSize();
1807#endif
1808
1809 return winSize;
1810}
1811
1812
1814{
1815 // Update the icon theme when the system theme changes and update the toolbars
1817 ThemeChanged();
1818
1819 // This isn't handled by ThemeChanged()
1820 if( GetMenuBar() )
1821 {
1822 // For icons in menus, icon scaling & hotkeys
1824 GetMenuBar()->Refresh();
1825 }
1826}
1827
1828
1829void EDA_BASE_FRAME::onSystemColorChange( wxSysColourChangedEvent& aEvent )
1830{
1831 // Call the handler to update the colors used in the frame
1833
1834 // Skip the change event to ensure the rest of the window controls get it
1835 aEvent.Skip();
1836}
1837
1838
1839void EDA_BASE_FRAME::onIconize( wxIconizeEvent& aEvent )
1840{
1841 // Call the handler
1842 handleIconizeEvent( aEvent );
1843
1844 // Skip the event.
1845 aEvent.Skip();
1846}
1847
1848
1849#ifdef __WXMSW__
1850WXLRESULT EDA_BASE_FRAME::MSWWindowProc( WXUINT message, WXWPARAM wParam, WXLPARAM lParam )
1851{
1852 // This will help avoid the menu keeping focus when the alt key is released
1853 // You can still trigger accelerators as long as you hold down alt
1854 if( message == WM_SYSCOMMAND )
1855 {
1856 if( wParam == SC_KEYMENU && ( lParam >> 16 ) <= 0 )
1857 return 0;
1858 }
1859
1860 return wxFrame::MSWWindowProc( message, wParam, lParam );
1861}
1862#endif
1863
1864
1866{
1867 ACTION_MENU* langsMenu = new ACTION_MENU( false, aControlTool );
1868 langsMenu->SetTitle( _( "Set Language" ) );
1869 langsMenu->SetIcon( BITMAPS::language );
1870
1871 wxString tooltip;
1872
1873 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
1874 {
1875 wxString label;
1876
1877 if( LanguagesList[ii].m_DoNotTranslate )
1878 label = LanguagesList[ii].m_Lang_Label;
1879 else
1880 label = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
1881
1882 wxMenuItem* item =
1883 new wxMenuItem( langsMenu,
1884 LanguagesList[ii].m_KI_Lang_Identifier, // wxMenuItem wxID
1885 label, tooltip, wxITEM_CHECK );
1886
1887 langsMenu->Append( item );
1888 }
1889
1890 // This must be done after the items are added
1891 aMasterMenu->Add( langsMenu );
1892}
1893
1894
1895void EDA_BASE_FRAME::OnLanguageSelectionEvent( wxCommandEvent& event )
1896{
1897 int id = event.GetId();
1898
1899 // tell all the KIWAY_PLAYERs about the language change.
1900 Kiway().SetLanguage( id );
1901}
void ShowAboutDialog(EDA_BASE_FRAME *aParent)
int index
const char * name
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
void ClearScaledBitmapCache()
Wipes out the scaled bitmap cache so that the icon theme can be changed.
Definition bitmap.cpp:184
BITMAP_STORE * GetBitmapStore()
Definition bitmap.cpp:92
static TOOL_ACTION paste
Definition actions.h:80
static TOOL_ACTION about
Definition actions.h:287
static TOOL_ACTION reportBug
Definition actions.h:291
static TOOL_ACTION copy
Definition actions.h:78
static TOOL_ACTION donate
Definition actions.h:289
static TOOL_ACTION listHotKeys
Definition actions.h:288
static TOOL_ACTION getInvolved
Definition actions.h:290
static TOOL_ACTION undo
Definition actions.h:75
static TOOL_ACTION redo
Definition actions.h:76
static TOOL_ACTION cut
Definition actions.h:77
static TOOL_ACTION gettingStarted
Definition actions.h:285
static TOOL_ACTION help
Definition actions.h:286
Manage TOOL_ACTION objects.
const std::map< std::string, TOOL_ACTION * > & GetActions() const
Get a list of currently-registered actions mapped by their name.
Define the structure of a menu based on ACTIONs.
Definition action_menu.h:47
void SetTitle(const wxString &aTitle) override
Set title for the menu.
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
Class to hold basic information about controls that can be added to the toolbars.
const std::string & GetName() const
Define the structure of a toolbar with buttons that invoke ACTIONs.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
WINDOW_SETTINGS m_Window
void ThemeChanged()
Notifies the store that the icon theme has been changed by the user, so caches must be invalidated.
Handle actions that are shared between different applications.
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:68
int ShowModal() override
The base frame for deriving all KiCad main window classes.
virtual wxString help_name()
virtual bool doAutoSave()
This should be overridden by the derived class to handle the auto save feature.
void LoadWindowState(const wxString &aFileName)
FRAME_T GetFrameType() const
virtual void UnregisterUIUpdateHandler(int aID) override
Unregister a UI handler for a given ID that was registered using RegisterUIUpdateHandler.
virtual bool isAutoSaveRequired() const
Return the auto save status of the application.
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
virtual void handleIconizeEvent(wxIconizeEvent &aEvent)
Handle a window iconize event.
virtual void PushCommandToUndoList(PICKED_ITEMS_LIST *aItem)
Add a command to undo in the undo list.
void windowClosing(wxCloseEvent &event)
(with its unexpected name so it does not collide with the real OnWindowClose() function provided in d...
virtual void OnCharHook(wxKeyEvent &aKeyEvent)
Capture the key event before it is sent to the GUI.
virtual int GetRedoCommandCount() const
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
UNDO_REDO_CONTAINER m_undoList
virtual void OnMove(wxMoveEvent &aEvent)
virtual WINDOW_SETTINGS * GetWindowSettings(APP_SETTINGS_BASE *aCfg)
Return a pointer to the window settings for this frame.
virtual void doCloseWindow()
void OnToolbarSizeChanged()
Update toolbars if desired toolbar icon changed.
void OnMenuEvent(wxMenuEvent &event)
The TOOL_DISPATCHER needs these to work around some issues in wxWidgets where the menu events aren't ...
virtual bool IsModal() const
Return true if the frame is shown in our modal mode and false if the frame is shown as an usual frame...
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
virtual void HandleSystemColorChange()
Update the UI in response to a change in the system colors.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
void ensureWindowIsOnScreen()
bool m_isNonUserClose
Set by NonUserClose() to indicate that the user did not request the current close.
void LoadWindowSettings(const WINDOW_SETTINGS *aCfg)
Load window settings from the given settings object.
std::vector< wxFileName > m_AcceptedFiles
bool m_autoSavePermissionError
void OnKicadAbout(wxCommandEvent &event)
virtual void UpdateToolbarControlSizes()
Update the sizes of any controls in the toolbars of the frame.
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
virtual void DoWithAcceptedFiles()
Execute action on accepted dropped file.
virtual void OnModify()
Must be called after a model change in order to set the "modify" flag and do other frame-specific pro...
wxWindow * findQuasiModalDialog()
static void HandleUpdateUIEvent(wxUpdateUIEvent &aEvent, EDA_BASE_FRAME *aFrame, ACTION_CONDITIONS aCond)
Handle events generated when the UI is trying to figure out the current state of the UI controls rela...
wxString m_perspective
virtual void ClearUndoORRedoList(UNDO_REDO_LIST aList, int aItemCount=-1)
Remove the aItemCount of old commands from aList and delete commands, pickers and picked items if nee...
virtual void ThemeChanged()
Process light/dark theme change.
EDA_BASE_FRAME(wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, KIWAY *aKiway, const EDA_IU_SCALE &aIuScale)
static constexpr int KICAD_AUI_TB_STYLE
Default style flags used for wxAUI toolbars.
ACTION_TOOLBAR * m_tbRight
void ShowPreferences(wxString aStartPage, wxString aStartParentPage)
Display the preferences and settings of all opened editors paged dialog, starting with a particular p...
void initExitKey()
Set the common key-pair for exiting the application (Ctrl-Q) and ties it to the wxID_EXIT event id.
void OnPreferences(wxCommandEvent &event)
virtual const SEARCH_STACK & sys_search()
Return a SEARCH_STACK pertaining to entire program.
WX_INFOBAR * m_infoBar
void onAutoSaveTimer(wxTimerEvent &aEvent)
Handle the auto save timer event.
void SaveWindowSettings(WINDOW_SETTINGS *aCfg)
Save window settings to the given settings object.
virtual wxString GetRedoActionDescription() const
TOOLBAR_SETTINGS * m_toolbarSettings
virtual wxString GetCurrentFileName() const
Get the full filename + path of the currently opened file in the frame.
void ChangeUserUnits(EDA_UNITS aUnits)
void AddMenuLanguageList(ACTION_MENU *aMasterMenu, TOOL_INTERACTIVE *aControlTool)
Create a menu list for language choice, and add it as submenu to MasterMenu.
void RegisterCustomToolbarControlFactory(const ACTION_TOOLBAR_CONTROL &aControlDesc, const ACTION_TOOLBAR_CONTROL_FACTORY &aControlFactory)
Register a creation factory for toolbar controls that are present in this frame.
void ShowInfoBarMsg(const wxString &aMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an info icon on the left of...
virtual void configureToolbars()
wxTimer * m_autoSaveTimer
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, INFOBAR_MESSAGE_TYPE aType=INFOBAR_MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
wxAuiManager m_auimgr
void PrintMsg(const wxString &text)
void SelectToolbarAction(const TOOL_ACTION &aAction)
Select the given action in the toolbar group which contains it, if any.
void commonInit(FRAME_T aFrameType)
Collect common initialization functions used in all CTORs.
virtual bool IsContentModified() const
Get if the contents of the frame have been modified since the last save.
void ShowInfoBarWarning(const wxString &aWarningMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and a warning icon on the left ...
virtual PICKED_ITEMS_LIST * PopCommandFromRedoList()
Return the last command to undo and remove it from list, nothing is deleted.
virtual void RecreateToolbars()
std::map< int, UIUpdateHandler > m_uiUpdateMap
Map containing the UI update handlers registered with wx for each action.
std::map< std::string, ACTION_TOOLBAR_CONTROL_FACTORY > m_toolbarControlFactories
ACTION_TOOLBAR_CONTROL_FACTORY * GetCustomToolbarControlFactory(const std::string &aName)
UNDO_REDO_CONTAINER m_redoList
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
FILE_HISTORY * m_fileHistory
ACTION_TOOLBAR * m_tbLeft
SETTINGS_MANAGER * m_settingsManager
virtual void OnSize(wxSizeEvent &aEvent)
virtual wxString GetUndoActionDescription() const
virtual PICKED_ITEMS_LIST * PopCommandFromUndoList()
Return the last command to undo and remove it from list, nothing is deleted.
void OnLanguageSelectionEvent(wxCommandEvent &aEvent)
An event handler called on a language menu selection.
wxString GetRunMenuCommandDescription(const TOOL_ACTION &aAction)
virtual bool canCloseWindow(wxCloseEvent &aCloseEvent)
bool ProcessEvent(wxEvent &aEvent) override
Override the default process event handler to implement the auto save feature.
bool IsWritable(const wxFileName &aFileName, bool aVerbose=true)
Check if aFileName can be written.
wxPoint m_normalFramePos
void OnMaximize(wxMaximizeEvent &aEvent)
std::unique_ptr< nlohmann::json > m_auiLayoutState
virtual void ClearFileHistory()
Remove all files from the file history.
ACTION_TOOLBAR * m_tbTopAux
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.
void onIconize(wxIconizeEvent &aEvent)
virtual void unitsChangeRefresh()
Called when when the units setting has changed to allow for any derived classes to handle refreshing ...
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetch the file name from the file history list.
wxSize GetWindowSize()
Get the undecorated window size that can be used for restoring the window size.
int GetAutoSaveInterval() const
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
void onSystemColorChange(wxSysColourChangedEvent &aEvent)
virtual int GetUndoCommandCount() const
virtual void RegisterUIUpdateHandler(int aID, const ACTION_CONDITIONS &aConditions) override
Register a UI update handler for the control with ID aID.
ACTION_TOOLBAR * m_tbTopMain
virtual void PushCommandToRedoList(PICKED_ITEMS_LIST *aItem)
Add a command to redo in the redo list.
bool m_isClosing
Set by the close window event handler after frames are asked if they can close.
void AddStandardHelpMenu(wxMenuBar *aMenuBar)
Add the standard KiCad help menu to the menubar.
void ReCreateMenuBar()
Recreate the menu bar.
virtual void doReCreateMenuBar()
WX_INFOBAR * GetInfoBar()
Specialization of the wxAuiPaneInfo class for KiCad panels.
This class implements a file history object to store a list of files, that can then be added to a men...
void AddFileToHistory(const wxString &aFile) override
Adds a file to the history.
The main KiCad project manager frame.
SEARCH_STACK & KifaceSearch()
Only for DSO specific 'non-library' files.
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:95
const wxString & GetHelpFileName() const
Return just the basename portion of the current help file.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY_HOLDER(KIWAY *aKiway, HOLDER_TYPE aType)
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:295
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition kiway.cpp:525
@ FACE_SCH
eeschema DSO
Definition kiway.h:302
@ FACE_PL_EDITOR
Definition kiway.h:306
@ FACE_PCB
pcbnew DSO
Definition kiway.h:303
@ FACE_GERBVIEW
Definition kiway.h:305
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:407
virtual void CommonSettingsChanged(int aFlags=0)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition kiway.cpp:599
bool Init(const wxString &aProjectPath)
Initialize the local history repository for the given project path.
bool RunRegisteredSaversAndCommit(const wxString &aProjectPath, const wxString &aTitle)
Run all registered savers and, if any staged changes differ from HEAD, create a commit.
WX_TREEBOOK * GetTreebook()
void SetInitialPage(const wxString &aPage, const wxString &aParentPage=wxEmptyString)
std::vector< TOOL_ACTION * > & ActionsList()
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:137
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:541
virtual int GetSelectedLanguageIdentifier() const
Definition pgm_base.h:237
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:131
A holder to handle information on schematic or board items.
void SaveFileState(const wxString &aFileName, const WINDOW_SETTINGS *aWindowCfg, bool aOpen)
const PROJECT_FILE_STATE * GetFileState(const wxString &aFileName)
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:209
Look for files in a number of paths.
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
virtual void CommonSettingsChanged(int aFlags=0)
Notification event that some of the common (suite-wide) settings have changed.
TOOL_MANAGER * m_toolManager
virtual void ShowChangedLanguage()
TOOL_DISPATCHER * m_toolDispatcher
virtual SELECTION & GetCurrentSelection()
Get the current selection from the canvas area.
Represent a single user action.
wxString GetMenuLabel() const
Return the translated label for the action.
wxString GetFriendlyName() const
Return the translated user-friendly name of the action.
@ REDRAW
Full drawing refresh.
Definition tool_base.h:83
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
void SetUserUnits(EDA_UNITS aUnits)
bool Deserialize(const nlohmann::json &aState) const
nlohmann::json Serialize() const
Simple wrapper around wxBusyCursor for used with the generic BUSY_INDICATOR interface.
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:77
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
bool AddLazyPage(std::function< wxWindow *(wxWindow *aParent)> aLazyCtor, const wxString &text, bool bSelect=false, int imageId=NO_IMAGE)
bool AddLazySubPage(std::function< wxWindow *(wxWindow *aParent)> aLazyCtor, const wxString &text, bool bSelect=false, int imageId=NO_IMAGE)
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
This file is part of the common library.
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:52
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
static const wxSize minSizeLookup(FRAME_T aFrameType, wxWindow *aWindow)
#define LAZY_CTOR(key)
static const wxSize defaultSize(FRAME_T aFrameType, wxWindow *aWindow)
wxWindow * findQuasiModalDialog(wxWindow *aParent)
Base window classes and related definitions.
#define KICAD_MANAGER_FRAME_NAME
std::function< void(ACTION_TOOLBAR *)> ACTION_TOOLBAR_CONTROL_FACTORY
#define DEFAULT_MAX_UNDO_ITEMS
std::function< void(wxUpdateUIEvent &) > UIUpdateHandler
This is the handler functor for the update UI events.
void SocketCleanup()
Must be called to clean up the socket thread used by SendCommand.
Definition eda_dde.cpp:239
DDE server & client.
EDA_UNITS
Definition eda_units.h:48
EVT_MENU_RANGE(ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILEMAX, GERBVIEW_FRAME::OnDrlFileHistory) EVT_MENU_RANGE(ID_GERBVIEW_ZIP_FILE1
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition frame_type.h:33
@ PANEL_PCB_GRIDS
Definition frame_type.h:98
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ PANEL_SYM_EDIT_GRIDS
Definition frame_type.h:73
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ PANEL_3DV_TOOLBARS
Definition frame_type.h:108
@ PANEL_SCH_FIELD_NAME_TEMPLATES
Definition frame_type.h:83
@ PANEL_DS_TOOLBARS
Definition frame_type.h:120
@ PANEL_SCH_TOOLBARS
Definition frame_type.h:82
@ PANEL_GBR_DISPLAY_OPTIONS
Definition frame_type.h:110
@ PANEL_3DV_OPENGL
Definition frame_type.h:106
@ PANEL_FP_DEFAULT_GRAPHICS_VALUES
Definition frame_type.h:93
@ PANEL_PCB_TOOLBARS
Definition frame_type.h:101
@ PANEL_PCB_ORIGINS_AXES
Definition frame_type.h:103
@ PANEL_PCB_EDIT_OPTIONS
Definition frame_type.h:99
@ PANEL_SCH_DISP_OPTIONS
Definition frame_type.h:78
@ PANEL_FP_DISPLAY_OPTIONS
Definition frame_type.h:87
@ PANEL_SCH_SIMULATOR
Definition frame_type.h:84
@ FRAME_SCH
Definition frame_type.h:34
@ PANEL_DS_COLORS
Definition frame_type.h:119
@ PANEL_PCB_COLORS
Definition frame_type.h:100
@ PANEL_SYM_TOOLBARS
Definition frame_type.h:76
@ PANEL_3DV_RAYTRACING
Definition frame_type.h:107
@ PANEL_SYM_EDIT_OPTIONS
Definition frame_type.h:74
@ PANEL_FP_GRIDS
Definition frame_type.h:88
@ PANEL_SCH_EDIT_OPTIONS
Definition frame_type.h:80
@ PANEL_FP_ORIGINS_AXES
Definition frame_type.h:95
@ PANEL_SYM_DISP_OPTIONS
Definition frame_type.h:72
@ PANEL_PCB_DISPLAY_OPTS
Definition frame_type.h:97
@ PANEL_FP_COLORS
Definition frame_type.h:90
@ PANEL_FP_DEFAULT_FIELDS
Definition frame_type.h:92
@ PANEL_SYM_COLORS
Definition frame_type.h:75
@ FRAME_PL_EDITOR
Definition frame_type.h:59
@ PANEL_GBR_GRIDS
Definition frame_type.h:113
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:43
@ FRAME_GERBER
Definition frame_type.h:57
@ PANEL_DS_GRIDS
Definition frame_type.h:118
@ FRAME_PCB_DISPLAY3D
Definition frame_type.h:47
@ PANEL_GBR_TOOLBARS
Definition frame_type.h:115
@ PANEL_FP_EDIT_OPTIONS
Definition frame_type.h:89
@ PANEL_SCH_GRIDS
Definition frame_type.h:79
@ PANEL_FP_TOOLBARS
Definition frame_type.h:91
@ PANEL_PCB_ACTION_PLUGINS
Definition frame_type.h:102
@ PANEL_3DV_DISPLAY_OPTIONS
Definition frame_type.h:105
@ PANEL_DS_DISPLAY_OPTIONS
Definition frame_type.h:117
@ PANEL_SCH_COLORS
Definition frame_type.h:81
@ PANEL_GBR_COLORS
Definition frame_type.h:114
@ PANEL_GBR_EXCELLON_OPTIONS
Definition frame_type.h:112
@ KICAD_MAIN_FRAME_T
Definition frame_type.h:68
static const std::string GerberFileExtension
static bool IsGerberFileExtension(const wxString &ext)
const wxChar *const traceAutoSave
Flag to enable auto save feature debug tracing.
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
const wxChar *const traceDisplayLocation
Flag to enable debug output of display positioning logic.
void ReadHotKeyConfigIntoActions(const wxString &aFileName, std::vector< TOOL_ACTION * > &aActions)
Read a hotkey config file into a list of actions.
@ ID_FILE_LIST_CLEAR
Definition id.h:62
@ ID_LANGUAGE_CHOICE
Definition id.h:66
@ ID_LANGUAGE_CHOICE_END
Definition id.h:110
@ ID_FILE1
Definition id.h:59
@ ID_AUTO_SAVE_TIMER
Definition id.h:54
void RemoveShutdownBlockReason(wxWindow *aWindow)
Removes any shutdown block reason set.
Definition unix/app.cpp:85
PGM_BASE & Pgm()
The global program "get" accessor.
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition pgm_base.cpp:95
see class PGM_BASE
std::vector< FAB_LAYER_COLOR > dummy
Functors that can be used to figure out how the action controls should be displayed in the UI and if ...
SELECTION_CONDITION enableCondition
Returns true if the UI control should be enabled.
SELECTION_CONDITION checkCondition
Returns true if the UI control should be checked.
SELECTION_CONDITION showCondition
Returns true if the UI control should be shown.
ACTION_CONDITIONS & Check(const SELECTION_CONDITION &aCondition)
Implement a participant in the KIWAY alchemy.
Definition kiway.h:156
struct WINDOW_STATE window
Store the common settings that are saved and loaded for each window / frame.
WINDOW_STATE state
wxString mru_path
nlohmann::json aui_state
wxString perspective
Store the window positioning/state.
unsigned int display
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)
@ RIGHT
Toolbar on the right side of the canvas.
@ LEFT
Toolbar on the left side of the canvas.
@ TOP_AUX
Toolbar on the top of the canvas.
@ TOP_MAIN
Toolbar on the top of the canvas.
#define HOTKEYS_CHANGED
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.
INFOBAR_MESSAGE_TYPE
Sets the type of message for special handling if needed.