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>
29#include <api/api_server.h>
30#include <bitmaps.h>
31#include <bitmap_store.h>
32#include <dialog_shim.h>
40#include <eda_dde.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
353}
354
355
356bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent )
357{
358#ifdef __WXMAC__
359 // Apple in its infinite wisdom will raise a disabled window before even passing
360 // us the event, so we have no way to stop it. Instead, we have to catch an
361 // improperly ordered disabled window and quasi-modal dialog here and reorder
362 // them.
363 if( !IsEnabled() && IsActive() )
364 {
365 wxWindow* dlg = findQuasiModalDialog();
366
367 if( dlg )
368 dlg->Raise();
369 }
370#endif
371
372#ifdef __WXMSW__
373 // When changing DPI to a lower value, somehow, called from wxNonOwnedWindow::HandleDPIChange,
374 // our sizers compute a min size that is larger than the old frame size. wx then sets this wrong size.
375 // This shouldn't be needed since the OS have already sent a size event.
376 // Avoid this wx behaviour by pretending we've processed the event even if we use Skip in handlers.
377 if( aEvent.GetEventType() == wxEVT_DPI_CHANGED )
378 {
379 wxFrame::ProcessEvent( aEvent );
380 return true;
381 }
382#endif
383
384 if( !wxFrame::ProcessEvent( aEvent ) )
385 return false;
386
387 if( Pgm().m_Quitting )
388 return true;
389
390 if( !m_isClosing && m_supportsAutoSave && IsShownOnScreen() && IsActive()
392 && GetAutoSaveInterval() > 0 )
393 {
394 if( !m_autoSavePending )
395 {
396 wxLogTrace( traceAutoSave, wxT( "Starting auto save timer." ) );
397 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
398 m_autoSavePending = true;
399
400 // A fresh cycle starts here (a prior snapshot completed or an explicit save cleared
401 // the pending state), so drop any deferral streak left over from that cycle; otherwise
402 // its stale start time could force the next snapshot to run mid-interaction.
403 m_autoSaveDeferredSince = wxInvalidDateTime;
404 }
405 else if( m_autoSaveTimer->IsRunning() )
406 {
407 wxLogTrace( traceAutoSave, wxT( "Stopping auto save timer." ) );
408 m_autoSaveTimer->Stop();
409 m_autoSavePending = false;
410 }
411 }
412
413 return true;
414}
415
416
421
422
423void EDA_BASE_FRAME::onAutoSaveTimer( wxTimerEvent& aEvent )
424{
425 // Don't stomp on someone else's timer event.
426 if( aEvent.GetId() != ID_AUTO_SAVE_TIMER )
427 {
428 aEvent.Skip();
429 return;
430 }
431
432 // A one-shot tick can already be queued when the frame starts closing; running the saver batch
433 // then would serialize documents whose editors are mid-teardown, so bail once closing begins.
434 if( m_isClosing )
435 return;
436
437 // When the save is deferred (an interactive operation is in progress) keep the timer armed so
438 // a later tick retries. Maintaining m_autoSavePending here preserves the "pending == timer
439 // running" invariant that ProcessEvent() relies on to avoid re-arming the timer on every event.
441 {
442 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
443 m_autoSavePending = true;
444 }
445 else
446 {
447 m_autoSavePending = false;
448 }
449}
450
451
452static wxString buildRecoveredFileName( const wxFileName& aSrcFn, const wxDateTime& aStamp )
453{
454 wxString stamp = aStamp.IsValid() ? aStamp.Format( wxS( "%Y-%m-%d_%H%M%S" ) ) : wxString( wxS( "unknown-time" ) );
455
456 wxFileName recovered( aSrcFn );
457 recovered.SetName( aSrcFn.GetName() + wxS( ".recovered." ) + stamp );
458
459 int seq = 1;
460
461 while( recovered.FileExists() )
462 recovered.SetName( aSrcFn.GetName() + wxS( ".recovered." ) + stamp + wxString::Format( wxS( ".%d" ), seq++ ) );
463
464 return recovered.GetFullPath();
465}
466
467
468void EDA_BASE_FRAME::CheckForAutosaveFiles( const wxString& aProjectPath, const std::vector<wxString>& aExtensions )
469{
470 auto stale = Kiway().LocalHistory().FindStaleAutosaveFiles( aProjectPath, aExtensions );
471
472 if( stale.empty() )
473 return;
474
475 DIALOG_AUTOSAVE_RECOVERY dlg( this, stale );
476 dlg.ShowModal();
477
478 auto selected = dlg.GetSelectedStale();
479
480 switch( dlg.GetChoice() )
481 {
483 for( const auto& [autosavePath, srcPath] : selected )
484 {
485 if( !wxCopyFile( autosavePath, srcPath, true ) )
486 {
487 wxLogError( _( "Failed to recover auto-saved file '%s'." ), srcPath );
488 continue;
489 }
490
491 wxRemoveFile( autosavePath );
492 }
493 break;
494
496 for( const auto& [autosavePath, srcPath] : selected )
497 {
498 if( wxFileExists( autosavePath ) )
499 wxRemoveFile( autosavePath );
500 }
501 break;
502
504 for( const auto& [autosavePath, srcPath] : selected )
505 {
506 wxFileName autosaveFn( autosavePath );
507 wxFileName srcFn( srcPath );
508 wxDateTime stamp = autosaveFn.FileExists() ? autosaveFn.GetModificationTime() : wxDateTime::Now();
509
510 wxString target = buildRecoveredFileName( srcFn, stamp );
511
512 if( !wxCopyFile( autosavePath, target, true ) )
513 {
514 wxLogError( _( "Failed to write recovered file '%s'." ), target );
515 continue;
516 }
517
518 wxRemoveFile( autosavePath );
519 }
520 break;
521
523 // Leave all autosaves on disk so the dialog can offer them again next open.
524 break;
525 }
526}
527
528
530{
531 // Defer the snapshot if the user is mid-interaction. Serializing a large document on the
532 // UI thread freezes the editor for seconds; deferring keeps the dirty flags set so the
533 // rescheduled timer tick will pick the work up once the operation completes. To avoid
534 // starving the snapshot when the user parks in an interactive tool, the deferral is bounded
535 // and the save is forced once it has been outstanding for longer than the cap.
536 if( !canRunAutoSave() )
537 {
538 wxDateTime now = wxDateTime::Now();
539
540 if( !m_autoSaveDeferredSince.IsValid() )
542
543 wxTimeSpan maxDeferral = wxTimeSpan::Seconds( std::max( 60, GetAutoSaveInterval() * 12 ) );
544
545 if( now - m_autoSaveDeferredSince < maxDeferral )
546 {
547 wxLogTrace( traceAutoSave, wxT( "Deferring auto save; an interactive operation is in progress." ) );
548 return false;
549 }
550
551 wxLogTrace( traceAutoSave, wxT( "Auto save deferral exceeded; saving despite interactive operation." ) );
552 }
553
554 // The deferral is resolved (either the user went idle or the cap forced the snapshot), so the
555 // cycle is now consumed regardless of the saver outcome. The snapshot is best effort: a
556 // droppable cycle (a prior autosave still writing) is recaptured by the next edit's OnModify,
557 // so clear the flags here rather than re-arming on the saver result, which would poll forever
558 // in degenerate states such as no registered savers.
559 m_autoSaveDeferredSince = wxInvalidDateTime;
560 m_autoSaveRequired = false;
561
563
564 // Incremental and zip-autosave both write outside the project tree when the user
565 // selects USER_DIR, so a read-only project is fine in that mode. Only when the
566 // chosen location is the project directory does the project tree need to be writable.
567 if( cs->m_Backup.location == BACKUP_LOCATION::PROJECT_DIR && Prj().IsReadOnly() )
568 return true;
569
570 if( cs->AutosaveUsesLocalHistory() )
571 Kiway().LocalHistory().RunRegisteredSaversAndCommit( Prj().GetProjectPath(), wxS( "Autosave" ) );
572 else
574
575 return true;
576}
577
578
579void EDA_BASE_FRAME::OnCharHook( wxKeyEvent& aKeyEvent )
580{
581 wxLogTrace( kicadTraceKeyEvent, wxS( "EDA_BASE_FRAME::OnCharHook %s" ), dump( aKeyEvent ) );
582
583 // Key events can be filtered here.
584 // Currently no filtering is made.
585 aKeyEvent.Skip();
586}
587
588
589void EDA_BASE_FRAME::OnMenuEvent( wxMenuEvent& aEvent )
590{
591 if( !m_toolDispatcher )
592 aEvent.Skip();
593 else
594 m_toolDispatcher->DispatchWxEvent( aEvent );
595}
596
597
599{
600 // Bind a single wxID_ANY dispatcher on first use rather than one Bind() per action.
601 // wxEvtHandler::SearchDynamicEventTable does a linear scan through all dynamic bindings
602 // for every event dispatch (including mouse motion), so 150 individual bindings cost
603 // O(150) per event regardless of event type. One wxID_ANY binding costs O(1).
605 {
606 Bind( wxEVT_UPDATE_UI, &EDA_BASE_FRAME::onUpdateUI, this );
608 }
609
611 std::placeholders::_1,
612 this,
613 aConditions );
614}
615
616
618{
619 m_uiUpdateMap.erase( aID );
620}
621
622
623void EDA_BASE_FRAME::onUpdateUI( wxUpdateUIEvent& aEvent )
624{
625 const auto it = m_uiUpdateMap.find( aEvent.GetId() );
626
627 if( it != m_uiUpdateMap.end() )
628 it->second( aEvent );
629 else
630 aEvent.Skip();
631}
632
633
634void EDA_BASE_FRAME::HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAME* aFrame,
635 ACTION_CONDITIONS& aCond )
636{
637 bool checkRes = false;
638 bool enableRes = true;
639 bool showRes = true;
640 bool isCut = aEvent.GetId() == ACTIONS::cut.GetUIId();
641 bool isCopy = aEvent.GetId() == ACTIONS::copy.GetUIId();
642 bool isPaste = aEvent.GetId() == ACTIONS::paste.GetUIId();
643 SELECTION& selection = aFrame->GetCurrentSelection();
644
645 try
646 {
647 checkRes = aCond.checkCondition( selection );
648 enableRes = aCond.enableCondition( selection );
649 showRes = aCond.showCondition( selection );
650 }
651 catch( std::exception& )
652 {
653 // Something broke with the conditions, just skip the event.
654 aEvent.Skip();
655 return;
656 }
657
658 if( showRes && aEvent.GetId() == ACTIONS::undo.GetUIId() )
659 {
660 wxString msg = _( "Undo" );
661
662 if( enableRes )
663 msg += wxS( " " ) + aFrame->GetUndoActionDescription();
664
665 aEvent.SetText( msg );
666 }
667 else if( showRes && aEvent.GetId() == ACTIONS::redo.GetUIId() )
668 {
669 wxString msg = _( "Redo" );
670
671 if( enableRes )
672 msg += wxS( " " ) + aFrame->GetRedoActionDescription();
673
674 aEvent.SetText( msg );
675 }
676
677 if( isCut || isCopy || isPaste )
678 {
679 wxWindow* focus = wxWindow::FindFocus();
680 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
681
682 if( textEntry && isCut && textEntry->CanCut() )
683 enableRes = true;
684 else if( textEntry && isCopy && textEntry->CanCopy() )
685 enableRes = true;
686 else if( textEntry && isPaste && textEntry->CanPaste() )
687 enableRes = true;
688 else if( dynamic_cast<WX_GRID*>( focus ) )
689 enableRes = false; // Must disable menu in order to get command as CharHook event
690 }
691
692 aEvent.Enable( enableRes );
693 aEvent.Show( showRes );
694
695 if( aEvent.IsCheckable() )
696 aEvent.Check( checkRes );
697}
698
699
701{
702 // Setup the conditions to check a language menu item
703 auto isCurrentLang =
704 [] ( const SELECTION& aSel, int aLangIdentifier )
705 {
706 return Pgm().GetSelectedLanguageIdentifier() == aLangIdentifier;
707 };
708
709 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
710 {
712 cond.Check( std::bind( isCurrentLang, std::placeholders::_1,
713 LanguagesList[ii].m_WX_Lang_Identifier ) );
714 RegisterUIUpdateHandler( LanguagesList[ii].m_KI_Lang_Identifier, cond );
715 }
716}
717
718
720 const ACTION_TOOLBAR_CONTROL_FACTORY& aControlFactory )
721{
722 m_toolbarControlFactories.emplace( aControlDesc.GetName(), aControlFactory );
723}
724
725
727{
728 for( auto& control : m_toolbarControlFactories )
729 {
730 if( control.first == aName )
731 return &control.second;
732 }
733
734 return nullptr;
735}
736
737
741
742
744{
745 if( m_tbLeft )
746 m_tbLeft->SelectAction( aAction );
747
748 if( m_tbTopMain )
749 m_tbTopMain->SelectAction( aAction );
750
751 if( m_tbTopAux )
752 m_tbTopAux->SelectAction( aAction );
753
754 if( m_tbRight )
755 m_tbRight->SelectAction( aAction );
756}
757
758
760{
761 wxWindowUpdateLocker dummy( this );
762
763 wxASSERT( m_toolbarSettings );
764
765 if( m_tbRight )
766 m_tbRight->ClearToolbar();
767
768 if( m_tbLeft )
769 m_tbLeft->ClearToolbar();
770
771 if( m_tbTopMain )
772 m_tbTopMain->ClearToolbar();
773
774 if( m_tbTopAux )
775 m_tbTopAux->ClearToolbar();
776
777 std::optional<TOOLBAR_CONFIGURATION> tbConfig;
778
779 // Drawing tools (typically on right edge of window)
780 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::RIGHT, config()->m_CustomToolbars );
781
782 if( tbConfig.has_value() )
783 {
784 if( !m_tbRight )
785 {
786 m_tbRight = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
787 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL | wxAUI_TB_TEXT
788 | wxAUI_TB_OVERFLOW );
789 m_tbRight->SetAuiManager( &m_auimgr );
790 }
791
792 m_tbRight->ApplyConfiguration( tbConfig.value() );
793 }
794
795 // Options (typically on left edge of window)
796 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::LEFT, config()->m_CustomToolbars );
797
798 if( tbConfig.has_value() )
799 {
800 if( !m_tbLeft )
801 {
802 m_tbLeft = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
803 KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
804 m_tbLeft->SetAuiManager( &m_auimgr );
805 }
806
807 m_tbLeft->ApplyConfiguration( tbConfig.value() );
808 }
809
810 // Top main toolbar (the top one)
811 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::TOP_MAIN, config()->m_CustomToolbars );
812
813 if( tbConfig.has_value() )
814 {
815 if( !m_tbTopMain )
816 {
817 m_tbTopMain = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
818 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT | wxAUI_TB_HORIZONTAL
819 | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
820 m_tbTopMain->SetAuiManager( &m_auimgr );
821 }
822
823 m_tbTopMain->ApplyConfiguration( tbConfig.value() );
824 }
825
826 // Top aux toolbar (the bottom one)
827 tbConfig = m_toolbarSettings->GetToolbarConfig( TOOLBAR_LOC::TOP_AUX, config()->m_CustomToolbars );
828
829 if( tbConfig.has_value() )
830 {
831 if( !m_tbTopAux )
832 {
833 m_tbTopAux = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
834 KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT | wxAUI_TB_HORIZONTAL
835 | wxAUI_TB_TEXT | wxAUI_TB_OVERFLOW );
836 m_tbTopAux->SetAuiManager( &m_auimgr );
837 }
838
839 m_tbTopAux->ApplyConfiguration( tbConfig.value() );
840 }
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 )
892 } );
893}
894
895
896void EDA_BASE_FRAME::AddStandardHelpMenu( wxMenuBar* aMenuBar )
897{
898 COMMON_CONTROL* commonControl = m_toolManager->GetTool<COMMON_CONTROL>();
899 ACTION_MENU* helpMenu = new ACTION_MENU( false, commonControl );
900
901 helpMenu->Add( ACTIONS::help );
902 helpMenu->Add( ACTIONS::gettingStarted );
903 helpMenu->Add( ACTIONS::listHotKeys );
904 helpMenu->Add( ACTIONS::getInvolved );
905 helpMenu->Add( ACTIONS::donate );
906 helpMenu->Add( ACTIONS::reportBug );
907
908 helpMenu->AppendSeparator();
909 helpMenu->Add( ACTIONS::about );
910
911 aMenuBar->Append( helpMenu, _( "&Help" ) );
912}
913
914
915
917{
918 wxString menuItemLabel = aAction.GetMenuLabel();
919 wxMenuBar* menuBar = GetMenuBar();
920
921 for( size_t ii = 0; ii < menuBar->GetMenuCount(); ++ii )
922 {
923 for( wxMenuItem* menuItem : menuBar->GetMenu( ii )->GetMenuItems() )
924 {
925 if( menuItem->GetItemLabelText() == menuItemLabel )
926 {
927 wxString menuTitleLabel = menuBar->GetMenuLabelText( ii );
928
929 menuTitleLabel.Replace( wxS( "&" ), wxS( "&&" ) );
930 menuItemLabel.Replace( wxS( "&" ), wxS( "&&" ) );
931
932 return wxString::Format( _( "Run: %s > %s" ),
933 menuTitleLabel,
934 menuItemLabel );
935 }
936 }
937 }
938
939 return wxString::Format( _( "Run: %s" ), aAction.GetFriendlyName() );
940};
941
942
944{
946
947 if( GetMenuBar() )
948 {
950 GetMenuBar()->Refresh();
951 }
952}
953
954
956{
958
959 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
960
961 bool running = Pgm().GetApiServer().Running();
962
963 if( running && !settings->m_Api.enable_server )
964 Pgm().GetApiServer().Stop();
965 else if( !running && settings->m_Api.enable_server )
966 Pgm().GetApiServer().Start();
967
968 if( m_fileHistory )
969 {
970 int historySize = settings->m_System.file_history_size;
971 m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) );
972 }
973
974 if( Pgm().GetCommonSettings()->AutosaveUsesLocalHistory() )
975 Kiway().LocalHistory().Init( Prj().GetProjectPath() );
976
978 ThemeChanged();
979
980 if( GetMenuBar() )
981 {
982 // For icons in menus, icon scaling & hotkeys
984 GetMenuBar()->Refresh();
985 }
986
987 // Update the toolbars
989}
990
991
993{
995
996 // Update all the toolbars to have new icons
997 wxAuiPaneInfoArray panes = m_auimgr.GetAllPanes();
998
999 for( size_t i = 0; i < panes.GetCount(); ++i )
1000 {
1001 if( ACTION_TOOLBAR* toolbar = dynamic_cast<ACTION_TOOLBAR*>( panes[i].window ) )
1002 toolbar->RefreshBitmaps();
1003 }
1004}
1005
1006
1007void EDA_BASE_FRAME::OnSize( wxSizeEvent& aEvent )
1008{
1009#ifdef __WXMAC__
1010 int currentDisplay = wxDisplay::GetFromWindow( this );
1011
1012 if( m_displayIndex >= 0 && currentDisplay >= 0 && currentDisplay != m_displayIndex )
1013 {
1014 wxLogTrace( traceDisplayLocation, wxS( "OnSize: current display changed %d to %d" ),
1015 m_displayIndex, currentDisplay );
1016 m_displayIndex = currentDisplay;
1018 }
1019#endif
1020
1021 aEvent.Skip();
1022}
1023
1024
1025void EDA_BASE_FRAME::LoadWindowState( const wxString& aFileName )
1026{
1027 if( !Pgm().GetCommonSettings()->m_Session.remember_open_files )
1028 return;
1029
1030 if( const PROJECT_FILE_STATE* state = Prj().GetLocalSettings().GetFileState( aFileName ) )
1031 LoadWindowState( state->window );
1032}
1033
1034
1036{
1037 bool wasDefault = false;
1038
1039 m_framePos.x = aState.pos_x;
1040 m_framePos.y = aState.pos_y;
1041 m_frameSize.x = aState.size_x;
1042 m_frameSize.y = aState.size_y;
1043
1044 wxLogTrace( traceDisplayLocation, wxS( "Config position (%d, %d) with size (%d, %d)" ),
1046
1047 // Ensure minimum size is set if the stored config was zero-initialized
1048 wxSize minSize = minSizeLookup( m_ident, this );
1049
1050 if( m_frameSize.x < minSize.x || m_frameSize.y < minSize.y )
1051 {
1052 m_frameSize = defaultSize( m_ident, this );
1053 wasDefault = true;
1054
1055 wxLogTrace( traceDisplayLocation, wxS( "Using minimum size (%d, %d)" ), m_frameSize.x, m_frameSize.y );
1056 }
1057
1058 wxLogTrace( traceDisplayLocation, wxS( "Number of displays: %d" ), wxDisplay::GetCount() );
1059
1060 if( aState.display >= wxDisplay::GetCount() )
1061 {
1062 wxLogTrace( traceDisplayLocation, wxS( "Previous display not found" ) );
1063
1064 // If it isn't attached, use the first display
1065 // Warning wxDisplay has 2 ctor variants. the parameter needs a type:
1066 const unsigned int index = 0;
1067 wxDisplay display( index );
1068 wxRect clientSize = display.GetGeometry();
1069
1070 m_framePos = wxDefaultPosition;
1071
1072 // Ensure the window fits on the display, since the other one could have been larger
1073 if( m_frameSize.x > clientSize.width )
1074 m_frameSize.x = clientSize.width;
1075
1076 if( m_frameSize.y > clientSize.height )
1077 m_frameSize.y = clientSize.height;
1078 }
1079 else
1080 {
1081 wxPoint upperRight( m_framePos.x + m_frameSize.x, m_framePos.y );
1082 wxPoint upperLeft( m_framePos.x, m_framePos.y );
1083
1084 wxDisplay display( aState.display );
1085 wxRect clientSize = display.GetClientArea();
1086
1087 int yLimTop = clientSize.y;
1088 int yLimBottom = clientSize.y + clientSize.height;
1089 int xLimLeft = clientSize.x;
1090 int xLimRight = clientSize.x + clientSize.width;
1091
1092 if( upperLeft.x > xLimRight || // Upper left corner too close to right edge of screen
1093 upperRight.x < xLimLeft || // Upper right corner too close to left edge of screen
1094 upperLeft.y < yLimTop || // Upper corner too close to the bottom of the screen
1095 upperLeft.y > yLimBottom )
1096 {
1097 m_framePos = wxDefaultPosition;
1098 wxLogTrace( traceDisplayLocation, wxS( "Resetting to default position" ) );
1099 }
1100
1101 // Clamp the saved size to the current display, in case the window was sized for a
1102 // larger external monitor that is no longer attached.
1103 if( m_frameSize.x > clientSize.width )
1104 {
1105 wxLogTrace( traceDisplayLocation, wxS( "Clamping window width %d to display width %d" ),
1106 m_frameSize.x, clientSize.width );
1107 m_frameSize.x = clientSize.width;
1108 }
1109
1110 if( m_frameSize.y > clientSize.height )
1111 {
1112 wxLogTrace( traceDisplayLocation, wxS( "Clamping window height %d to display height %d" ),
1113 m_frameSize.y, clientSize.height );
1114 m_frameSize.y = clientSize.height;
1115 }
1116 }
1117
1118 wxLogTrace( traceDisplayLocation, wxS( "Final window position (%d, %d) with size (%d, %d)" ),
1120
1121 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
1122
1123 // Center the window if we reset to default
1124 if( m_framePos.x == -1 )
1125 {
1126 wxLogTrace( traceDisplayLocation, wxS( "Centering window" ) );
1127 Center();
1128 m_framePos = GetPosition();
1129 }
1130
1131 // Record the frame sizes in an un-maximized state
1134
1135 // Maximize if we were maximized before
1136 if( aState.maximized || ( wasDefault && m_maximizeByDefault ) )
1137 {
1138 wxLogTrace( traceDisplayLocation, wxS( "Maximizing window" ) );
1139 Maximize();
1140 }
1141
1142 m_displayIndex = wxDisplay::GetFromWindow( this );
1143}
1144
1145
1147{
1148 wxDisplay display( wxDisplay::GetFromWindow( this ) );
1149 wxRect clientSize = display.GetClientArea();
1150 wxPoint pos = GetPosition();
1151 wxSize size = GetWindowSize();
1152
1153 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: clientArea (%d, %d) w %d h %d" ),
1154 clientSize.x, clientSize.y,
1155 clientSize.width, clientSize.height );
1156
1157 if( pos.y < clientSize.y )
1158 {
1159 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: y pos %d below minimum, setting to %d" ),
1160 pos.y, clientSize.y );
1161 pos.y = clientSize.y;
1162 }
1163
1164 if( pos.x < clientSize.x )
1165 {
1166 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: x pos %d below minimum, setting to %d" ),
1167 pos.x, clientSize.x );
1168 pos.x = clientSize.x;
1169 }
1170
1171 if( pos.x + size.x - clientSize.x > clientSize.width )
1172 {
1173 int newWidth = clientSize.width - ( pos.x - clientSize.x );
1174 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: width %d above available %d, setting to %d" ),
1175 pos.x + size.x, clientSize.width, newWidth );
1176 size.x = newWidth;
1177 }
1178
1179 if( pos.y + size.y - clientSize.y > clientSize.height )
1180 {
1181 int newHeight = clientSize.height - ( pos.y - clientSize.y );
1182 wxLogTrace( traceDisplayLocation, wxS( "ensureWindowIsOnScreen: height %d above available %d, setting to %d" ),
1183 pos.y + size.y, clientSize.height, newHeight );
1184 size.y = newHeight;
1185 }
1186
1187 wxLogTrace( traceDisplayLocation, wxS( "Updating window position (%d, %d) with size (%d, %d)" ),
1188 pos.x, pos.y, size.x, size.y );
1189
1190 SetSize( pos.x, pos.y, size.x, size.y );
1191}
1192
1193
1195{
1196 LoadWindowState( aCfg->state );
1197
1198 m_perspective = aCfg->perspective;
1199 m_auiLayoutState = std::make_unique<nlohmann::json>( aCfg->aui_state );
1200 m_mruPath = aCfg->mru_path;
1201
1203}
1204
1205
1207{
1208 if( IsIconized() )
1209 return;
1210
1211 // If the window is maximized, we use the saved window size from before it was maximized
1212 if( IsMaximized() )
1213 {
1216 }
1217 else
1218 {
1220 m_framePos = GetPosition();
1221 }
1222
1223 aCfg->state.pos_x = m_framePos.x;
1224 aCfg->state.pos_y = m_framePos.y;
1225 aCfg->state.size_x = m_frameSize.x;
1226 aCfg->state.size_y = m_frameSize.y;
1227 aCfg->state.maximized = IsMaximized();
1228 aCfg->state.display = wxDisplay::GetFromWindow( this );
1229
1230 wxLogTrace( traceDisplayLocation, wxS( "Saving window maximized: %s" ),
1231 IsMaximized() ? wxS( "true" ) : wxS( "false" ) );
1232 wxLogTrace( traceDisplayLocation, wxS( "Saving config position (%d, %d) with size (%d, %d)" ),
1234
1235 // Once this is fully implemented, wxAuiManager will be used to maintain
1236 // the persistence of the main frame and all it's managed windows and
1237 // all of the legacy frame persistence position code can be removed.
1238#if wxCHECK_VERSION( 3, 3, 0 )
1239 {
1240 WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
1241 nlohmann::json state = serializer.Serialize();
1242
1243 if( state.is_null() || state.empty() )
1244 aCfg->aui_state = nlohmann::json();
1245 else
1246 aCfg->aui_state = state;
1247
1248 aCfg->perspective.clear();
1249 }
1250#else
1251 aCfg->perspective = m_auimgr.SavePerspective().ToStdString();
1252 aCfg->aui_state = nlohmann::json();
1253#endif
1254
1255 aCfg->mru_path = m_mruPath;
1256}
1257
1258
1260{
1262
1263 // Get file history size from common settings
1264 int fileHistorySize = Pgm().GetCommonSettings()->m_System.file_history_size;
1265
1266 // Load the recently used files into the history menu
1267 m_fileHistory = new FILE_HISTORY( (unsigned) std::max( 1, fileHistorySize ), ID_FILE1, ID_FILE_LIST_CLEAR );
1268 m_fileHistory->Load( *aCfg );
1269}
1270
1271
1273{
1274 wxCHECK( config(), /* void */ );
1275
1277
1278 bool fileOpen = m_isClosing && m_isNonUserClose;
1279
1280 wxString currentlyOpenedFile = GetCurrentFileName();
1281
1282 if( Pgm().GetCommonSettings()->m_Session.remember_open_files && !currentlyOpenedFile.IsEmpty() )
1283 {
1284 wxFileName rfn( currentlyOpenedFile );
1285 rfn.MakeRelativeTo( Prj().GetProjectPath() );
1286 Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &aCfg->m_Window, fileOpen );
1287 }
1288
1289 // Save the recently used files list
1290 if( m_fileHistory )
1291 {
1292 // Save the currently opened file in the file history
1293 if( !currentlyOpenedFile.IsEmpty() )
1294 UpdateFileHistory( currentlyOpenedFile );
1295
1296 m_fileHistory->Save( *aCfg );
1297 }
1298}
1299
1300
1305
1306
1308{
1309 // KICAD_MANAGER_FRAME overrides this
1310 return Kiface().KifaceSettings();
1311}
1312
1313
1315{
1316 return Kiface().KifaceSearch();
1317}
1318
1319
1321{
1322 return Kiface().GetHelpFileName();
1323}
1324
1325
1326void EDA_BASE_FRAME::PrintMsg( const wxString& text )
1327{
1328 SetStatusText( text );
1329}
1330
1331
1333{
1334#if defined( __WXOSX_MAC__ )
1336#else
1337 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
1338
1339 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) ).Top().Layer(1) );
1340#endif
1341}
1342
1343
1345{
1346#if defined( __WXOSX_MAC__ )
1347 m_auimgr.Update();
1348#else
1349 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
1350 // hiding it.
1351 m_auimgr.Update();
1352
1353 // We don't want the infobar displayed right away
1354 m_auimgr.GetPane( wxS( "InfoBar" ) ).Hide();
1355 m_auimgr.Update();
1356#endif
1357}
1358
1359
1361{
1362 if( !ADVANCED_CFG::GetCfg().m_EnableUseAuiPerspective )
1363 return;
1364
1365 bool restored = false;
1366
1367#if wxCHECK_VERSION( 3, 3, 0 )
1368 if( m_auiLayoutState && !m_auiLayoutState->is_null() && !m_auiLayoutState->empty() )
1369 {
1370 WX_AUI_JSON_SERIALIZER serializer( m_auimgr );
1371
1372 if( serializer.Deserialize( *m_auiLayoutState ) )
1373 restored = true;
1374 }
1375#endif
1376
1377 /*
1378 * Legacy loading of the string AUI perspective (if it exists). This is needed for
1379 * 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).
1380 */
1381 if( !restored && !m_perspective.IsEmpty() )
1382 m_auimgr.LoadPerspective( m_perspective );
1383
1384 // Workaround for two bugs:
1385 // 1) wx 3.2: LoadPerspective() hides all panes first, then shows only
1386 // those in the saved string. If toolbar names changed or new toolbars were added,
1387 // they'd stay hidden. Ensure all toolbars are visible after restore.
1388 // 2) We still saw this even after this fix, so just make the toolbars shown unconditionally
1389 // since we don't actually allow hiding them. The root cause of this part is not known.
1390 wxAuiPaneInfoArray& panes = m_auimgr.GetAllPanes();
1391
1392 for( size_t i = 0; i < panes.GetCount(); ++i )
1393 {
1394 if( panes.Item( i ).IsToolbar() )
1395 panes.Item( i ).Show( true );
1396 }
1397}
1398
1399
1400void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
1401 INFOBAR_MESSAGE_TYPE aType )
1402{
1403 m_infoBar->RemoveAllButtons();
1404
1405 if( aShowCloseButton )
1406 m_infoBar->AddCloseButton();
1407
1408 GetInfoBar()->ShowMessageFor( aErrorMsg, 8000, wxICON_ERROR, aType );
1409}
1410
1411
1412void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
1413 std::function<void(void)> aCallback )
1414{
1415 m_infoBar->RemoveAllButtons();
1416
1417 if( aShowCloseButton )
1418 m_infoBar->AddCloseButton();
1419
1420 if( aCallback )
1421 m_infoBar->SetCallback( aCallback );
1422
1423 GetInfoBar()->ShowMessageFor( aErrorMsg, 6000, wxICON_ERROR );
1424}
1425
1426
1427void EDA_BASE_FRAME::ShowInfoBarWarning( const wxString& aWarningMsg, bool aShowCloseButton )
1428{
1429 m_infoBar->RemoveAllButtons();
1430
1431 if( aShowCloseButton )
1432 m_infoBar->AddCloseButton();
1433
1434 GetInfoBar()->ShowMessageFor( aWarningMsg, 6000, wxICON_WARNING );
1435}
1436
1437
1438void EDA_BASE_FRAME::ShowInfoBarMsg( const wxString& aMsg, bool aShowCloseButton )
1439{
1440 m_infoBar->RemoveAllButtons();
1441
1442 if( aShowCloseButton )
1443 m_infoBar->AddCloseButton();
1444
1445 GetInfoBar()->ShowMessageFor( aMsg, 8000, wxICON_INFORMATION );
1446}
1447
1448
1449void EDA_BASE_FRAME::UpdateFileHistory( const wxString& FullFileName, FILE_HISTORY* aFileHistory )
1450{
1451 if( !aFileHistory )
1452 aFileHistory = m_fileHistory;
1453
1454 wxASSERT( aFileHistory );
1455
1456 aFileHistory->AddFileToHistory( FullFileName );
1457
1458 // Update the menubar to update the file history menu
1459 if( !m_isClosing && GetMenuBar() )
1460 {
1462 GetMenuBar()->Refresh();
1463 }
1464}
1465
1466
1467wxString EDA_BASE_FRAME::GetFileFromHistory( int cmdId, const wxString& type, FILE_HISTORY* aFileHistory )
1468{
1469 if( !aFileHistory )
1470 aFileHistory = m_fileHistory;
1471
1472 wxASSERT( aFileHistory );
1473
1474 int baseId = aFileHistory->GetBaseId();
1475
1476 wxASSERT( cmdId >= baseId && cmdId < baseId + (int) aFileHistory->GetCount() );
1477 int i = cmdId - baseId;
1478
1479 wxString fn = aFileHistory->GetHistoryFile( i );
1480
1481 if( !wxFileName::FileExists( fn ) )
1482 {
1483 KICAD_MESSAGE_DIALOG dlg( this, wxString::Format( _( "File '%s' was not found.\n" ), fn ), _( "Error" ),
1484 wxYES_NO | wxYES_DEFAULT | wxICON_ERROR | wxCENTER );
1485
1486 dlg.SetExtendedMessage( _( "Do you want to remove it from list of recently opened files?" ) );
1487 dlg.SetYesNoLabels( KICAD_MESSAGE_DIALOG::ButtonLabel( _( "Remove" ) ),
1488 KICAD_MESSAGE_DIALOG::ButtonLabel( _( "Keep" ) ) );
1489
1490 if( dlg.ShowModal() == wxID_YES )
1491 aFileHistory->RemoveFileFromHistory( i );
1492
1493 fn.Clear();
1494 }
1495
1496 // Update the menubar to update the file history menu
1497 if( GetMenuBar() )
1498 {
1500 GetMenuBar()->Refresh();
1501 }
1502
1503 return fn;
1504}
1505
1506
1508{
1509 wxASSERT( m_fileHistory );
1510
1511 m_fileHistory->ClearFileHistory();
1512
1513 // Update the menubar to update the file history menu
1514 if( GetMenuBar() )
1515 {
1517 GetMenuBar()->Refresh();
1518 }
1519}
1520
1521
1522void EDA_BASE_FRAME::OnKicadAbout( wxCommandEvent& event )
1523{
1524 void ShowAboutDialog( EDA_BASE_FRAME * aParent ); // See AboutDialog_main.cpp
1525 ShowAboutDialog( this );
1526}
1527
1528
1529void EDA_BASE_FRAME::OnPreferences( wxCommandEvent& event )
1530{
1531 ShowPreferences( wxEmptyString, wxEmptyString );
1532}
1533
1534
1535void EDA_BASE_FRAME::ShowPreferences( const wxString& aStartPage, const wxString& aStartParentPage )
1536{
1537 PAGED_DIALOG dlg( this, _( "Preferences" ), true, true, wxEmptyString,
1538 wxWindow::FromDIP( wxSize( 980, 560 ), nullptr ) );
1539
1540 dlg.SetEvtHandlerEnabled( false );
1541
1542 {
1543 WX_BUSY_INDICATOR busy_cursor;
1544
1545 WX_TREEBOOK* book = dlg.GetTreebook();
1546 PANEL_HOTKEYS_EDITOR* hotkeysPanel = new PANEL_HOTKEYS_EDITOR( this, book, false );
1547 std::vector<int> expand;
1548
1549 wxWindow* kicadMgr_window = wxWindow::FindWindowByName( KICAD_MANAGER_FRAME_NAME );
1550
1551 if( KICAD_MANAGER_FRAME* kicadMgr = static_cast<KICAD_MANAGER_FRAME*>( kicadMgr_window ) )
1552 {
1553 ACTION_MANAGER* actionMgr = kicadMgr->GetToolManager()->GetActionManager();
1554
1555 for( const auto& [name, action] : actionMgr->GetActions() )
1556 hotkeysPanel->ActionsList().push_back( action );
1557 }
1558
1559 book->AddLazyPage(
1560 []( wxWindow* aParent ) -> wxWindow*
1561 {
1562 return new PANEL_COMMON_SETTINGS( aParent );
1563 },
1564 _( "Common" ) );
1565
1566 book->AddLazyPage(
1567 []( wxWindow* aParent ) -> wxWindow*
1568 {
1569 return new PANEL_MOUSE_SETTINGS( aParent );
1570 }, _( "Mouse and Touchpad" ) );
1571
1572#if defined(__linux__) || defined(__FreeBSD__)
1573 book->AddLazyPage(
1574 [] ( wxWindow* aParent ) -> wxWindow*
1575 {
1576 return new PANEL_SPACEMOUSE( aParent );
1577 }, _( "SpaceMouse" ) );
1578#endif
1579
1580 book->AddPage( hotkeysPanel, _( "Hotkeys" ) );
1581
1582 book->AddLazyPage(
1583 []( wxWindow* aParent ) -> wxWindow*
1584 {
1585 return new PANEL_GIT_REPOS( aParent );
1586 }, _( "Version Control" ) );
1587
1588#ifdef KICAD_USE_SENTRY
1589 book->AddLazyPage(
1590 []( wxWindow* aParent ) -> wxWindow*
1591 {
1592 return new PANEL_DATA_COLLECTION( aParent );
1593 }, _( "Data Collection" ) );
1594#endif
1595
1596#define LAZY_CTOR( key ) \
1597 [this, kiface]( wxWindow* aParent ) \
1598 { \
1599 return kiface->CreateKiWindow( aParent, key, &Kiway() ); \
1600 }
1601
1602 // If a dll is not loaded, the loader will show an error message.
1603
1604 try
1605 {
1606 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_SCH ) )
1607 {
1608 kiface->GetActions( hotkeysPanel->ActionsList() );
1609
1611 expand.push_back( (int) book->GetPageCount() );
1612
1613 book->AddPage( new wxPanel( book ), _( "Symbol Editor" ) );
1614 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_DISP_OPTIONS ), _( "Display Options" ) );
1615 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_GRIDS ), _( "Grids" ) );
1616 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_SNAPPING ), _( "Snapping" ) );
1617 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_OPTIONS ), _( "Editing Options" ) );
1618 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_COLORS ), _( "Colors" ) );
1619 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_TOOLBARS ), _( "Toolbars" ) );
1620
1621 if( GetFrameType() == FRAME_SCH )
1622 expand.push_back( (int) book->GetPageCount() );
1623
1624 book->AddPage( new wxPanel( book ), _( "Schematic Editor" ) );
1625 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DISP_OPTIONS ), _( "Display Options" ) );
1626 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_GRIDS ), _( "Grids" ) );
1627 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_SNAPPING ), _( "Snapping" ) );
1628 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_EDIT_OPTIONS ), _( "Editing Options" ) );
1629 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_COLORS ), _( "Colors" ) );
1630 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_TOOLBARS ), _( "Toolbars" ) );
1631 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) );
1632 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DATA_SOURCES ), _( "Data Sources" ) );
1633 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_SIMULATOR ), _( "Simulator" ) );
1634 }
1635 }
1636 catch( ... )
1637 {
1638 }
1639
1640 try
1641 {
1642 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_PCB ) )
1643 {
1644 kiface->GetActions( hotkeysPanel->ActionsList() );
1645
1647 expand.push_back( (int) book->GetPageCount() );
1648
1649 book->AddPage( new wxPanel( book ), _( "Footprint Editor" ) );
1650 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DISPLAY_OPTIONS ), _( "Display Options" ) );
1651 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_GRIDS ), _( "Grids" ) );
1652 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_SNAPPING ), _( "Snapping" ) );
1653 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_ORIGINS_AXES ), _( "Origins & Axes" ) );
1654 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_EDIT_OPTIONS ), _( "Editing Options" ) );
1655 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_COLORS ), _( "Colors" ) );
1656 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_TOOLBARS ), _( "Toolbars" ) );
1657 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_FIELDS ), _( "Footprint Defaults" ) );
1658 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_GRAPHICS_VALUES ), _( "Graphics Defaults" ) );
1659 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_USER_LAYER_NAMES ), _( "User Layer Names" ) );
1660
1662 expand.push_back( (int) book->GetPageCount() );
1663
1664 book->AddPage( new wxPanel( book ), _( "PCB Editor" ) );
1665 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_DISPLAY_OPTS ), _( "Display Options" ) );
1666 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_GRIDS ), _( "Grids" ) );
1667 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_SNAPPING ), _( "Snapping" ) );
1668 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ORIGINS_AXES ), _( "Origins & Axes" ) );
1669 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_EDIT_OPTIONS ), _( "Editing Options" ) );
1670 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_COLORS ), _( "Colors" ) );
1671 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_TOOLBARS ), _( "Toolbars" ) );
1672 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ACTION_PLUGINS ), _( "Plugins" ) );
1673
1675 expand.push_back( (int) book->GetPageCount() );
1676
1677 book->AddPage( new wxPanel( book ), _( "3D Viewer" ) );
1678 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_DISPLAY_OPTIONS ), _( "General" ) );
1679 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_TOOLBARS ), _( "Toolbars" ) );
1680 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_OPENGL ), _( "Realtime Renderer" ) );
1681 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_RAYTRACING ), _( "Raytracing Renderer" ) );
1682 }
1683 }
1684 catch( ... )
1685 {
1686 }
1687
1688 try
1689 {
1690 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_GERBVIEW ) )
1691 {
1692 kiface->GetActions( hotkeysPanel->ActionsList() );
1693
1694 if( GetFrameType() == FRAME_GERBER )
1695 expand.push_back( (int) book->GetPageCount() );
1696
1697 book->AddPage( new wxPanel( book ), _( "Gerber Viewer" ) );
1698 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
1699 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_COLORS ), _( "Colors" ) );
1700 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_TOOLBARS ), _( "Toolbars" ) );
1701 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_GRIDS ), _( "Grids" ) );
1702 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_SNAPPING ), _( "Snapping" ) );
1703 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
1704 }
1705 }
1706 catch( ... )
1707 {
1708 }
1709
1710 try
1711 {
1712 if( KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_PL_EDITOR ) )
1713 {
1714 kiface->GetActions( hotkeysPanel->ActionsList() );
1715
1716 if( GetFrameType() == FRAME_PL_EDITOR )
1717 expand.push_back( (int) book->GetPageCount() );
1718
1719 book->AddPage( new wxPanel( book ), _( "Drawing Sheet Editor" ) );
1720 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
1721 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_GRIDS ), _( "Grids" ) );
1722 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_SNAPPING ), _( "Snapping" ) );
1723 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_COLORS ), _( "Colors" ) );
1724 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_TOOLBARS ), _( "Toolbars" ) );
1725
1726 book->AddLazyPage(
1727 []( wxWindow* aParent ) -> wxWindow*
1728 {
1729 return new PANEL_PACKAGES_AND_UPDATES( aParent );
1730 }, _( "Packages and Updates" ) );
1731 }
1732 }
1733 catch( ... )
1734 {
1735 }
1736
1737 book->AddPage( new PANEL_PLUGIN_SETTINGS( book ), _( "Plugins" ) );
1738
1739 book->AddPage( new PANEL_MAINTENANCE( book, this ), _( "Maintenance" ) );
1740
1741 // Update all of the action hotkeys. The process of loading the actions through
1742 // the KiFACE will only get us the default hotkeys
1743 ReadHotKeyConfigIntoActions( wxEmptyString, hotkeysPanel->ActionsList() );
1744
1745 for( size_t i = 0; i < book->GetPageCount(); ++i )
1746 book->GetPage( i )->Layout();
1747
1748 for( int page : expand )
1749 book->ExpandNode( page );
1750
1751 if( !aStartPage.IsEmpty() )
1752 dlg.SetInitialPage( aStartPage, aStartParentPage );
1753
1754 dlg.SetEvtHandlerEnabled( true );
1755#undef LAZY_CTOR
1756 }
1757
1758 if( dlg.ShowModal() == wxID_OK )
1759 {
1760 // Update our grids that are cached in the tool
1761 m_toolManager->ResetTools( TOOL_BASE::REDRAW );
1764 }
1765
1766}
1767
1768
1769void EDA_BASE_FRAME::OnDropFiles( wxDropFilesEvent& aEvent )
1770{
1771 Raise();
1772
1773 wxString* files = aEvent.GetFiles();
1774
1775 for( int nb = 0; nb < aEvent.GetNumberOfFiles(); nb++ )
1776 {
1777 const wxFileName fn = wxFileName( files[nb] );
1778 wxString ext = fn.GetExt();
1779
1780 // Alias all gerber files as GerberFileExtension
1783
1784 if( m_acceptedExts.find( ext.ToStdString() ) != m_acceptedExts.end() )
1785 m_AcceptedFiles.emplace_back( fn );
1786 }
1787
1789 m_AcceptedFiles.clear();
1790}
1791
1792
1794{
1795 for( const wxFileName& file : m_AcceptedFiles )
1796 {
1797 wxString fn = file.GetFullPath();
1798 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( file.GetExt() ), &fn );
1799 }
1800}
1801
1802
1803bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
1804{
1805 wxString msg;
1806 wxFileName fn = aFileName;
1807
1808 // Check for absence of a file path with a file name. Unfortunately KiCad
1809 // uses paths relative to the current project path without the ./ part which
1810 // confuses wxFileName. Making the file name path absolute may be less than
1811 // elegant but it solves the problem.
1812 if( fn.GetPath().IsEmpty() && fn.HasName() )
1813 fn.MakeAbsolute();
1814
1815 wxCHECK_MSG( fn.IsOk(), false, wxT( "File name object is invalid. Bad programmer!" ) );
1816 wxCHECK_MSG( !fn.GetPath().IsEmpty(), false,
1817 wxT( "File name object path <" ) + fn.GetFullPath() + wxT( "> is not set. Bad programmer!" ) );
1818
1819 if( fn.IsDir() && !fn.IsDirWritable() )
1820 {
1821 msg.Printf( _( "Insufficient permissions to folder '%s'." ), fn.GetPath() );
1822 }
1823 else if( !fn.FileExists() && !fn.IsDirWritable() )
1824 {
1825 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1826 }
1827 else if( fn.FileExists() && !fn.IsFileWritable() )
1828 {
1829 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1830 }
1831
1832 if( !msg.IsEmpty() )
1833 {
1834 if( aVerbose )
1835 DisplayErrorMessage( this, msg );
1836
1837 return false;
1838 }
1839
1840 return true;
1841}
1842
1843
1845{
1846 // This function should be overridden in child classes
1847 return false;
1848}
1849
1850
1852{
1853 wxAcceleratorEntry entries[1];
1854 entries[0].Set( wxACCEL_CTRL, int( 'Q' ), wxID_EXIT );
1855 wxAcceleratorTable accel( 1, entries );
1856 SetAcceleratorTable( accel );
1857}
1858
1859
1865
1866
1868{
1869 m_undoList.PushCommand( aNewitem );
1870
1871 // Delete the extra items, if count max reached
1872 if( m_undoRedoCountMax > 0 )
1873 {
1874 int extraitems = GetUndoCommandCount() - m_undoRedoCountMax;
1875
1876 if( extraitems > 0 )
1877 ClearUndoORRedoList( UNDO_LIST, extraitems );
1878 }
1879}
1880
1881
1883{
1884 m_redoList.PushCommand( aNewitem );
1885
1886 // Delete the extra items, if count max reached
1887 if( m_undoRedoCountMax > 0 )
1888 {
1889 int extraitems = GetRedoCommandCount() - m_undoRedoCountMax;
1890
1891 if( extraitems > 0 )
1892 ClearUndoORRedoList( REDO_LIST, extraitems );
1893 }
1894}
1895
1896
1901
1902
1907
1908
1910{
1911 if( GetUndoCommandCount() > 0 )
1912 return m_undoList.m_CommandsList.back()->GetDescription();
1913
1914 return wxEmptyString;
1915}
1916
1917
1919{
1920 if( GetRedoCommandCount() > 0 )
1921 return m_redoList.m_CommandsList.back()->GetDescription();
1922
1923 return wxEmptyString;
1924}
1925
1926
1928{
1929 m_autoSaveRequired = true;
1930}
1931
1932
1934{
1935 SetUserUnits( aUnits );
1937
1938 wxCommandEvent e( EDA_EVT_UNITS_CHANGED );
1939 e.SetInt( static_cast<int>( aUnits ) );
1940 e.SetClientData( this );
1941 ProcessEventLocally( e );
1942}
1943
1944
1945void EDA_BASE_FRAME::OnMaximize( wxMaximizeEvent& aEvent )
1946{
1947 // When we maximize the window, we want to save the old information
1948 // so that we can add it to the settings on next window load.
1949 // Contrary to the documentation, this event seems to be generated
1950 // when the window is also being unmaximized on OSX, so we only
1951 // capture the size information when we maximize the window when on OSX.
1952#ifdef __WXOSX__
1953 if( !IsMaximized() )
1954#endif
1955 {
1957 m_normalFramePos = GetPosition();
1958 wxLogTrace( traceDisplayLocation, "Maximizing window - Saving position (%d, %d) with size (%d, %d)",
1961 }
1962
1963 // Skip event to actually maximize the window
1964 aEvent.Skip();
1965}
1966
1967
1969{
1970#if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 2, 9 )
1971 wxSize winSize = GetSize();
1972
1973 // GTK includes the window decorations in the normal GetSize call,
1974 // so we have to use a GTK-specific sizing call that returns the
1975 // non-decorated window size.
1977 {
1978 int width = 0;
1979 int height = 0;
1980 GTKDoGetSize( &width, &height );
1981
1982 winSize.Set( width, height );
1983 }
1984#else
1985 wxSize winSize = GetSize();
1986#endif
1987
1988 return winSize;
1989}
1990
1991
1993{
1994 // Update the icon theme when the system theme changes and update the toolbars
1996 ThemeChanged();
1997
1998 // This isn't handled by ThemeChanged()
1999 if( GetMenuBar() )
2000 {
2001 // For icons in menus, icon scaling & hotkeys
2003 GetMenuBar()->Refresh();
2004 }
2005}
2006
2007
2008void EDA_BASE_FRAME::onSystemColorChange( wxSysColourChangedEvent& aEvent )
2009{
2010 // Call the handler to update the colors used in the frame
2012
2013 // Skip the change event to ensure the rest of the window controls get it
2014 aEvent.Skip();
2015}
2016
2017
2018void EDA_BASE_FRAME::onIconize( wxIconizeEvent& aEvent )
2019{
2020 // Call the handler
2021 handleIconizeEvent( aEvent );
2022
2023 // Skip the event.
2024 aEvent.Skip();
2025}
2026
2027
2028#ifdef __WXMSW__
2029WXLRESULT EDA_BASE_FRAME::MSWWindowProc( WXUINT message, WXWPARAM wParam, WXLPARAM lParam )
2030{
2031 // This will help avoid the menu keeping focus when the alt key is released
2032 // You can still trigger accelerators as long as you hold down alt
2033 if( message == WM_SYSCOMMAND )
2034 {
2035 if( wParam == SC_KEYMENU && ( lParam >> 16 ) <= 0 )
2036 return 0;
2037 }
2038
2039 return wxFrame::MSWWindowProc( message, wParam, lParam );
2040}
2041#endif
2042
2043
2045{
2046 ACTION_MENU* langsMenu = new ACTION_MENU( false, aControlTool );
2047 langsMenu->SetTitle( _( "Set Language" ) );
2048 langsMenu->SetIcon( BITMAPS::language );
2049
2050 wxString tooltip;
2051
2052 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
2053 {
2054 wxString label;
2055
2056 if( LanguagesList[ii].m_DoNotTranslate )
2057 label = LanguagesList[ii].m_Lang_Label;
2058 else
2059 label = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
2060
2061 wxMenuItem* item = new wxMenuItem( langsMenu, LanguagesList[ii].m_KI_Lang_Identifier, // wxMenuItem wxID
2062 label, tooltip, wxITEM_CHECK );
2063
2064 langsMenu->Append( item );
2065 }
2066
2067 // This must be done after the items are added
2068 aMasterMenu->Add( langsMenu );
2069}
2070
2071
2072void EDA_BASE_FRAME::OnLanguageSelectionEvent( wxCommandEvent& event )
2073{
2074 int id = event.GetId();
2075
2076 // tell all the KIWAY_PLAYERs about the language change.
2077 Kiway().SetLanguage( id );
2078}
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:285
static TOOL_ACTION reportBug
Definition actions.h:289
static TOOL_ACTION copy
Definition actions.h:74
static TOOL_ACTION donate
Definition actions.h:287
static TOOL_ACTION listHotKeys
Definition actions.h:286
static TOOL_ACTION getInvolved
Definition actions.h:288
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:283
static TOOL_ACTION help
Definition actions.h:284
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.
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.
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 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 SelectToolbarAction(const TOOL_ACTION &aAction)
Select the given action in the toolbar group which contains it, if any.
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()
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.
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:91
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:311
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition kiway.cpp:506
@ FACE_SCH
eeschema DSO
Definition kiway.h:318
@ FACE_PL_EDITOR
Definition kiway.h:322
@ FACE_PCB
pcbnew DSO
Definition kiway.h:319
@ FACE_GERBVIEW
Definition kiway.h:321
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:422
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:562
virtual int GetSelectedLanguageIdentifier() const
Definition pgm_base.h:230
KICAD_API_SERVER & GetApiServer()
Definition pgm_base.h:142
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:124
A holder to handle information on schematic or board items.
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: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)
@ 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
void SocketCleanup()
Must be called to clean up the socket thread used by SendCommand.
Definition eda_dde.cpp:234
DDE server & client.
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
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:226
PGM_BASE & Pgm()
The global program "get" accessor.
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition pgm_base.cpp:87
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:152
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)
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.