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, see <https://www.gnu.org/licenses/>.
21 */
22
24#include "kicad_manager_frame.h"
25#include <eda_base_frame.h>
26#include <nlohmann/json.hpp>
27
28#include <advanced_config.h>
30#include <api/api_server.h>
31#include <bitmaps.h>
32#include <bitmap_store.h>
33#include <dialog_shim.h>
41#include <file_history.h>
42#include <id.h>
43#include <kiface_base.h>
44#include <hotkeys_basic.h>
46#include <paths.h>
47#include <local_history.h>
48#include <confirm.h>
50#include <pgm_base.h>
51#include <scoped_set_reset.h>
56#include <tool/action_manager.h>
57#include <tool/action_menu.h>
58#include <tool/action_toolbar.h>
59#include <tool/actions.h>
60#include <tool/common_control.h>
61#include <tool/tool_manager.h>
64#include <trace_helpers.h>
67#include <widgets/wx_infobar.h>
70#include <widgets/wx_grid.h>
71#include <widgets/wx_treebook.h>
72#include <wx/app.h>
73#include <wx/config.h>
74#include <wx/display.h>
75#include <wx/stdpaths.h>
76#include <wx/string.h>
77#include <wx/msgdlg.h>
78#include <wx/wupdlock.h>
79#include <kiplatform/app.h>
80#include <kiplatform/io.h>
81#include <kiplatform/ui.h>
82
83#include <nlohmann/json.hpp>
84
85#include <functional>
86#include <kiface_ids.h>
87
88
89
90// Minimum window size
91static const wxSize minSizeLookup( FRAME_T aFrameType, wxWindow* aWindow )
92{
93 switch( aFrameType )
94 {
96 return wxWindow::FromDIP( wxSize( 406, 354 ), aWindow );
97
98 default:
99 return wxWindow::FromDIP( wxSize( 500, 400 ), aWindow );
100 }
101}
102
103
104static const wxSize defaultSize( FRAME_T aFrameType, wxWindow* aWindow )
105{
106 switch( aFrameType )
107 {
109 return wxWindow::FromDIP( wxSize( 850, 540 ), aWindow );
110
111 default:
112 return wxWindow::FromDIP( wxSize( 1280, 720 ), aWindow );
113 }
114}
115
116
117BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
118 // These event table entries are needed to handle events from the mac application menu
120 EVT_MENU( wxID_PREFERENCES, EDA_BASE_FRAME::OnPreferences )
121
122 EVT_CHAR_HOOK( EDA_BASE_FRAME::OnCharHook )
123 EVT_MENU_OPEN( EDA_BASE_FRAME::OnMenuEvent )
124 EVT_MENU_CLOSE( EDA_BASE_FRAME::OnMenuEvent )
125 EVT_MENU_HIGHLIGHT_ALL( EDA_BASE_FRAME::OnMenuEvent )
126 EVT_MOVE( EDA_BASE_FRAME::OnMove )
127 EVT_SIZE( EDA_BASE_FRAME::OnSize )
128 EVT_MAXIMIZE( EDA_BASE_FRAME::OnMaximize )
129
130 EVT_SYS_COLOUR_CHANGED( EDA_BASE_FRAME::onSystemColorChange )
131 EVT_ICONIZE( EDA_BASE_FRAME::onIconize )
132
134 END_EVENT_TABLE()
135
136
138{
139 m_ident = aFrameType;
140 m_maximizeByDefault = false;
141 m_infoBar = nullptr;
142 m_settingsManager = nullptr;
143 m_fileHistory = nullptr;
144 m_supportsAutoSave = false;
145 m_autoSavePending = false;
147 m_isClosing = false;
148 m_closeInProgress = false;
149 m_isNonUserClose = false;
150 m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
151 m_autoSaveRequired = false;
154 m_frameSize = defaultSize( aFrameType, this );
155 m_displayIndex = -1;
156
157 m_auimgr.SetArtProvider( new WX_AUI_DOCK_ART() );
158
160
161 // Set a reasonable minimal size for the frame
162 wxSize minSize = minSizeLookup( aFrameType, this );
163 SetSizeHints( minSize.x, minSize.y, -1, -1, -1, -1 );
164
165 // Store dimensions of the user area of the main window.
166 GetClientSize( &m_frameSize.x, &m_frameSize.y );
167
168 Connect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER, wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) );
169
170 // hook wxEVT_CLOSE_WINDOW so we can call SaveSettings(). This function seems
171 // to be called before any other hook for wxCloseEvent, which is necessary.
172 Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
173
174 KIPLATFORM::UI::SetWMClass( this, Pgm().GetDesktopAppId() );
175
176 initExitKey();
177}
178
179
180EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle,
181 const wxPoint& aPos, const wxSize& aSize, long aStyle,
182 const wxString& aFrameName, KIWAY* aKiway,
183 const EDA_IU_SCALE& aIuScale ) :
184 wxFrame( aParent, wxID_ANY, aTitle, aPos, aSize, aStyle, aFrameName ),
185 TOOLS_HOLDER(),
186 KIWAY_HOLDER( aKiway, KIWAY_HOLDER::FRAME ),
187 UNITS_PROVIDER( aIuScale, EDA_UNITS::MM )
188{
189 m_tbTopMain = nullptr;
190 m_tbTopAux = nullptr;
191 m_tbRight = nullptr;
192 m_tbLeft = nullptr;
194
195 commonInit( aFrameType );
196
197 Bind( wxEVT_DPI_CHANGED,
198 [&]( wxDPIChangedEvent& aEvent )
199 {
200#ifdef __WXMSW__
201 // Workaround to update toolbar sizes on MSW
202 if( m_auimgr.GetManagedWindow() )
203 {
204 wxAuiPaneInfoArray& panes = m_auimgr.GetAllPanes();
205
206 for( size_t ii = 0; ii < panes.GetCount(); ii++ )
207 {
208 wxAuiPaneInfo& pinfo = panes.Item( ii );
209 pinfo.best_size = pinfo.window->GetSize();
210
211 // But we still shouldn't make it too small.
212 pinfo.best_size.IncTo( pinfo.window->GetBestSize() );
213 pinfo.best_size.IncTo( pinfo.min_size );
214 }
215
216 m_auimgr.Update();
217 }
218#endif
219
220 aEvent.Skip();
221 } );
222}
223
224
225wxWindow* findQuasiModalDialog( wxWindow* aParent )
226{
227 for( wxWindow* child : aParent->GetChildren() )
228 {
229 if( DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( child ) )
230 {
231 if( dlg->IsQuasiModal() )
232 return dlg;
233
234 if( wxWindow* nestedDlg = findQuasiModalDialog( child ) )
235 return nestedDlg;
236 }
237 }
238
239 return nullptr;
240}
241
242
244{
245 if( wxWindow* dlg = ::findQuasiModalDialog( this ) )
246 return dlg;
247
248 // FIXME: CvPcb is currently implemented on top of KIWAY_PLAYER rather than DIALOG_SHIM,
249 // so we have to look for it separately.
250 if( m_ident == FRAME_SCH )
251 {
252 wxWindow* cvpcb = wxWindow::FindWindowByName( wxS( "CvpcbFrame" ) );
253
254 if( cvpcb )
255 return cvpcb;
256 }
257
258 return nullptr;
259}
260
261
262void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event )
263{
264 // Guard against re-entrant close events. GTK can deliver a second wxEVT_CLOSE_WINDOW
265 // while we are still processing the first one (e.g. during Destroy() calls), which leads
266 // to use-after-free crashes when child objects have already been torn down.
267 if( m_isClosing )
268 return;
269
270 // The unsaved-changes prompt in canCloseWindow() pumps messages, so a second close event
271 // (queued title-bar click, Alt+F4 repeat, session end) can arrive while the first close is
272 // still deciding. m_isClosing is not set until canCloseWindow() succeeds, so without this
273 // guard the second event would run the entire prompt and teardown re-entrantly and the
274 // first close would then resume against a demolished frame.
275 //
276 // A non-vetoable session end that lands during the prompt is dropped here rather than run
277 // re-entrantly. That trades a rare failure to persist settings on forced logoff for not
278 // crashing; the durable fix keeps the close off the OS default-window-proc stack entirely and
279 // needs Windows verification.
281 {
282 if( event.CanVeto() )
283 event.Veto();
284
285 return;
286 }
287
288 // Don't allow closing when a quasi-modal is open.
289 wxWindow* quasiModal = findQuasiModalDialog();
290
291 if( quasiModal )
292 {
293 // Raise and notify; don't give the user a warning regarding "quasi-modal dialogs"
294 // when they have no idea what those are.
295 quasiModal->Raise();
296 wxBell();
297
298 if( event.CanVeto() )
299 event.Veto();
300
301 return;
302 }
303
304
305 if( event.GetId() == wxEVT_QUERY_END_SESSION || event.GetId() == wxEVT_END_SESSION )
306 {
307 // End session means the OS is going to terminate us
308 m_isNonUserClose = true;
309 }
310
311 SCOPED_SET_RESET<bool> closeGuard( m_closeInProgress, true );
312
313 if( canCloseWindow( event ) )
314 {
315 m_isClosing = true;
316
317 if( m_infoBar )
318 m_infoBar->Dismiss();
319
320 APP_SETTINGS_BASE* cfg = config();
321
322 if( cfg )
323 SaveSettings( cfg ); // virtual, wxFrame specific
324
326
327 // Destroy (safe delete frame) this frame only in non modal mode.
328 // In modal mode, the caller will call Destroy().
329 if( !IsModal() )
330 Destroy();
331 }
332 else
333 {
334 if( event.CanVeto() )
335 event.Veto();
336 }
337}
338
339
341{
342 Disconnect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER, wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) );
343 Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
344
345 delete m_autoSaveTimer;
346 delete m_fileHistory;
347
349
351}
352
353
354bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent )
355{
356#ifdef __WXMAC__
357 // Apple in its infinite wisdom will raise a disabled window before even passing
358 // us the event, so we have no way to stop it. Instead, we have to catch an
359 // improperly ordered disabled window and quasi-modal dialog here and reorder
360 // them.
361 if( !IsEnabled() && IsActive() )
362 {
363 wxWindow* dlg = findQuasiModalDialog();
364
365 if( dlg )
366 dlg->Raise();
367 }
368#endif
369
370#ifdef __WXMSW__
371 // When changing DPI to a lower value, somehow, called from wxNonOwnedWindow::HandleDPIChange,
372 // our sizers compute a min size that is larger than the old frame size. wx then sets this wrong size.
373 // This shouldn't be needed since the OS have already sent a size event.
374 // Avoid this wx behaviour by pretending we've processed the event even if we use Skip in handlers.
375 if( aEvent.GetEventType() == wxEVT_DPI_CHANGED )
376 {
377 wxFrame::ProcessEvent( aEvent );
378 return true;
379 }
380#endif
381
382 if( !wxFrame::ProcessEvent( aEvent ) )
383 return false;
384
385 if( Pgm().m_Quitting )
386 return true;
387
388 if( !m_isClosing && m_supportsAutoSave && IsShownOnScreen() && IsActive()
390 && GetAutoSaveInterval() > 0 )
391 {
392 if( !m_autoSavePending )
393 {
394 wxLogTrace( traceAutoSave, wxT( "Starting auto save timer." ) );
395 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
396 m_autoSavePending = true;
397
398 // A fresh cycle starts here (a prior snapshot completed or an explicit save cleared
399 // the pending state), so drop any deferral streak left over from that cycle; otherwise
400 // its stale start time could force the next snapshot to run mid-interaction.
401 m_autoSaveDeferredSince = wxInvalidDateTime;
402 }
403 else if( m_autoSaveTimer->IsRunning() )
404 {
405 wxLogTrace( traceAutoSave, wxT( "Stopping auto save timer." ) );
406 m_autoSaveTimer->Stop();
407 m_autoSavePending = false;
408 }
409 }
410
411 return true;
412}
413
414
419
420
421void EDA_BASE_FRAME::onAutoSaveTimer( wxTimerEvent& aEvent )
422{
423 // Don't stomp on someone else's timer event.
424 if( aEvent.GetId() != ID_AUTO_SAVE_TIMER )
425 {
426 aEvent.Skip();
427 return;
428 }
429
430 // A one-shot tick can already be queued when the frame starts closing; running the saver batch
431 // then would serialize documents whose editors are mid-teardown, so bail once closing begins.
432 if( m_isClosing )
433 return;
434
435 // When the save is deferred (an interactive operation is in progress) keep the timer armed so
436 // a later tick retries. Maintaining m_autoSavePending here preserves the "pending == timer
437 // running" invariant that ProcessEvent() relies on to avoid re-arming the timer on every event.
439 {
440 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
441 m_autoSavePending = true;
442 }
443 else
444 {
445 m_autoSavePending = false;
446 }
447}
448
449
450static wxString buildRecoveredFileName( const wxFileName& aSrcFn, const wxDateTime& aStamp )
451{
452 wxString stamp = aStamp.IsValid() ? aStamp.Format( wxS( "%Y-%m-%d_%H%M%S" ) ) : wxString( wxS( "unknown-time" ) );
453
454 wxFileName recovered( aSrcFn );
455 recovered.SetName( aSrcFn.GetName() + wxS( ".recovered." ) + stamp );
456
457 int seq = 1;
458
459 while( recovered.FileExists() )
460 recovered.SetName( aSrcFn.GetName() + wxS( ".recovered." ) + stamp + wxString::Format( wxS( ".%d" ), seq++ ) );
461
462 return recovered.GetFullPath();
463}
464
465
466void EDA_BASE_FRAME::CheckForAutosaveFiles( const wxString& aProjectPath, const std::vector<wxString>& aExtensions )
467{
468 auto stale = Kiway().LocalHistory().FindStaleAutosaveFiles( aProjectPath, aExtensions );
469
470 if( stale.empty() )
471 return;
472
473 DIALOG_AUTOSAVE_RECOVERY dlg( this, stale );
474 dlg.ShowModal();
475
476 auto selected = dlg.GetSelectedStale();
477
478 switch( dlg.GetChoice() )
479 {
481 for( const auto& [autosavePath, srcPath] : selected )
482 {
483 if( !wxCopyFile( autosavePath, srcPath, true ) )
484 {
485 wxLogError( _( "Failed to recover auto-saved file '%s'." ), srcPath );
486 continue;
487 }
488
489 wxRemoveFile( autosavePath );
490 }
491 break;
492
494 for( const auto& [autosavePath, srcPath] : selected )
495 {
496 if( wxFileExists( autosavePath ) )
497 wxRemoveFile( autosavePath );
498 }
499 break;
500
502 for( const auto& [autosavePath, srcPath] : selected )
503 {
504 wxFileName autosaveFn( autosavePath );
505 wxFileName srcFn( srcPath );
506 wxDateTime stamp = autosaveFn.FileExists() ? autosaveFn.GetModificationTime() : wxDateTime::Now();
507
508 wxString target = buildRecoveredFileName( srcFn, stamp );
509
510 if( !wxCopyFile( autosavePath, target, true ) )
511 {
512 wxLogError( _( "Failed to write recovered file '%s'." ), target );
513 continue;
514 }
515
516 wxRemoveFile( autosavePath );
517 }
518 break;
519
521 // Leave all autosaves on disk so the dialog can offer them again next open.
522 break;
523 }
524}
525
526
528{
529 // Defer the snapshot if the user is mid-interaction. Serializing a large document on the
530 // UI thread freezes the editor for seconds; deferring keeps the dirty flags set so the
531 // rescheduled timer tick will pick the work up once the operation completes. To avoid
532 // starving the snapshot when the user parks in an interactive tool, the deferral is bounded
533 // and the save is forced once it has been outstanding for longer than the cap.
534 if( !canRunAutoSave() )
535 {
536 wxDateTime now = wxDateTime::Now();
537
538 if( !m_autoSaveDeferredSince.IsValid() )
540
541 wxTimeSpan maxDeferral = wxTimeSpan::Seconds( std::max( 60, GetAutoSaveInterval() * 12 ) );
542
543 if( now - m_autoSaveDeferredSince < maxDeferral )
544 {
545 wxLogTrace( traceAutoSave, wxT( "Deferring auto save; an interactive operation is in progress." ) );
546 return false;
547 }
548
549 wxLogTrace( traceAutoSave, wxT( "Auto save deferral exceeded; saving despite interactive operation." ) );
550 }
551
552 // The deferral is resolved (either the user went idle or the cap forced the snapshot), so the
553 // cycle is now consumed regardless of the saver outcome. The snapshot is best effort: a
554 // droppable cycle (a prior autosave still writing) is recaptured by the next edit's OnModify,
555 // so clear the flags here rather than re-arming on the saver result, which would poll forever
556 // in degenerate states such as no registered savers.
557 m_autoSaveDeferredSince = wxInvalidDateTime;
558 m_autoSaveRequired = false;
559
561
562 // Incremental and zip-autosave both write outside the project tree when the user
563 // selects USER_DIR, so a read-only project is fine in that mode. Only when the
564 // chosen location is the project directory does the project tree need to be writable.
565 if( cs->m_Backup.location == BACKUP_LOCATION::PROJECT_DIR && Prj().IsReadOnly() )
566 return true;
567
568 if( cs->AutosaveUsesLocalHistory() )
569 Kiway().LocalHistory().RunRegisteredSaversAndCommit( Prj().GetProjectPath(), wxS( "Autosave" ) );
570 else
572
573 return true;
574}
575
576
577void EDA_BASE_FRAME::OnCharHook( wxKeyEvent& aKeyEvent )
578{
579 wxLogTrace( kicadTraceKeyEvent, wxS( "EDA_BASE_FRAME::OnCharHook %s" ), dump( aKeyEvent ) );
580
581 // Key events can be filtered here.
582 // Currently no filtering is made.
583 aKeyEvent.Skip();
584}
585
586
587void EDA_BASE_FRAME::OnMenuEvent( wxMenuEvent& aEvent )
588{
589 if( !m_toolDispatcher )
590 aEvent.Skip();
591 else
592 m_toolDispatcher->DispatchWxEvent( aEvent );
593}
594
595
597{
598 // Bind a single wxID_ANY dispatcher on first use rather than one Bind() per action.
599 // wxEvtHandler::SearchDynamicEventTable does a linear scan through all dynamic bindings
600 // for every event dispatch (including mouse motion), so 150 individual bindings cost
601 // O(150) per event regardless of event type. One wxID_ANY binding costs O(1).
603 {
604 Bind( wxEVT_UPDATE_UI, &EDA_BASE_FRAME::onUpdateUI, this );
606 }
607
609 std::placeholders::_1,
610 this,
611 aConditions );
612}
613
614
616{
617 m_uiUpdateMap.erase( aID );
618}
619
620
621void EDA_BASE_FRAME::onUpdateUI( wxUpdateUIEvent& aEvent )
622{
623 const auto it = m_uiUpdateMap.find( aEvent.GetId() );
624
625 if( it != m_uiUpdateMap.end() )
626 it->second( aEvent );
627 else
628 aEvent.Skip();
629}
630
631
632void EDA_BASE_FRAME::HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAME* aFrame,
633 ACTION_CONDITIONS& aCond )
634{
635 bool checkRes = false;
636 bool enableRes = true;
637 bool showRes = true;
638 bool isCut = aEvent.GetId() == ACTIONS::cut.GetUIId();
639 bool isCopy = aEvent.GetId() == ACTIONS::copy.GetUIId();
640 bool isPaste = aEvent.GetId() == ACTIONS::paste.GetUIId();
641 SELECTION& selection = aFrame->GetCurrentSelection();
642
643 try
644 {
645 checkRes = aCond.checkCondition( selection );
646 enableRes = aCond.enableCondition( selection );
647 showRes = aCond.showCondition( selection );
648 }
649 catch( std::exception& )
650 {
651 // Something broke with the conditions, just skip the event.
652 aEvent.Skip();
653 return;
654 }
655
656 if( showRes && aEvent.GetId() == ACTIONS::undo.GetUIId() )
657 {
658 wxString msg = _( "Undo" );
659
660 if( enableRes )
661 msg += wxS( " " ) + aFrame->GetUndoActionDescription();
662
663 aEvent.SetText( msg );
664 }
665 else if( showRes && aEvent.GetId() == ACTIONS::redo.GetUIId() )
666 {
667 wxString msg = _( "Redo" );
668
669 if( enableRes )
670 msg += wxS( " " ) + aFrame->GetRedoActionDescription();
671
672 aEvent.SetText( msg );
673 }
674
675 if( isCut || isCopy || isPaste )
676 {
677 wxWindow* focus = wxWindow::FindFocus();
678 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
679
680 if( textEntry && isCut && textEntry->CanCut() )
681 enableRes = true;
682 else if( textEntry && isCopy && textEntry->CanCopy() )
683 enableRes = true;
684 else if( textEntry && isPaste && textEntry->CanPaste() )
685 enableRes = true;
686 else if( dynamic_cast<WX_GRID*>( focus ) )
687 enableRes = false; // Must disable menu in order to get command as CharHook event
688 }
689
690 aEvent.Enable( enableRes );
691 aEvent.Show( showRes );
692
693 if( aEvent.IsCheckable() )
694 aEvent.Check( checkRes );
695}
696
697
699{
700 // Setup the conditions to check a language menu item
701 auto isCurrentLang =
702 [] ( const SELECTION& aSel, int aLangIdentifier )
703 {
704 return Pgm().GetSelectedLanguageIdentifier() == aLangIdentifier;
705 };
706
707 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
708 {
710 cond.Check( std::bind( isCurrentLang, std::placeholders::_1,
711 LanguagesList[ii].m_WX_Lang_Identifier ) );
712 RegisterUIUpdateHandler( LanguagesList[ii].m_KI_Lang_Identifier, cond );
713 }
714}
715
716
718 const ACTION_TOOLBAR_CONTROL_FACTORY& aControlFactory )
719{
720 m_toolbarControlFactories.emplace( aControlDesc.GetName(), aControlFactory );
721}
722
723
725{
726 for( auto& control : m_toolbarControlFactories )
727 {
728 if( control.first == aName )
729 return &control.second;
730 }
731
732 return nullptr;
733}
734
735
739
740
742{
743 if( m_tbLeft )
744 m_tbLeft->SelectAction( aAction );
745
746 if( m_tbTopMain )
747 m_tbTopMain->SelectAction( aAction );
748
749 if( m_tbTopAux )
750 m_tbTopAux->SelectAction( aAction );
751
752 if( m_tbRight )
753 m_tbRight->SelectAction( aAction );
754}
755
756
758{
759 wxWindowUpdateLocker dummy( this );
760
761 wxASSERT( m_toolbarSettings );
762
763 if( m_tbRight )
764 m_tbRight->ClearToolbar();
765
766 if( m_tbLeft )
767 m_tbLeft->ClearToolbar();
768
769 if( m_tbTopMain )
770 m_tbTopMain->ClearToolbar();
771
772 if( m_tbTopAux )
773 m_tbTopAux->ClearToolbar();
774
775 std::optional<TOOLBAR_CONFIGURATION> tbConfig;
776
777 // Drawing tools (typically on right edge of window)
778 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::RIGHT, config()->m_CustomToolbars );
779
780 if( tbConfig.has_value() )
781 {
782 if( !m_tbRight )
783 {
784 m_tbRight = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
785 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL | wxAUI_TB_TEXT
786 | wxAUI_TB_OVERFLOW );
787 m_tbRight->SetAuiManager( &m_auimgr );
788 }
789
790 m_tbRight->ApplyConfiguration( tbConfig.value() );
791 }
792
793 // Options (typically on left edge of window)
794 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::LEFT, config()->m_CustomToolbars );
795
796 if( tbConfig.has_value() )
797 {
798 if( !m_tbLeft )
799 {
800 m_tbLeft = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
801 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
802 m_tbLeft->SetAuiManager( &m_auimgr );
803 }
804
805 m_tbLeft->ApplyConfiguration( tbConfig.value() );
806 }
807
808 // Top main toolbar (the top one)
809 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::TOP_MAIN, config()->m_CustomToolbars );
810
811 if( tbConfig.has_value() )
812 {
813 if( !m_tbTopMain )
814 {
815 m_tbTopMain = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
816 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT | wxAUI_TB_HORIZONTAL
817 | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
818 m_tbTopMain->SetAuiManager( &m_auimgr );
819 }
820
821 m_tbTopMain->ApplyConfiguration( tbConfig.value() );
822 }
823
824 // Top aux toolbar (the bottom one)
825 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::TOP_AUX, config()->m_CustomToolbars );
826
827 if( tbConfig.has_value() )
828 {
829 if( !m_tbTopAux )
830 {
831 m_tbTopAux = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
832 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT | wxAUI_TB_HORIZONTAL
833 | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
834 m_tbTopAux->SetAuiManager( &m_auimgr );
835 }
836
837 m_tbTopAux->ApplyConfiguration( tbConfig.value() );
838 }
839
841}
842
843
845{
846 if( m_tbTopMain )
847 m_tbTopMain->UpdateControlWidths();
848
849 if( m_tbRight )
850 m_tbRight->UpdateControlWidths();
851
852 if( m_tbLeft )
853 m_tbLeft->UpdateControlWidths();
854
855 if( m_tbTopAux )
856 m_tbTopAux->UpdateControlWidths();
857
858}
859
860
862{
863 if( m_tbTopMain )
864 m_auimgr.GetPane( m_tbTopMain ).MaxSize( m_tbTopMain->GetSize() );
865
866 if( m_tbRight )
867 m_auimgr.GetPane( m_tbRight ).MaxSize( m_tbRight->GetSize() );
868
869 if( m_tbLeft )
870 m_auimgr.GetPane( m_tbLeft ).MaxSize( m_tbLeft->GetSize() );
871
872 if( m_tbTopAux )
873 m_auimgr.GetPane( m_tbTopAux ).MaxSize( m_tbTopAux->GetSize() );
874
875 m_auimgr.Update();
876}
877
878
880{
887
888 CallAfter( [this]()
889 {
890 if( m_isClosing )
891 return;
892
894
895 // A submenu entry gets a new automatic id in each menubar, and its handler
896 // is registered under that id, so the ones of the old menubar are dead
897 wxMenuBar* menuBar = GetMenuBar();
898
899 std::erase_if( m_uiUpdateMap,
900 [menuBar]( const auto& aEntry )
901 {
902 int id = aEntry.first;
903
904 return id >= wxID_AUTO_LOWEST && id <= wxID_AUTO_HIGHEST
905 && !( menuBar && menuBar->FindItem( id ) );
906 } );
907 } );
908}
909
910
911void EDA_BASE_FRAME::AddStandardHelpMenu( wxMenuBar* aMenuBar )
912{
913 COMMON_CONTROL* commonControl = m_toolManager->GetTool<COMMON_CONTROL>();
914 ACTION_MENU* helpMenu = new ACTION_MENU( false, commonControl );
915
916 helpMenu->Add( ACTIONS::help );
917 helpMenu->Add( ACTIONS::gettingStarted );
918 helpMenu->Add( ACTIONS::listHotKeys );
919 helpMenu->Add( ACTIONS::getInvolved );
920 helpMenu->Add( ACTIONS::donate );
921 helpMenu->Add( ACTIONS::reportBug );
922
923 helpMenu->AppendSeparator();
924 helpMenu->Add( ACTIONS::about );
925
926 aMenuBar->Append( helpMenu, _( "&Help" ) );
927}
928
929
930
932{
933 wxString menuItemLabel = aAction.GetMenuLabel();
934 wxMenuBar* menuBar = GetMenuBar();
935
936 for( size_t ii = 0; ii < menuBar->GetMenuCount(); ++ii )
937 {
938 for( wxMenuItem* menuItem : menuBar->GetMenu( ii )->GetMenuItems() )
939 {
940 if( menuItem->GetItemLabelText() == menuItemLabel )
941 {
942 wxString menuTitleLabel = menuBar->GetMenuLabelText( ii );
943
944 menuTitleLabel.Replace( wxS( "&" ), wxS( "&&" ) );
945 menuItemLabel.Replace( wxS( "&" ), wxS( "&&" ) );
946
947 return wxString::Format( _( "Run: %s > %s" ),
948 menuTitleLabel,
949 menuItemLabel );
950 }
951 }
952 }
953
954 return wxString::Format( _( "Run: %s" ), aAction.GetFriendlyName() );
955};
956
957
959{
961
962 if( GetMenuBar() )
963 {
965 GetMenuBar()->Refresh();
966 }
967}
968
969
971{
973
974 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
975
976 bool running = Pgm().GetApiServer().Running();
977
978 if( running && !settings->m_Api.enable_server )
979 {
980 Pgm().GetApiServer().Stop();
981 }
982 else if( !running && settings->m_Api.enable_server )
983 {
984 Pgm().GetApiServer().Start();
986 }
987
988 if( m_fileHistory )
989 {
990 int historySize = settings->m_System.file_history_size;
991 m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) );
992 }
993
994 if( Pgm().GetCommonSettings()->AutosaveUsesLocalHistory() )
995 Kiway().LocalHistory().Init( Prj().GetProjectPath() );
996
998 ThemeChanged();
999
1000 if( GetMenuBar() )
1001 {
1002 // For icons in menus, icon scaling & hotkeys
1004 GetMenuBar()->Refresh();
1005 }
1006
1007 // Update the toolbars
1009}
1010
1011
1013{
1015
1016 // Update all the toolbars to have new icons
1017 wxAuiPaneInfoArray panes = m_auimgr.GetAllPanes();
1018
1019 for( size_t i = 0; i < panes.GetCount(); ++i )
1020 {
1021 if( ACTION_TOOLBAR* toolbar = dynamic_cast<ACTION_TOOLBAR*>( panes[i].window ) )
1022 toolbar->RefreshBitmaps();
1023 }
1024}
1025
1026
1027void EDA_BASE_FRAME::OnSize( wxSizeEvent& aEvent )
1028{
1029#ifdef __WXMAC__
1030 int currentDisplay = wxDisplay::GetFromWindow( this );
1031
1032 if( m_displayIndex >= 0 && currentDisplay >= 0 && currentDisplay != m_displayIndex )
1033 {
1034 wxLogTrace( traceDisplayLocation, wxS( "OnSize: current display changed %d to %d" ),
1035 m_displayIndex, currentDisplay );
1036 m_displayIndex = currentDisplay;
1038 }
1039#endif
1040
1041 aEvent.Skip();
1042}
1043
1044
1045void EDA_BASE_FRAME::LoadWindowState( const wxString& aFileName )
1046{
1047 if( !Pgm().GetCommonSettings()->m_Session.remember_open_files )
1048 return;
1049
1050 if( const PROJECT_FILE_STATE* state = Prj().GetLocalSettings().GetFileState( aFileName ) )
1051 LoadWindowState( state->window );
1052}
1053
1054
1056{
1057 bool wasDefault = false;
1058
1059 m_framePos.x = aState.pos_x;
1060 m_framePos.y = aState.pos_y;
1061 m_frameSize.x = aState.size_x;
1062 m_frameSize.y = aState.size_y;
1063
1064 wxLogTrace( traceDisplayLocation, wxS( "Config position (%d, %d) with size (%d, %d)" ),
1066
1067 // Ensure minimum size is set if the stored config was zero-initialized
1068 wxSize minSize = minSizeLookup( m_ident, this );
1069
1070 if( m_frameSize.x < minSize.x || m_frameSize.y < minSize.y )
1071 {
1072 m_frameSize = defaultSize( m_ident, this );
1073 wasDefault = true;
1074
1075 wxLogTrace( traceDisplayLocation, wxS( "Using minimum size (%d, %d)" ), m_frameSize.x, m_frameSize.y );
1076 }
1077
1078 wxLogTrace( traceDisplayLocation, wxS( "Number of displays: %d" ), wxDisplay::GetCount() );
1079
1080 if( aState.display >= wxDisplay::GetCount() )
1081 {
1082 wxLogTrace( traceDisplayLocation, wxS( "Previous display not found" ) );
1083
1084 // If it isn't attached, use the first display
1085 // Warning wxDisplay has 2 ctor variants. the parameter needs a type:
1086 const unsigned int index = 0;
1087 wxDisplay display( index );
1088 wxRect clientSize = display.GetGeometry();
1089
1090 m_framePos = wxDefaultPosition;
1091
1092 // Ensure the window fits on the display, since the other one could have been larger
1093 if( m_frameSize.x > clientSize.width )
1094 m_frameSize.x = clientSize.width;
1095
1096 if( m_frameSize.y > clientSize.height )
1097 m_frameSize.y = clientSize.height;
1098 }
1099 else
1100 {
1101 wxPoint upperRight( m_framePos.x + m_frameSize.x, m_framePos.y );
1102 wxPoint upperLeft( m_framePos.x, m_framePos.y );
1103
1104 wxDisplay display( aState.display );
1105 wxRect clientSize = display.GetClientArea();
1106
1107 int yLimTop = clientSize.y;
1108 int yLimBottom = clientSize.y + clientSize.height;
1109 int xLimLeft = clientSize.x;
1110 int xLimRight = clientSize.x + clientSize.width;
1111
1112 if( upperLeft.x > xLimRight || // Upper left corner too close to right edge of screen
1113 upperRight.x < xLimLeft || // Upper right corner too close to left edge of screen
1114 upperLeft.y < yLimTop || // Upper corner too close to the bottom of the screen
1115 upperLeft.y > yLimBottom )
1116 {
1117 m_framePos = wxDefaultPosition;
1118 wxLogTrace( traceDisplayLocation, wxS( "Resetting to default position" ) );
1119 }
1120
1121 // Clamp the saved size to the current display, in case the window was sized for a
1122 // larger external monitor that is no longer attached.
1123 if( m_frameSize.x > clientSize.width )
1124 {
1125 wxLogTrace( traceDisplayLocation, wxS( "Clamping window width %d to display width %d" ),
1126 m_frameSize.x, clientSize.width );
1127 m_frameSize.x = clientSize.width;
1128 }
1129
1130 if( m_frameSize.y > clientSize.height )
1131 {
1132 wxLogTrace( traceDisplayLocation, wxS( "Clamping window height %d to display height %d" ),
1133 m_frameSize.y, clientSize.height );
1134 m_frameSize.y = clientSize.height;
1135 }
1136 }
1137
1138 wxLogTrace( traceDisplayLocation, wxS( "Final window position (%d, %d) with size (%d, %d)" ),
1140
1141 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
1142
1143 // Center the window if we reset to default
1144 if( m_framePos.x == -1 )
1145 {
1146 wxLogTrace( traceDisplayLocation, wxS( "Centering window" ) );
1147 Center();
1148 m_framePos = GetPosition();
1149 }
1150
1151 // Record the frame sizes in an un-maximized state
1154
1155 // Maximize if we were maximized before
1156 if( aState.maximized || ( wasDefault && m_maximizeByDefault ) )
1157 {
1158 wxLogTrace( traceDisplayLocation, wxS( "Maximizing window" ) );
1159 Maximize();
1160 }
1161
1162 m_displayIndex = wxDisplay::GetFromWindow( this );
1163}
1164
1165
1167{
1168 wxDisplay display( wxDisplay::GetFromWindow( this ) );
1169 wxRect clientSize = display.GetClientArea();
1170 wxPoint pos = GetPosition();
1171 wxSize size = GetWindowSize();
1172
1173 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: clientArea (%d, %d) w %d h %d" ),
1174 clientSize.x, clientSize.y,
1175 clientSize.width, clientSize.height );
1176
1177 if( pos.y < clientSize.y )
1178 {
1179 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: y pos %d below minimum, setting to %d" ),
1180 pos.y, clientSize.y );
1181 pos.y = clientSize.y;
1182 }
1183
1184 if( pos.x < clientSize.x )
1185 {
1186 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: x pos %d below minimum, setting to %d" ),
1187 pos.x, clientSize.x );
1188 pos.x = clientSize.x;
1189 }
1190
1191 if( pos.x + size.x - clientSize.x > clientSize.width )
1192 {
1193 int newWidth = clientSize.width - ( pos.x - clientSize.x );
1194 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: width %d above available %d, setting to %d" ),
1195 pos.x + size.x, clientSize.width, newWidth );
1196 size.x = newWidth;
1197 }
1198
1199 if( pos.y + size.y - clientSize.y > clientSize.height )
1200 {
1201 int newHeight = clientSize.height - ( pos.y - clientSize.y );
1202 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: height %d above available %d, setting to %d" ),
1203 pos.y + size.y, clientSize.height, newHeight );
1204 size.y = newHeight;
1205 }
1206
1207 wxLogTrace( traceDisplayLocation, wxS( "Updating window position (%d, %d) with size (%d, %d)" ),
1208 pos.x, pos.y, size.x, size.y );
1209
1210 SetSize( pos.x, pos.y, size.x, size.y );
1211}
1212
1213
1215{
1216 LoadWindowState( aCfg->state );
1217
1218 m_perspective = aCfg->perspective;
1219 m_auiLayoutState = std::make_unique<nlohmann::json>( aCfg->aui_state );
1220 m_mruPath = aCfg->mru_path;
1221
1223}
1224
1225
1227{
1228 if( IsIconized() )
1229 return;
1230
1231 // If the window is maximized, we use the saved window size from before it was maximized
1232 if( IsMaximized() )
1233 {
1236 }
1237 else
1238 {
1240 m_framePos = GetPosition();
1241 }
1242
1243 aCfg->state.pos_x = m_framePos.x;
1244 aCfg->state.pos_y = m_framePos.y;
1245 aCfg->state.size_x = m_frameSize.x;
1246 aCfg->state.size_y = m_frameSize.y;
1247 aCfg->state.maximized = IsMaximized();
1248 aCfg->state.display = wxDisplay::GetFromWindow( this );
1249
1250 wxLogTrace( traceDisplayLocation, wxS( "Saving window maximized: %s" ),
1251 IsMaximized() ? wxS( "true" ) : wxS( "false" ) );
1252 wxLogTrace( traceDisplayLocation, wxS( "Saving config position (%d, %d) with size (%d, %d)" ),
1254
1255 // Once this is fully implemented, wxAuiManager will be used to maintain
1256 // the persistence of the main frame and all it's managed windows and
1257 // all of the legacy frame persistence position code can be removed.
1258#if wxCHECK_VERSION( 3, 3, 0 )
1259 {
1260 WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
1261 nlohmann::json state = serializer.Serialize();
1262
1263 if( state.is_null() || state.empty() )
1264 aCfg->aui_state = nlohmann::json();
1265 else
1266 aCfg->aui_state = state;
1267
1268 aCfg->perspective.clear();
1269 }
1270#else
1271 aCfg->perspective = m_auimgr.SavePerspective().ToStdString();
1272 aCfg->aui_state = nlohmann::json();
1273#endif
1274
1275 aCfg->mru_path = m_mruPath;
1276}
1277
1278
1280{
1282
1283 // Get file history size from common settings
1284 int fileHistorySize = Pgm().GetCommonSettings()->m_System.file_history_size;
1285
1286 // Load the recently used files into the history menu
1287 m_fileHistory = new FILE_HISTORY( (unsigned) std::max( 1, fileHistorySize ), ID_FILE1, ID_FILE_LIST_CLEAR );
1288 m_fileHistory->Load( *aCfg );
1289}
1290
1291
1293{
1294 wxCHECK( config(), /* void */ );
1295
1297
1298 bool fileOpen = m_isClosing && m_isNonUserClose;
1299
1300 wxString currentlyOpenedFile = GetCurrentFileName();
1301
1302 if( Pgm().GetCommonSettings()->m_Session.remember_open_files && !currentlyOpenedFile.IsEmpty() )
1303 {
1304 wxFileName rfn( currentlyOpenedFile );
1305 rfn.MakeRelativeTo( Prj().GetProjectPath() );
1306 Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &aCfg->m_Window, fileOpen );
1307 }
1308
1309 // Save the recently used files list
1310 if( m_fileHistory )
1311 {
1312 // Save the currently opened file in the file history
1313 if( !currentlyOpenedFile.IsEmpty() )
1314 UpdateFileHistory( currentlyOpenedFile );
1315
1316 m_fileHistory->Save( *aCfg );
1317 }
1318}
1319
1320
1325
1326
1328{
1329 // KICAD_MANAGER_FRAME overrides this
1330 return Kiface().KifaceSettings();
1331}
1332
1333
1335{
1336 return Kiface().KifaceSearch();
1337}
1338
1339
1341{
1342 return Kiface().GetHelpFileName();
1343}
1344
1345
1346void EDA_BASE_FRAME::PrintMsg( const wxString& text )
1347{
1348 SetStatusText( text );
1349}
1350
1351
1353{
1354 wxWindow* canvas = GetToolCanvas();
1355
1356 wxCHECK( canvas, /* void */ );
1357
1358 m_infoBar = new WX_INFOBAR( canvas, wxID_ANY, true );
1359}
1360
1361
1363{
1364 m_auimgr.Update();
1365}
1366
1367
1369{
1370 if( !ADVANCED_CFG::GetCfg().m_EnableUseAuiPerspective )
1371 return;
1372
1373 bool restored = false;
1374
1375#if wxCHECK_VERSION( 3, 3, 0 )
1376 if( m_auiLayoutState && !m_auiLayoutState->is_null() && !m_auiLayoutState->empty() )
1377 {
1378 WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
1379
1380 if( serializer.Deserialize( *m_auiLayoutState ) )
1381 restored = true;
1382 }
1383#endif
1384
1385 /*
1386 * Legacy loading of the string AUI perspective (if it exists). This is needed for
1387 * 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).
1388 */
1389 if( !restored && !m_perspective.IsEmpty() )
1390 m_auimgr.LoadPerspective( m_perspective );
1391
1392 // Workaround for two bugs:
1393 // 1) wx 3.2: LoadPerspective() hides all panes first, then shows only
1394 // those in the saved string. If toolbar names changed or new toolbars were added,
1395 // they'd stay hidden. Ensure all toolbars are visible after restore.
1396 // 2) We still saw this even after this fix, so just make the toolbars shown unconditionally
1397 // since we don't actually allow hiding them. The root cause of this part is not known.
1398 wxAuiPaneInfoArray& panes = m_auimgr.GetAllPanes();
1399
1400 for( size_t i = 0; i < panes.GetCount(); ++i )
1401 {
1402 if( panes.Item( i ).IsToolbar() )
1403 panes.Item( i ).Show( true );
1404 }
1405}
1406
1407
1408void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
1409 INFOBAR_MESSAGE_TYPE aType )
1410{
1411 wxCHECK( m_infoBar, /* void */ );
1412
1413 m_infoBar->RemoveAllButtons();
1414
1415 if( aShowCloseButton )
1416 m_infoBar->AddCloseButton();
1417
1418 GetInfoBar()->ShowMessageFor( aErrorMsg, 8000, wxICON_ERROR, aType );
1419}
1420
1421
1422void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
1423 std::function<void(void)> aCallback )
1424{
1425 wxCHECK( m_infoBar, /* void */ );
1426
1427 m_infoBar->RemoveAllButtons();
1428
1429 if( aShowCloseButton )
1430 m_infoBar->AddCloseButton();
1431
1432 if( aCallback )
1433 m_infoBar->SetCallback( aCallback );
1434
1435 GetInfoBar()->ShowMessageFor( aErrorMsg, 6000, wxICON_ERROR );
1436}
1437
1438
1439void EDA_BASE_FRAME::ShowInfoBarWarning( const wxString& aWarningMsg, bool aShowCloseButton )
1440{
1441 wxCHECK( m_infoBar, /* void */ );
1442
1443 m_infoBar->RemoveAllButtons();
1444
1445 if( aShowCloseButton )
1446 m_infoBar->AddCloseButton();
1447
1448 GetInfoBar()->ShowMessageFor( aWarningMsg, 6000, wxICON_WARNING );
1449}
1450
1451
1452void EDA_BASE_FRAME::ShowInfoBarMsg( const wxString& aMsg, bool aShowCloseButton )
1453{
1454 wxCHECK( m_infoBar, /* void */ );
1455
1456 m_infoBar->RemoveAllButtons();
1457
1458 if( aShowCloseButton )
1459 m_infoBar->AddCloseButton();
1460
1461 GetInfoBar()->ShowMessageFor( aMsg, 8000, wxICON_INFORMATION );
1462}
1463
1464
1465void EDA_BASE_FRAME::UpdateFileHistory( const wxString& FullFileName, FILE_HISTORY* aFileHistory )
1466{
1467 if( !aFileHistory )
1468 aFileHistory = m_fileHistory;
1469
1470 wxASSERT( aFileHistory );
1471
1472 aFileHistory->AddFileToHistory( FullFileName );
1473
1474 // Update the menubar to update the file history menu
1475 if( !m_isClosing && GetMenuBar() )
1476 {
1478 GetMenuBar()->Refresh();
1479 }
1480}
1481
1482
1483wxString EDA_BASE_FRAME::GetFileFromHistory( int cmdId, const wxString& type, FILE_HISTORY* aFileHistory )
1484{
1485 if( !aFileHistory )
1486 aFileHistory = m_fileHistory;
1487
1488 wxASSERT( aFileHistory );
1489
1490 int baseId = aFileHistory->GetBaseId();
1491
1492 wxASSERT( cmdId >= baseId && cmdId < baseId + (int) aFileHistory->GetCount() );
1493 int i = cmdId - baseId;
1494
1495 wxString fn = aFileHistory->GetHistoryFile( i );
1496
1497 if( !wxFileName::FileExists( fn ) )
1498 {
1499 KICAD_MESSAGE_DIALOG dlg( this, wxString::Format( _( "File '%s' was not found.\n" ), fn ), _( "Error" ),
1500 wxYES_NO | wxYES_DEFAULT | wxICON_ERROR | wxCENTER );
1501
1502 dlg.SetExtendedMessage( _( "Do you want to remove it from list of recently opened files?" ) );
1503 dlg.SetYesNoLabels( KICAD_MESSAGE_DIALOG::ButtonLabel( _( "Remove" ) ),
1504 KICAD_MESSAGE_DIALOG::ButtonLabel( _( "Keep" ) ) );
1505
1506 if( dlg.ShowModal() == wxID_YES )
1507 aFileHistory->RemoveFileFromHistory( i );
1508
1509 fn.Clear();
1510 }
1511
1512 // Update the menubar to update the file history menu
1513 if( GetMenuBar() )
1514 {
1516 GetMenuBar()->Refresh();
1517 }
1518
1519 return fn;
1520}
1521
1522
1524{
1525 wxASSERT( m_fileHistory );
1526
1527 m_fileHistory->ClearFileHistory();
1528
1529 // Update the menubar to update the file history menu
1530 if( GetMenuBar() )
1531 {
1533 GetMenuBar()->Refresh();
1534 }
1535}
1536
1537
1538void EDA_BASE_FRAME::OnKicadAbout( wxCommandEvent& event )
1539{
1540 void ShowAboutDialog( EDA_BASE_FRAME * aParent ); // See AboutDialog_main.cpp
1541 ShowAboutDialog( this );
1542}
1543
1544
1545void EDA_BASE_FRAME::OnPreferences( wxCommandEvent& event )
1546{
1547 ShowPreferences( wxEmptyString, wxEmptyString );
1548}
1549
1550
1551void EDA_BASE_FRAME::ShowPreferences( const wxString& aStartPage, const wxString& aStartParentPage )
1552{
1553 PAGED_DIALOG dlg( this, _( "Preferences" ), true, true, wxEmptyString,
1554 wxWindow::FromDIP( wxSize( 980, 560 ), nullptr ) );
1555
1556 dlg.SetEvtHandlerEnabled( false );
1557
1558 {
1559 WX_BUSY_INDICATOR busy_cursor;
1560
1561 WX_TREEBOOK* book = dlg.GetTreebook();
1562 PANEL_HOTKEYS_EDITOR* hotkeysPanel = new PANEL_HOTKEYS_EDITOR( this, book, false );
1563 std::vector<int> expand;
1564
1565 wxWindow* kicadMgr_window = wxWindow::FindWindowByName( KICAD_MANAGER_FRAME_NAME );
1566
1567 if( KICAD_MANAGER_FRAME* kicadMgr = static_cast<KICAD_MANAGER_FRAME*>( kicadMgr_window ) )
1568 {
1569 ACTION_MANAGER* actionMgr = kicadMgr->GetToolManager()->GetActionManager();
1570
1571 for( const auto& [name, action] : actionMgr->GetActions() )
1572 hotkeysPanel->ActionsList().push_back( action );
1573 }
1574
1575 book->AddLazyPage(
1576 []( wxWindow* aParent ) -> wxWindow*
1577 {
1578 return new PANEL_COMMON_SETTINGS( aParent );
1579 },
1580 _( "Common" ) );
1581
1582 book->AddLazyPage(
1583 []( wxWindow* aParent ) -> wxWindow*
1584 {
1585 return new PANEL_MOUSE_SETTINGS( aParent );
1586 }, _( "Mouse and Touchpad" ) );
1587
1588#if defined(__linux__) || defined(__FreeBSD__)
1589 book->AddLazyPage(
1590 [] ( wxWindow* aParent ) -> wxWindow*
1591 {
1592 return new PANEL_SPACEMOUSE( aParent );
1593 }, _( "SpaceMouse" ) );
1594#endif
1595
1596 book->AddPage( hotkeysPanel, _( "Hotkeys" ) );
1597
1598 book->AddLazyPage(
1599 []( wxWindow* aParent ) -> wxWindow*
1600 {
1601 return new PANEL_GIT_REPOS( aParent );
1602 }, _( "Version Control" ) );
1603
1604#ifdef KICAD_USE_SENTRY
1605 book->AddLazyPage(
1606 []( wxWindow* aParent ) -> wxWindow*
1607 {
1608 return new PANEL_DATA_COLLECTION( aParent );
1609 }, _( "Data Collection" ) );
1610#endif
1611
1612#define LAZY_CTOR( key ) \
1613 [this, kiface]( wxWindow* aParent ) \
1614 { \
1615 return kiface->CreateKiWindow( aParent, key, &Kiway() ); \
1616 }
1617
1618 // If a dll is not loaded, the loader will show an error message.
1619
1620 try
1621 {
1622 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_SCH ) )
1623 {
1624 kiface->GetActions( hotkeysPanel->ActionsList() );
1625
1627 expand.push_back( (int) book->GetPageCount() );
1628
1629 book->AddPage( new wxPanel( book ), _( "Symbol Editor" ) );
1630 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_DISP_OPTIONS ), _( "Display Options" ) );
1631 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_GRIDS ), _( "Grids" ) );
1632 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_SNAPPING ), _( "Snapping" ) );
1633 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_OPTIONS ), _( "Editing Options" ) );
1634 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_COLORS ), _( "Colors" ) );
1635 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_TOOLBARS ), _( "Toolbars" ) );
1636
1637 if( GetFrameType() == FRAME_SCH )
1638 expand.push_back( (int) book->GetPageCount() );
1639
1640 book->AddPage( new wxPanel( book ), _( "Schematic Editor" ) );
1641 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DISP_OPTIONS ), _( "Display Options" ) );
1642 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_GRIDS ), _( "Grids" ) );
1643 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_SNAPPING ), _( "Snapping" ) );
1644 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_EDIT_OPTIONS ), _( "Editing Options" ) );
1645 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_COLORS ), _( "Colors" ) );
1646 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_TOOLBARS ), _( "Toolbars" ) );
1647 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) );
1648 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DATA_SOURCES ), _( "Data Sources" ) );
1649 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_SIMULATOR ), _( "Simulator" ) );
1650 }
1651 }
1652 catch( ... )
1653 {
1654 }
1655
1656 try
1657 {
1658 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_PCB ) )
1659 {
1660 kiface->GetActions( hotkeysPanel->ActionsList() );
1661
1663 expand.push_back( (int) book->GetPageCount() );
1664
1665 book->AddPage( new wxPanel( book ), _( "Footprint Editor" ) );
1666 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DISPLAY_OPTIONS ), _( "Display Options" ) );
1667 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_GRIDS ), _( "Grids" ) );
1668 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_SNAPPING ), _( "Snapping" ) );
1669 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_ORIGINS_AXES ), _( "Origins & Axes" ) );
1670 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_EDIT_OPTIONS ), _( "Editing Options" ) );
1671 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_COLORS ), _( "Colors" ) );
1672 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_TOOLBARS ), _( "Toolbars" ) );
1673 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_FIELDS ), _( "Footprint Defaults" ) );
1674 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_GRAPHICS_VALUES ), _( "Graphics Defaults" ) );
1675 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_USER_LAYER_NAMES ), _( "User Layer Names" ) );
1676
1678 expand.push_back( (int) book->GetPageCount() );
1679
1680 book->AddPage( new wxPanel( book ), _( "PCB Editor" ) );
1681 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_DISPLAY_OPTS ), _( "Display Options" ) );
1682 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_GRIDS ), _( "Grids" ) );
1683 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_SNAPPING ), _( "Snapping" ) );
1684 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ORIGINS_AXES ), _( "Origins & Axes" ) );
1685 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_EDIT_OPTIONS ), _( "Editing Options" ) );
1686 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_COLORS ), _( "Colors" ) );
1687 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_TOOLBARS ), _( "Toolbars" ) );
1688 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ACTION_PLUGINS ), _( "Plugins" ) );
1689
1691 expand.push_back( (int) book->GetPageCount() );
1692
1693 book->AddPage( new wxPanel( book ), _( "3D Viewer" ) );
1694 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_DISPLAY_OPTIONS ), _( "General" ) );
1695 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_TOOLBARS ), _( "Toolbars" ) );
1696 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_OPENGL ), _( "Realtime Renderer" ) );
1697 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_RAYTRACING ), _( "Raytracing Renderer" ) );
1698 }
1699 }
1700 catch( ... )
1701 {
1702 }
1703
1704 try
1705 {
1706 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_GERBVIEW ) )
1707 {
1708 kiface->GetActions( hotkeysPanel->ActionsList() );
1709
1710 if( GetFrameType() == FRAME_GERBER )
1711 expand.push_back( (int) book->GetPageCount() );
1712
1713 book->AddPage( new wxPanel( book ), _( "Gerber Viewer" ) );
1714 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
1715 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_COLORS ), _( "Colors" ) );
1716 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_TOOLBARS ), _( "Toolbars" ) );
1717 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_GRIDS ), _( "Grids" ) );
1718 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_SNAPPING ), _( "Snapping" ) );
1719 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
1720 }
1721 }
1722 catch( ... )
1723 {
1724 }
1725
1726 try
1727 {
1728 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_PL_EDITOR ) )
1729 {
1730 kiface->GetActions( hotkeysPanel->ActionsList() );
1731
1732 if( GetFrameType() == FRAME_PL_EDITOR )
1733 expand.push_back( (int) book->GetPageCount() );
1734
1735 book->AddPage( new wxPanel( book ), _( "Drawing Sheet Editor" ) );
1736 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
1737 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_GRIDS ), _( "Grids" ) );
1738 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_SNAPPING ), _( "Snapping" ) );
1739 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_COLORS ), _( "Colors" ) );
1740 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_TOOLBARS ), _( "Toolbars" ) );
1741
1742 book->AddLazyPage(
1743 []( wxWindow* aParent ) -> wxWindow*
1744 {
1745 return new PANEL_PACKAGES_AND_UPDATES( aParent );
1746 }, _( "Packages and Updates" ) );
1747 }
1748 }
1749 catch( ... )
1750 {
1751 }
1752
1753 book->AddPage( new PANEL_PLUGIN_SETTINGS( book ), _( "Plugins" ) );
1754
1755 book->AddPage( new PANEL_MAINTENANCE( book, this ), _( "Maintenance" ) );
1756
1757 // Update all of the action hotkeys. The process of loading the actions through
1758 // the KiFACE will only get us the default hotkeys
1759 ReadHotKeyConfigIntoActions( wxEmptyString, hotkeysPanel->ActionsList() );
1760
1761 for( size_t i = 0; i < book->GetPageCount(); ++i )
1762 book->GetPage( i )->Layout();
1763
1764 for( int page : expand )
1765 book->ExpandNode( page );
1766
1767 if( !aStartPage.IsEmpty() )
1768 dlg.SetInitialPage( aStartPage, aStartParentPage );
1769
1770 dlg.SetEvtHandlerEnabled( true );
1771#undef LAZY_CTOR
1772 }
1773
1774 if( dlg.ShowModal() == wxID_OK )
1775 {
1776 // Update our grids that are cached in the tool
1777 m_toolManager->ResetTools( TOOL_BASE::REDRAW );
1780 }
1781
1782}
1783
1784
1785void EDA_BASE_FRAME::OnDropFiles( wxDropFilesEvent& aEvent )
1786{
1787 Raise();
1788
1789 wxString* files = aEvent.GetFiles();
1790
1791 for( int nb = 0; nb < aEvent.GetNumberOfFiles(); nb++ )
1792 {
1793 const wxFileName fn = wxFileName( files[nb] );
1794 wxString ext = fn.GetExt();
1795
1796 // Alias all gerber files as GerberFileExtension
1799
1800 if( m_acceptedExts.find( ext.ToStdString() ) != m_acceptedExts.end() )
1801 m_AcceptedFiles.emplace_back( fn );
1802 }
1803
1805 m_AcceptedFiles.clear();
1806}
1807
1808
1810{
1811 for( const wxFileName& file : m_AcceptedFiles )
1812 {
1813 wxString fn = file.GetFullPath();
1814 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( file.GetExt() ), &fn );
1815 }
1816}
1817
1818
1819bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
1820{
1821 wxString msg;
1822 wxFileName fn = aFileName;
1823
1824 // Check for absence of a file path with a file name. Unfortunately KiCad
1825 // uses paths relative to the current project path without the ./ part which
1826 // confuses wxFileName. Making the file name path absolute may be less than
1827 // elegant but it solves the problem.
1828 if( fn.GetPath().IsEmpty() && fn.HasName() )
1829 fn.MakeAbsolute();
1830
1831 wxCHECK_MSG( fn.IsOk(), false, wxT( "File name object is invalid. Bad programmer!" ) );
1832 wxCHECK_MSG( !fn.GetPath().IsEmpty(), false,
1833 wxT( "File name object path <" ) + fn.GetFullPath() + wxT( "> is not set. Bad programmer!" ) );
1834
1835 if( fn.IsDir() && !fn.IsDirWritable() )
1836 {
1837 msg.Printf( _( "Insufficient permissions to folder '%s'." ), fn.GetPath() );
1838 }
1839 else if( !fn.FileExists() && !fn.IsDirWritable() )
1840 {
1841 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1842 }
1843 else if( fn.FileExists() && !fn.IsFileWritable() )
1844 {
1845 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1846 }
1847
1848 if( !msg.IsEmpty() )
1849 {
1850 if( aVerbose )
1851 DisplayErrorMessage( this, msg );
1852
1853 return false;
1854 }
1855
1856 return true;
1857}
1858
1859
1861{
1862 // This function should be overridden in child classes
1863 return false;
1864}
1865
1866
1868{
1869 wxAcceleratorEntry entries[1];
1870 entries[0].Set( wxACCEL_CTRL, int( 'Q' ), wxID_EXIT );
1871 wxAcceleratorTable accel( 1, entries );
1872 SetAcceleratorTable( accel );
1873}
1874
1875
1881
1882
1884{
1885 m_undoList.PushCommand( aNewitem );
1886
1887 // Delete the extra items, if count max reached
1888 if( m_undoRedoCountMax > 0 )
1889 {
1890 int extraitems = GetUndoCommandCount() - m_undoRedoCountMax;
1891
1892 if( extraitems > 0 )
1893 ClearUndoORRedoList( UNDO_LIST, extraitems );
1894 }
1895}
1896
1897
1899{
1900 m_redoList.PushCommand( aNewitem );
1901
1902 // Delete the extra items, if count max reached
1903 if( m_undoRedoCountMax > 0 )
1904 {
1905 int extraitems = GetRedoCommandCount() - m_undoRedoCountMax;
1906
1907 if( extraitems > 0 )
1908 ClearUndoORRedoList( REDO_LIST, extraitems );
1909 }
1910}
1911
1912
1917
1918
1923
1924
1926{
1927 if( GetUndoCommandCount() > 0 )
1928 return m_undoList.m_CommandsList.back()->GetDescription();
1929
1930 return wxEmptyString;
1931}
1932
1933
1935{
1936 if( GetRedoCommandCount() > 0 )
1937 return m_redoList.m_CommandsList.back()->GetDescription();
1938
1939 return wxEmptyString;
1940}
1941
1942
1944{
1945 m_autoSaveRequired = true;
1946}
1947
1948
1950{
1951 SetUserUnits( aUnits );
1953
1954 wxCommandEvent e( EDA_EVT_UNITS_CHANGED );
1955 e.SetInt( static_cast<int>( aUnits ) );
1956 e.SetClientData( this );
1957 ProcessEventLocally( e );
1958}
1959
1960
1961void EDA_BASE_FRAME::OnMaximize( wxMaximizeEvent& aEvent )
1962{
1963 // When we maximize the window, we want to save the old information
1964 // so that we can add it to the settings on next window load.
1965 // Contrary to the documentation, this event seems to be generated
1966 // when the window is also being unmaximized on OSX, so we only
1967 // capture the size information when we maximize the window when on OSX.
1968#ifdef __WXOSX__
1969 if( !IsMaximized() )
1970#endif
1971 {
1973 m_normalFramePos = GetPosition();
1974 wxLogTrace( traceDisplayLocation, "Maximizing window - Saving position (%d, %d) with size (%d, %d)",
1977 }
1978
1979 // Skip event to actually maximize the window
1980 aEvent.Skip();
1981}
1982
1983
1985{
1986#if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 2, 9 )
1987 wxSize winSize = GetSize();
1988
1989 // GTK includes the window decorations in the normal GetSize call,
1990 // so we have to use a GTK-specific sizing call that returns the
1991 // non-decorated window size.
1993 {
1994 int width = 0;
1995 int height = 0;
1996 GTKDoGetSize( &width, &height );
1997
1998 winSize.Set( width, height );
1999 }
2000#else
2001 wxSize winSize = GetSize();
2002#endif
2003
2004 return winSize;
2005}
2006
2007
2009{
2010 // Update the icon theme when the system theme changes and update the toolbars
2012 ThemeChanged();
2013
2014 // This isn't handled by ThemeChanged()
2015 if( GetMenuBar() )
2016 {
2017 // For icons in menus, icon scaling & hotkeys
2019 GetMenuBar()->Refresh();
2020 }
2021}
2022
2023
2024void EDA_BASE_FRAME::onSystemColorChange( wxSysColourChangedEvent& aEvent )
2025{
2026 // Call the handler to update the colors used in the frame
2028
2029 // Skip the change event to ensure the rest of the window controls get it
2030 aEvent.Skip();
2031}
2032
2033
2034void EDA_BASE_FRAME::onIconize( wxIconizeEvent& aEvent )
2035{
2036 // Call the handler
2037 handleIconizeEvent( aEvent );
2038
2039 // Skip the event.
2040 aEvent.Skip();
2041}
2042
2043
2044#ifdef __WXMSW__
2045WXLRESULT EDA_BASE_FRAME::MSWWindowProc( WXUINT message, WXWPARAM wParam, WXLPARAM lParam )
2046{
2047 // This will help avoid the menu keeping focus when the alt key is released
2048 // You can still trigger accelerators as long as you hold down alt
2049 if( message == WM_SYSCOMMAND )
2050 {
2051 if( wParam == SC_KEYMENU && ( lParam >> 16 ) <= 0 )
2052 return 0;
2053 }
2054
2055 return wxFrame::MSWWindowProc( message, wParam, lParam );
2056}
2057#endif
2058
2059
2061{
2062 ACTION_MENU* langsMenu = new ACTION_MENU( false, aControlTool );
2063 langsMenu->SetTitle( _( "Set Language" ) );
2064 langsMenu->SetIcon( BITMAPS::language );
2065
2066 wxString tooltip;
2067
2068 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
2069 {
2070 wxString label;
2071
2072 if( LanguagesList[ii].m_DoNotTranslate )
2073 label = LanguagesList[ii].m_Lang_Label;
2074 else
2075 label = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
2076
2077 wxMenuItem* item = new wxMenuItem( langsMenu, LanguagesList[ii].m_KI_Lang_Identifier, // wxMenuItem wxID
2078 label, tooltip, wxITEM_CHECK );
2079
2080 langsMenu->Append( item );
2081 }
2082
2083 // This must be done after the items are added
2084 aMasterMenu->Add( langsMenu );
2085}
2086
2087
2088void EDA_BASE_FRAME::OnLanguageSelectionEvent( wxCommandEvent& event )
2089{
2090 int id = event.GetId();
2091
2092 // tell all the KIWAY_PLAYERs about the language change.
2093 Kiway().SetLanguage( id );
2094}
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:180
BITMAP_STORE * GetBitmapStore()
Definition bitmap.cpp:88
static TOOL_ACTION paste
Definition actions.h:76
static TOOL_ACTION about
Definition actions.h:286
static TOOL_ACTION reportBug
Definition actions.h:290
static TOOL_ACTION copy
Definition actions.h:74
static TOOL_ACTION donate
Definition actions.h:288
static TOOL_ACTION listHotKeys
Definition actions.h:287
static TOOL_ACTION getInvolved
Definition actions.h:289
static TOOL_ACTION undo
Definition actions.h:71
static TOOL_ACTION redo
Definition actions.h:72
static TOOL_ACTION cut
Definition actions.h:73
static TOOL_ACTION gettingStarted
Definition actions.h:284
static TOOL_ACTION help
Definition actions.h:285
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:43
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.
void ReloadPlugins(std::optional< wxString > aDirectoryToScan=std::nullopt, std::shared_ptr< REPORTER > aReporter=nullptr)
Clears the loaded plugins and actions and re-scans the filesystem to register new ones.
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.
bool AutosaveUsesLocalHistory() const
The backup format is the single switch that selects the autosave mechanism: the incremental format re...
AUTO_BACKUP m_Backup
std::vector< std::pair< wxString, wxString > > GetSelectedStale() const
AUTOSAVE_RECOVERY_CHOICE GetChoice() const
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:80
int ShowModal() override
The base frame for deriving all KiCad main window classes.
void SelectToolbarAction(const TOOL_ACTION &aAction) override
Select the given action in the toolbar group which contains it, if any.
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 ShowPreferences(const wxString &aStartPage, const wxString &aStartParentPage)
Display the preferences and settings of all opened editors paged dialog, starting with a particular p...
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 syncToolbarSelections()
Called after the toolbars are rebuilt so a frame can select the group entries that reflect its saved ...
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
bool m_isNonUserClose
Set by NonUserClose() to indicate that the user did not request the current close.
void CheckForAutosaveFiles(const wxString &aProjectPath, const std::vector< wxString > &aExtensions)
Check for autosave files newer than their source files for the given project.
void LoadWindowSettings(const WINDOW_SETTINGS *aCfg)
Load window settings from the given settings object.
std::vector< wxFileName > m_AcceptedFiles
bool m_uiUpdateHandlerBound
True once the single wxID_ANY UPDATE_UI handler has been bound.
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()
wxString m_perspective
wxDateTime m_autoSaveDeferredSince
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.
bool m_closeInProgress
Set while windowClosing() is deciding whether the frame may close.
ACTION_TOOLBAR * m_tbRight
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.
virtual bool canRunAutoSave() const
Return true when it is safe to run an autosave snapshot right now.
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 onUpdateUI(wxUpdateUIEvent &aEvent)
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)
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...
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()
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.
bool Running() const
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:92
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:348
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all KIWAY_PLAYER objects.
Definition kiway.cpp:506
@ FACE_SCH
eeschema DSO
Definition kiway.h:355
@ FACE_PL_EDITOR
Definition kiway.h:359
@ FACE_PCB
pcbnew DSO
Definition kiway.h:356
@ FACE_GERBVIEW
Definition kiway.h:358
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:459
virtual void CommonSettingsChanged(int aFlags=0)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition kiway.cpp:580
bool RunRegisteredSaversAndCommit(const wxString &aProjectPath, const wxString &aTitle, const wxString &aTagFileType=wxEmptyString)
Run all registered savers and, if any staged changes differ from HEAD, create a commit.
std::vector< std::pair< wxString, wxString > > FindStaleAutosaveFiles(const wxString &aProjectPath, const std::vector< wxString > &aExtensions) const
Enumerate autosave files newer than their corresponding source files for the project at aProjectPath,...
bool Init(const wxString &aProjectPath)
Initialize the local history repository for the given project path.
bool RunRegisteredSaversAsAutosaveFiles(const wxString &aProjectPath)
Run all registered savers and write their output to autosave files instead of committing to the local...
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:551
virtual API_PLUGIN_MANAGER & GetPluginManager() const
Definition pgm_base.h:139
virtual int GetSelectedLanguageIdentifier() const
Definition pgm_base.h:229
KICAD_API_SERVER & GetApiServer()
Definition pgm_base.h:141
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
A holder to handle information on schematic or board items.
void SaveFileState(const wxString &aFileName, const WINDOW_SETTINGS *aWindowCfg, bool aOpen)
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:207
RAII class that sets an value at construction and resets it to the original value at destruction.
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:79
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:76
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)
@ PROJECT_DIR
Inside the project directory (default)
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:48
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
static wxString buildRecoveredFileName(const wxFileName &aSrcFn, const wxDateTime &aStamp)
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
EDA_UNITS
Definition eda_units.h:44
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:29
@ PANEL_PCB_GRIDS
Definition frame_type.h:102
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ PANEL_SYM_EDIT_GRIDS
Definition frame_type.h:74
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ PANEL_3DV_TOOLBARS
Definition frame_type.h:113
@ PANEL_SCH_FIELD_NAME_TEMPLATES
Definition frame_type.h:86
@ PANEL_DS_TOOLBARS
Definition frame_type.h:127
@ PANEL_SCH_TOOLBARS
Definition frame_type.h:85
@ PANEL_GBR_DISPLAY_OPTIONS
Definition frame_type.h:115
@ PANEL_3DV_OPENGL
Definition frame_type.h:111
@ PANEL_GBR_SNAPPING
Definition frame_type.h:119
@ PANEL_FP_DEFAULT_GRAPHICS_VALUES
Definition frame_type.h:97
@ PANEL_PCB_TOOLBARS
Definition frame_type.h:106
@ PANEL_SYM_SNAPPING
Definition frame_type.h:75
@ PANEL_PCB_ORIGINS_AXES
Definition frame_type.h:108
@ PANEL_PCB_EDIT_OPTIONS
Definition frame_type.h:104
@ PANEL_SCH_DISP_OPTIONS
Definition frame_type.h:80
@ PANEL_FP_DISPLAY_OPTIONS
Definition frame_type.h:90
@ PANEL_SCH_SIMULATOR
Definition frame_type.h:87
@ FRAME_SCH
Definition frame_type.h:30
@ PANEL_DS_COLORS
Definition frame_type.h:126
@ PANEL_PCB_COLORS
Definition frame_type.h:105
@ PANEL_SYM_TOOLBARS
Definition frame_type.h:78
@ PANEL_FP_SNAPPING
Definition frame_type.h:92
@ PANEL_3DV_RAYTRACING
Definition frame_type.h:112
@ PANEL_SYM_EDIT_OPTIONS
Definition frame_type.h:76
@ PANEL_FP_GRIDS
Definition frame_type.h:91
@ PANEL_SCH_EDIT_OPTIONS
Definition frame_type.h:83
@ PANEL_FP_ORIGINS_AXES
Definition frame_type.h:99
@ PANEL_SYM_DISP_OPTIONS
Definition frame_type.h:73
@ PANEL_PCB_DISPLAY_OPTS
Definition frame_type.h:101
@ PANEL_DS_SNAPPING
Definition frame_type.h:125
@ PANEL_FP_COLORS
Definition frame_type.h:94
@ PANEL_FP_DEFAULT_FIELDS
Definition frame_type.h:96
@ PANEL_SYM_COLORS
Definition frame_type.h:77
@ FRAME_PL_EDITOR
Definition frame_type.h:55
@ PANEL_SCH_SNAPPING
Definition frame_type.h:82
@ PANEL_GBR_GRIDS
Definition frame_type.h:118
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
@ FRAME_GERBER
Definition frame_type.h:53
@ PANEL_DS_GRIDS
Definition frame_type.h:124
@ FRAME_PCB_DISPLAY3D
Definition frame_type.h:43
@ PANEL_GBR_TOOLBARS
Definition frame_type.h:121
@ PANEL_FP_EDIT_OPTIONS
Definition frame_type.h:93
@ PANEL_SCH_GRIDS
Definition frame_type.h:81
@ PANEL_FP_TOOLBARS
Definition frame_type.h:95
@ PANEL_PCB_ACTION_PLUGINS
Definition frame_type.h:107
@ PANEL_3DV_DISPLAY_OPTIONS
Definition frame_type.h:110
@ PANEL_DS_DISPLAY_OPTIONS
Definition frame_type.h:123
@ PANEL_SCH_COLORS
Definition frame_type.h:84
@ PANEL_GBR_COLORS
Definition frame_type.h:120
@ PANEL_GBR_EXCELLON_OPTIONS
Definition frame_type.h:117
@ PANEL_PCB_SNAPPING
Definition frame_type.h:103
@ KICAD_MAIN_FRAME_T
Definition frame_type.h:69
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:58
@ ID_LANGUAGE_CHOICE
Definition id.h:62
@ ID_LANGUAGE_CHOICE_END
Definition id.h:110
@ ID_FILE1
Definition id.h:55
@ ID_AUTO_SAVE_TIMER
Definition id.h:50
std::string message
EVT_MENU(ID_COMPARE_PROJECT_BRANCHES, KICAD_MANAGER_FRAME::OnCompareProjectBranches) KICAD_MANAGER_FRAME
void RemoveShutdownBlockReason(wxWindow *aWindow)
Removes any shutdown block reason set.
Definition unix/app.cpp:97
void SetWMClass(wxWindow *aWindow, const wxString &aClass)
Tag a top-level window with the freedesktop application id of its installed launcher,...
Definition wxgtk/ui.cpp:305
PGM_BASE & Pgm()
The global program "get" accessor.
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition pgm_base.cpp:86
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)
BACKUP_LOCATION location
Where backups, history, and autosave files live.
Implement a participant in the KIWAY alchemy.
Definition kiway.h:153
Store the common settings that are saved and loaded for each window / frame.
WINDOW_STATE state
nlohmann::json aui_state
wxString perspective
Store the window positioning/state.
unsigned int display
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)
static const long long MM
@ 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.