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