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