KiCad PCB EDA Suite
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) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <bitmaps.h>
27#include <bitmap_store.h>
28#include <dialog_shim.h>
32#include <eda_dde.h>
33#include <filehistory.h>
34#include <id.h>
35#include <kiface_base.h>
36#include <menus_helpers.h>
37#include <hotkeys_basic.h>
39#include <paths.h>
40#include <confirm.h>
41#include <panel_pcm_settings.h>
42#include <pgm_base.h>
47#include <tool/action_manager.h>
48#include <tool/action_menu.h>
49#include <tool/action_toolbar.h>
50#include <tool/actions.h>
51#include <tool/common_control.h>
52#include <tool/tool_manager.h>
54#include <trace_helpers.h>
56#include <widgets/infobar.h>
58#include <wx/app.h>
59#include <wx/config.h>
60#include <wx/display.h>
61#include <wx/stdpaths.h>
62#include <wx/string.h>
63#include <wx/treebook.h>
64#include <kiplatform/app.h>
65#include <kiplatform/ui.h>
66
67#include <functional>
68#include <kiface_ids.h>
69
70wxDEFINE_EVENT( UNITS_CHANGED, wxCommandEvent );
71
72
73// Minimum window size
74static const wxSize minSize( FRAME_T aFrameType )
75{
76 switch( aFrameType )
77 {
79 return wxSize( 406, 354 );
80
81 default:
82 return wxSize( 500, 400 );
83 }
84}
85
86
87static const wxSize defaultSize( FRAME_T aFrameType )
88{
89 switch( aFrameType )
90 {
92 return wxSize( 850, 540 );
93
94 default:
95 return wxSize( 1280, 720 );
96 }
97}
98
99
100BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
101 EVT_MENU( wxID_ABOUT, EDA_BASE_FRAME::OnKicadAbout )
102 EVT_MENU( wxID_PREFERENCES, EDA_BASE_FRAME::OnPreferences )
103
104 EVT_CHAR_HOOK( EDA_BASE_FRAME::OnCharHook )
105 EVT_MENU_OPEN( EDA_BASE_FRAME::OnMenuEvent )
106 EVT_MENU_CLOSE( EDA_BASE_FRAME::OnMenuEvent )
107 EVT_MENU_HIGHLIGHT_ALL( EDA_BASE_FRAME::OnMenuEvent )
108 EVT_MOVE( EDA_BASE_FRAME::OnMove )
109 EVT_SIZE( EDA_BASE_FRAME::OnSize )
110 EVT_MAXIMIZE( EDA_BASE_FRAME::OnMaximize )
111
112 EVT_SYS_COLOUR_CHANGED( EDA_BASE_FRAME::onSystemColorChange )
113 EVT_ICONIZE( EDA_BASE_FRAME::onIconize )
114END_EVENT_TABLE()
115
116
117void EDA_BASE_FRAME::commonInit( FRAME_T aFrameType )
118{
119 m_ident = aFrameType;
120 m_maximizeByDefault = false;
121 m_infoBar = nullptr;
122 m_settingsManager = nullptr;
123 m_fileHistory = nullptr;
124 m_supportsAutoSave = false;
125 m_autoSaveState = false;
126 m_undoRedoCountMax = DEFAULT_MAX_UNDO_ITEMS;
127 m_isClosing = false;
128 m_isNonUserClose = false;
129 m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
131 m_frameSize = defaultSize( aFrameType );
132 m_displayIndex = -1;
133
134 m_auimgr.SetArtProvider( new WX_AUI_DOCK_ART() );
135
136 m_settingsManager = &Pgm().GetSettingsManager();
137
138 // Set a reasonable minimal size for the frame
139 SetSizeHints( minSize( aFrameType ).x, minSize( aFrameType ).y, -1, -1, -1, -1 );
140
141 // Store dimensions of the user area of the main window.
142 GetClientSize( &m_frameSize.x, &m_frameSize.y );
143
144 Connect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER,
145 wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) );
146
147 // hook wxEVT_CLOSE_WINDOW so we can call SaveSettings(). This function seems
148 // to be called before any other hook for wxCloseEvent, which is necessary.
149 Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
150
151 initExitKey();
152}
153
154
155EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle,
156 const wxPoint& aPos, const wxSize& aSize, long aStyle,
157 const wxString& aFrameName, KIWAY* aKiway,
158 const EDA_IU_SCALE& aIuScale ) :
159 wxFrame( aParent, wxID_ANY, aTitle, aPos, aSize, aStyle, aFrameName ),
160 TOOLS_HOLDER(),
161 KIWAY_HOLDER( aKiway, KIWAY_HOLDER::FRAME ),
163{
164 commonInit( aFrameType );
165}
166
167
169{
170 for( wxWindow* iter : GetChildren() )
171 {
172 DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( iter );
173
174 if( dlg && dlg->IsQuasiModal() )
175 return dlg;
176 }
177
178 // FIXME: CvPcb is currently implemented on top of KIWAY_PLAYER rather than DIALOG_SHIM,
179 // so we have to look for it separately.
180 if( m_ident == FRAME_SCH )
181 {
182 wxWindow* cvpcb = wxWindow::FindWindowByName( "CvpcbFrame" );
183
184 if( cvpcb )
185 return cvpcb;
186 }
187
188 return nullptr;
189}
190
191
192void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event )
193{
194 // Don't allow closing when a quasi-modal is open.
195 wxWindow* quasiModal = findQuasiModalDialog();
196
197 if( quasiModal )
198 {
199 // Raise and notify; don't give the user a warning regarding "quasi-modal dialogs"
200 // when they have no idea what those are.
201 quasiModal->Raise();
202 wxBell();
203
204 if( event.CanVeto() )
205 event.Veto();
206
207 return;
208 }
209
210
211 if( event.GetId() == wxEVT_QUERY_END_SESSION
212 || event.GetId() == wxEVT_END_SESSION )
213 {
214 // End session means the OS is going to terminate us
215 m_isNonUserClose = true;
216 }
217
218 if( canCloseWindow( event ) )
219 {
220 m_isClosing = true;
221 APP_SETTINGS_BASE* cfg = config();
222
223 if( cfg )
224 SaveSettings( cfg ); // virtual, wxFrame specific
225
227
228 // Destroy (safe delete frame) this frame only in non modal mode.
229 // In modal mode, the caller will call Destroy().
230 if( !IsModal() )
231 Destroy();
232 }
233 else
234 {
235 if( event.CanVeto() )
236 event.Veto();
237 }
238}
239
240
242{
243 delete m_autoSaveTimer;
244 delete m_fileHistory;
245
247
249
251}
252
253
254bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent )
255{
256#ifdef __WXMAC__
257 // Apple in its infinite wisdom will raise a disabled window before even passing
258 // us the event, so we have no way to stop it. Instead, we have to catch an
259 // improperly ordered disabled window and quasi-modal dialog here and reorder
260 // them.
261 if( !IsEnabled() && IsActive() )
262 {
263 wxWindow* dlg = findQuasiModalDialog();
264 if( dlg )
265 dlg->Raise();
266 }
267#endif
268
269 if( !wxFrame::ProcessEvent( aEvent ) )
270 return false;
271
272 if( Pgm().m_Quitting )
273 return true;
274
275 if( !m_isClosing && m_supportsAutoSave && IsShown() && IsActive()
277 && GetAutoSaveInterval() > 0 )
278 {
279 if( !m_autoSaveState )
280 {
281 wxLogTrace( traceAutoSave, wxT( "Starting auto save timer." ) );
282 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
283 m_autoSaveState = true;
284 }
285 else if( m_autoSaveTimer->IsRunning() )
286 {
287 wxLogTrace( traceAutoSave, wxT( "Stopping auto save timer." ) );
288 m_autoSaveTimer->Stop();
289 m_autoSaveState = false;
290 }
291 }
292
293 return true;
294}
295
296
298{
299 return Pgm().GetCommonSettings()->m_System.autosave_interval;
300}
301
302
303void EDA_BASE_FRAME::onAutoSaveTimer( wxTimerEvent& aEvent )
304{
305 if( !doAutoSave() )
306 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
307}
308
309
311{
312 wxCHECK_MSG( false, true, wxT( "Auto save timer function not overridden. Bad programmer!" ) );
313}
314
315
316void EDA_BASE_FRAME::OnCharHook( wxKeyEvent& aKeyEvent )
317{
318 wxLogTrace( kicadTraceKeyEvent, "EDA_BASE_FRAME::OnCharHook %s", dump( aKeyEvent ) );
319
320 // Key events can be filtered here.
321 // Currently no filtering is made.
322 aKeyEvent.Skip();
323}
324
325
326void EDA_BASE_FRAME::OnMenuEvent( wxMenuEvent& aEvent )
327{
328 if( !m_toolDispatcher )
329 aEvent.Skip();
330 else
332}
333
334
336{
338 std::placeholders::_1,
339 this,
340 aConditions );
341
342 m_uiUpdateMap[aID] = evtFunc;
343
344 Bind( wxEVT_UPDATE_UI, evtFunc, aID );
345}
346
347
349{
350 const auto it = m_uiUpdateMap.find( aID );
351
352 if( it == m_uiUpdateMap.end() )
353 return;
354
355 Unbind( wxEVT_UPDATE_UI, it->second, aID );
356}
357
358
359void EDA_BASE_FRAME::HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAME* aFrame,
360 ACTION_CONDITIONS aCond )
361{
362 bool checkRes = false;
363 bool enableRes = true;
364 bool showRes = true;
365 bool isCut = aEvent.GetId() == ACTIONS::cut.GetUIId();
366 bool isCopy = aEvent.GetId() == ACTIONS::copy.GetUIId();
367 bool isPaste = aEvent.GetId() == ACTIONS::paste.GetUIId();
368 SELECTION& selection = aFrame->GetCurrentSelection();
369
370 try
371 {
372 checkRes = aCond.checkCondition( selection );
373 enableRes = aCond.enableCondition( selection );
374 showRes = aCond.showCondition( selection );
375 }
376 catch( std::exception& )
377 {
378 // Something broke with the conditions, just skip the event.
379 aEvent.Skip();
380 return;
381 }
382
383 if( isCut || isCopy || isPaste )
384 {
385 wxWindow* focus = wxWindow::FindFocus();
386 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
387
388 if( textEntry && isCut && textEntry->CanCut() )
389 enableRes = true;
390 else if( textEntry && isCopy && textEntry->CanCopy() )
391 enableRes = true;
392 else if( textEntry && isPaste && textEntry->CanPaste() )
393 enableRes = true;
394 }
395
396 aEvent.Enable( enableRes );
397 aEvent.Show( showRes );
398
399 // wxWidgets 3.1.5+ includes a field in the event that says if the event supports being
400 // checked, since wxMenuItems don't want to be checked unless they actually are checkable
401#if wxCHECK_VERSION( 3, 1, 5 )
402 if( aEvent.IsCheckable() )
403 aEvent.Check( checkRes );
404#else
405 bool canCheck = true;
406
407 // wxMenuItems don't want to be checked unless they actually are checkable, so we have to
408 // check to see if they can be and can't just universally apply a check in this event.
409 if( auto menu = dynamic_cast<wxMenu*>( aEvent.GetEventObject() ) )
410 canCheck = menu->FindItem( aEvent.GetId() )->IsCheckable();
411
412 if( canCheck )
413 aEvent.Check( checkRes );
414#endif
415}
416
417
419{
420 // Setup the conditions to check a language menu item
421 auto isCurrentLang =
422 [] ( const SELECTION& aSel, int aLangIdentifier )
423 {
424 return Pgm().GetSelectedLanguageIdentifier() == aLangIdentifier;
425 };
426
427 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
428 {
430 cond.Check( std::bind( isCurrentLang, std::placeholders::_1,
431 LanguagesList[ii].m_WX_Lang_Identifier ) );
432
433 RegisterUIUpdateHandler( LanguagesList[ii].m_KI_Lang_Identifier, cond );
434 }
435}
436
437
439{
440}
441
442
443void EDA_BASE_FRAME::AddStandardHelpMenu( wxMenuBar* aMenuBar )
444{
446 ACTION_MENU* helpMenu = new ACTION_MENU( false, commonControl );
447
448 helpMenu->Add( ACTIONS::help );
449 helpMenu->Add( ACTIONS::gettingStarted );
450 helpMenu->Add( ACTIONS::listHotKeys );
451 helpMenu->Add( ACTIONS::getInvolved );
452 helpMenu->Add( ACTIONS::donate );
453 helpMenu->Add( ACTIONS::reportBug );
454
455 helpMenu->AppendSeparator();
456 helpMenu->Add( _( "&About KiCad" ), "", wxID_ABOUT, BITMAPS::about );
457
458 // Trailing space keeps OSX from hijacking our menu (and disabling everything in it).
459 aMenuBar->Append( helpMenu, _( "&Help" ) + wxS( " " ) );
460}
461
462
464{
466
467 if( GetMenuBar() )
468 {
470 GetMenuBar()->Refresh();
471 }
472}
473
474
475void EDA_BASE_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
476{
477 TOOLS_HOLDER::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
478
479 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
480
481 if( m_fileHistory )
482 {
483 int historySize = settings->m_System.file_history_size;
484 m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) );
485 }
486
488 ThemeChanged();
489
490 if( GetMenuBar() )
491 {
492 // For icons in menus, icon scaling & hotkeys
494 GetMenuBar()->Refresh();
495 }
496}
497
498
500{
502
503 // Update all the toolbars to have new icons
504 wxAuiPaneInfoArray panes = m_auimgr.GetAllPanes();
505
506 for( size_t i = 0; i < panes.GetCount(); ++i )
507 {
508 if( ACTION_TOOLBAR* toolbar = dynamic_cast<ACTION_TOOLBAR*>( panes[i].window ) )
509 toolbar->RefreshBitmaps();
510 }
511}
512
513
514void EDA_BASE_FRAME::OnSize( wxSizeEvent& aEvent )
515{
516#ifdef __WXMAC__
517 int currentDisplay = wxDisplay::GetFromWindow( this );
518
519 if( m_displayIndex >= 0 && currentDisplay >= 0 && currentDisplay != m_displayIndex )
520 {
521 wxLogTrace( traceDisplayLocation, "OnSize: current display changed %d to %d",
522 m_displayIndex, currentDisplay );
523 m_displayIndex = currentDisplay;
525 }
526#endif
527
528 aEvent.Skip();
529}
530
531
532void EDA_BASE_FRAME::LoadWindowState( const wxString& aFileName )
533{
534 if( !Pgm().GetCommonSettings()->m_Session.remember_open_files )
535 return;
536
537 const PROJECT_FILE_STATE* state = Prj().GetLocalSettings().GetFileState( aFileName );
538
539 if( state != nullptr )
540 {
541 LoadWindowState( state->window );
542 }
543}
544
545
547{
548 bool wasDefault = false;
549
550 m_framePos.x = aState.pos_x;
551 m_framePos.y = aState.pos_y;
552 m_frameSize.x = aState.size_x;
553 m_frameSize.y = aState.size_y;
554
555 wxLogTrace( traceDisplayLocation, "Config position (%d, %d) with size (%d, %d)",
557
558 // Ensure minimum size is set if the stored config was zero-initialized
559 if( m_frameSize.x < minSize( m_ident ).x || m_frameSize.y < minSize( m_ident ).y )
560 {
562 wasDefault = true;
563
564 wxLogTrace( traceDisplayLocation, "Using minimum size (%d, %d)",
566 }
567
568 wxLogTrace( traceDisplayLocation, "Number of displays: %d", wxDisplay::GetCount() );
569
570 if( aState.display >= wxDisplay::GetCount() )
571 {
572 wxLogTrace( traceDisplayLocation, "Previous display not found" );
573
574 // If it isn't attached, use the first display
575 // Warning wxDisplay has 2 ctor variants. the parameter needs a type:
576 const unsigned int index = 0;
577 wxDisplay display( index );
578 wxRect clientSize = display.GetGeometry();
579
580 m_framePos = wxDefaultPosition;
581
582 // Ensure the window fits on the display, since the other one could have been larger
583 if( m_frameSize.x > clientSize.width )
584 m_frameSize.x = clientSize.width;
585
586 if( m_frameSize.y > clientSize.height )
587 m_frameSize.y = clientSize.height;
588 }
589 else
590 {
591 wxPoint upperRight( m_framePos.x + m_frameSize.x, m_framePos.y );
592 wxPoint upperLeft( m_framePos.x, m_framePos.y );
593
594 wxDisplay display( aState.display );
595 wxRect clientSize = display.GetClientArea();
596
597 int yLimTop = clientSize.y;
598 int yLimBottom = clientSize.y + clientSize.height;
599 int xLimLeft = clientSize.x;
600 int xLimRight = clientSize.x + clientSize.width;
601
602 if( upperLeft.x > xLimRight || // Upper left corner too close to right edge of screen
603 upperRight.x < xLimLeft || // Upper right corner too close to left edge of screen
604 upperLeft.y < yLimTop || // Upper corner too close to the bottom of the screen
605 upperLeft.y > yLimBottom )
606 {
607 m_framePos = wxDefaultPosition;
608 wxLogTrace( traceDisplayLocation, "Resetting to default position" );
609 }
610 }
611
612 wxLogTrace( traceDisplayLocation, "Final window position (%d, %d) with size (%d, %d)",
614
615 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
616
617 // Center the window if we reset to default
618 if( m_framePos.x == -1 )
619 {
620 wxLogTrace( traceDisplayLocation, "Centering window" );
621 Center();
622 m_framePos = GetPosition();
623 }
624
625 // Record the frame sizes in an un-maximized state
628
629 // Maximize if we were maximized before
630 if( aState.maximized || ( wasDefault && m_maximizeByDefault ) )
631 {
632 wxLogTrace( traceDisplayLocation, "Maximizing window" );
633 Maximize();
634 }
635
636 m_displayIndex = wxDisplay::GetFromWindow( this );
637}
638
639
641{
642 wxDisplay display( wxDisplay::GetFromWindow( this ) );
643 wxRect clientSize = display.GetClientArea();
644 wxPoint pos = GetPosition();
645 wxSize size = GetWindowSize();
646
647 wxLogTrace( traceDisplayLocation,
648 "ensureWindowIsOnScreen: clientArea (%d, %d) w %d h %d", clientSize.x, clientSize.y,
649 clientSize.width, clientSize.height );
650
651 if( pos.y < clientSize.y )
652 {
653 wxLogTrace( traceDisplayLocation,
654 "ensureWindowIsOnScreen: y pos %d below minimum, setting to %d", pos.y,
655 clientSize.y );
656 pos.y = clientSize.y;
657 }
658
659 if( pos.x < clientSize.x )
660 {
661 wxLogTrace( traceDisplayLocation,
662 "ensureWindowIsOnScreen: x pos %d is off the client rect, setting to %d", pos.x,
663 clientSize.x );
664 pos.x = clientSize.x;
665 }
666
667 if( pos.x + size.x - clientSize.x > clientSize.width )
668 {
669 int newWidth = clientSize.width - ( pos.x - clientSize.x );
670 wxLogTrace( traceDisplayLocation,
671 "ensureWindowIsOnScreen: effective width %d above available %d, setting to %d",
672 pos.x + size.x, clientSize.width, newWidth );
673 size.x = newWidth;
674 }
675
676 if( pos.y + size.y - clientSize.y > clientSize.height )
677 {
678 int newHeight = clientSize.height - ( pos.y - clientSize.y );
679 wxLogTrace( traceDisplayLocation,
680 "ensureWindowIsOnScreen: effective height %d above available %d, setting to %d",
681 pos.y + size.y, clientSize.height, newHeight );
682 size.y = newHeight;
683 }
684
685 wxLogTrace( traceDisplayLocation, "Updating window position (%d, %d) with size (%d, %d)",
686 pos.x, pos.y, size.x, size.y );
687
688 SetSize( pos.x, pos.y, size.x, size.y );
689}
690
691
693{
694 LoadWindowState( aCfg->state );
695
697 m_mruPath = aCfg->mru_path;
698
700}
701
702
704{
705 if( IsIconized() )
706 return;
707
708 // If the window is maximized, we use the saved window size from before it was maximized
709 if( IsMaximized() )
710 {
713 }
714 else
715 {
717 m_framePos = GetPosition();
718 }
719
720 aCfg->state.pos_x = m_framePos.x;
721 aCfg->state.pos_y = m_framePos.y;
722 aCfg->state.size_x = m_frameSize.x;
723 aCfg->state.size_y = m_frameSize.y;
724 aCfg->state.maximized = IsMaximized();
725 aCfg->state.display = wxDisplay::GetFromWindow( this );
726
727 wxLogTrace( traceDisplayLocation, "Saving window maximized: %s",
728 IsMaximized() ? "true" : "false" );
729 wxLogTrace( traceDisplayLocation, "Saving config position (%d, %d) with size (%d, %d)",
731
732 // Once this is fully implemented, wxAuiManager will be used to maintain
733 // the persistence of the main frame and all it's managed windows and
734 // all of the legacy frame persistence position code can be removed.
735 aCfg->perspective = m_auimgr.SavePerspective().ToStdString();
736
737 aCfg->mru_path = m_mruPath;
738}
739
740
742{
744
745 // Get file history size from common settings
746 int fileHistorySize = Pgm().GetCommonSettings()->m_System.file_history_size;
747
748 // Load the recently used files into the history menu
749 m_fileHistory = new FILE_HISTORY( (unsigned) std::max( 0, fileHistorySize ),
751 m_fileHistory->Load( *aCfg );
752}
753
754
756{
758
759 bool fileOpen = m_isClosing && m_isNonUserClose;
760
761 wxString currentlyOpenedFile = GetCurrentFileName();
762
763 if( Pgm().GetCommonSettings()->m_Session.remember_open_files && !currentlyOpenedFile.IsEmpty() )
764 {
765 wxFileName rfn( currentlyOpenedFile );
766 rfn.MakeRelativeTo( Prj().GetProjectPath() );
767 Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &aCfg->m_Window, fileOpen );
768 }
769
770 // Save the recently used files list
771 if( m_fileHistory )
772 {
773 // Save the currently opened file in the file history
774 if( !currentlyOpenedFile.IsEmpty() )
775 UpdateFileHistory( currentlyOpenedFile );
776
777 m_fileHistory->Save( *aCfg );
778 }
779}
780
781
783{
784 return &aCfg->m_Window;
785}
786
787
789{
790 // KICAD_MANAGER_FRAME overrides this
791 return Kiface().KifaceSettings();
792}
793
794
796{
797 return Kiface().KifaceSearch();
798}
799
800
802{
803 return Kiface().GetHelpFileName();
804}
805
806
807void EDA_BASE_FRAME::PrintMsg( const wxString& text )
808{
809 SetStatusText( text );
810}
811
812
814{
815#if defined( __WXOSX_MAC__ )
817#else
818 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
819
820 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( "InfoBar" ).Top().Layer(1) );
821#endif
822}
823
824
826{
827#if defined( __WXOSX_MAC__ )
828 m_auimgr.Update();
829#else
830 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
831 // hiding it.
832 m_auimgr.Update();
833
834 // We don't want the infobar displayed right away
835 m_auimgr.GetPane( "InfoBar" ).Hide();
836 m_auimgr.Update();
837#endif
838}
839
840
841void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
843{
845
846 if( aShowCloseButton )
848
849 GetInfoBar()->ShowMessageFor( aErrorMsg, 8000, wxICON_ERROR, aType );
850}
851
852
853void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
854 std::function<void(void)> aCallback )
855{
857
858 if( aShowCloseButton )
860
861 if( aCallback )
862 m_infoBar->SetCallback( aCallback );
863
864 GetInfoBar()->ShowMessageFor( aErrorMsg, 6000, wxICON_ERROR );
865}
866
867
868void EDA_BASE_FRAME::ShowInfoBarWarning( const wxString& aWarningMsg, bool aShowCloseButton )
869{
871
872 if( aShowCloseButton )
874
875 GetInfoBar()->ShowMessageFor( aWarningMsg, 6000, wxICON_WARNING );
876}
877
878
879void EDA_BASE_FRAME::ShowInfoBarMsg( const wxString& aMsg, bool aShowCloseButton )
880{
882
883 if( aShowCloseButton )
885
886 GetInfoBar()->ShowMessageFor( aMsg, 8000, wxICON_INFORMATION );
887}
888
889
890void EDA_BASE_FRAME::UpdateFileHistory( const wxString& FullFileName, FILE_HISTORY* aFileHistory )
891{
892 if( !aFileHistory )
893 aFileHistory = m_fileHistory;
894
895 wxASSERT( aFileHistory );
896
897 aFileHistory->AddFileToHistory( FullFileName );
898
899 // Update the menubar to update the file history menu
900 if( !m_isClosing && GetMenuBar() )
901 {
903 GetMenuBar()->Refresh();
904 }
905}
906
907
908wxString EDA_BASE_FRAME::GetFileFromHistory( int cmdId, const wxString& type,
909 FILE_HISTORY* aFileHistory )
910{
911 if( !aFileHistory )
912 aFileHistory = m_fileHistory;
913
914 wxASSERT( aFileHistory );
915
916 int baseId = aFileHistory->GetBaseId();
917
918 wxASSERT( cmdId >= baseId && cmdId < baseId + (int) aFileHistory->GetCount() );
919
920 unsigned i = cmdId - baseId;
921
922 if( i < aFileHistory->GetCount() )
923 {
924 wxString fn = aFileHistory->GetHistoryFile( i );
925
926 if( wxFileName::FileExists( fn ) )
927 {
928 return fn;
929 }
930 else
931 {
932 DisplayErrorMessage( this, wxString::Format( _( "File '%s' was not found." ), fn ) );
933 aFileHistory->RemoveFileFromHistory( i );
934 }
935 }
936
937 // Update the menubar to update the file history menu
938 if( GetMenuBar() )
939 {
941 GetMenuBar()->Refresh();
942 }
943
944 return wxEmptyString;
945}
946
947
949{
950 if( !aFileHistory )
951 aFileHistory = m_fileHistory;
952
953 wxASSERT( aFileHistory );
954
955 aFileHistory->ClearFileHistory();
956
957 // Update the menubar to update the file history menu
958 if( GetMenuBar() )
959 {
961 GetMenuBar()->Refresh();
962 }
963}
964
965
966void EDA_BASE_FRAME::OnKicadAbout( wxCommandEvent& event )
967{
968 void ShowAboutDialog( EDA_BASE_FRAME * aParent ); // See AboutDialog_main.cpp
969 ShowAboutDialog( this );
970}
971
972
973void EDA_BASE_FRAME::OnPreferences( wxCommandEvent& event )
974{
975 PAGED_DIALOG dlg( this, _( "Preferences" ), true );
976 wxTreebook* book = dlg.GetTreebook();
977
978 PANEL_HOTKEYS_EDITOR* hotkeysPanel = new PANEL_HOTKEYS_EDITOR( this, book, false );
979 KIFACE* kiface = nullptr;
980 std::vector<int> expand;
981
982 Kiway().GetActions( hotkeysPanel->ActionsList() );
983
984 book->AddPage( new PANEL_COMMON_SETTINGS( &dlg, book ), _( "Common" ) );
985 book->AddPage( new PANEL_MOUSE_SETTINGS( &dlg, book ), _( "Mouse and Touchpad" ) );
986 book->AddPage( hotkeysPanel, _( "Hotkeys" ) );
987
988#ifdef KICAD_USE_SENTRY
989 book->AddPage( new PANEL_DATA_COLLECTION( &dlg, book ), _( "Data Collection" ) );
990#endif
991
992#define CREATE_PANEL( key ) kiface->CreateWindow( book, key, &Kiway() )
993
994 // If a dll is not loaded, the loader will show an error message.
995
996 try
997 {
999
1000 kiface->GetActions( hotkeysPanel->ActionsList() );
1001
1003 expand.push_back( book->GetPageCount() );
1004
1005 book->AddPage( new wxPanel( book ), _( "Symbol Editor" ) );
1006 book->AddSubPage( CREATE_PANEL( PANEL_SYM_DISP_OPTIONS ), _( "Display Options" ) );
1007 book->AddSubPage( CREATE_PANEL( PANEL_SYM_EDIT_OPTIONS ), _( "Editing Options" ) );
1008 book->AddSubPage( CREATE_PANEL( PANEL_SYM_COLORS ), _( "Colors" ) );
1009
1010 if( GetFrameType() == FRAME_SCH )
1011 expand.push_back( book->GetPageCount() );
1012
1013 book->AddPage( new wxPanel( book ), _( "Schematic Editor" ) );
1014 book->AddSubPage( CREATE_PANEL( PANEL_SCH_DISP_OPTIONS ), _( "Display Options" ) );
1015 book->AddSubPage( CREATE_PANEL( PANEL_SCH_EDIT_OPTIONS ), _( "Editing Options" ) );
1016 book->AddSubPage( CREATE_PANEL( PANEL_SCH_ANNO_OPTIONS ), _( "Annotation Options" ) );
1017 book->AddSubPage( CREATE_PANEL( PANEL_SCH_COLORS ), _( "Colors" ) );
1018 book->AddSubPage( CREATE_PANEL( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) );
1019 }
1020 catch( ... )
1021 {
1022 }
1023
1024 try
1025 {
1027
1028 kiface->GetActions( hotkeysPanel->ActionsList() );
1029
1031 expand.push_back( book->GetPageCount() );
1032
1033 book->AddPage( new wxPanel( book ), _( "Footprint Editor" ) );
1034 book->AddSubPage( CREATE_PANEL( PANEL_FP_DISPLAY_OPTIONS ), _( "Display Options" ) );
1035 book->AddSubPage( CREATE_PANEL( PANEL_FP_EDIT_OPTIONS ), _( "Editing Options" ) );
1036 book->AddSubPage( CREATE_PANEL( PANEL_FP_COLORS ), _( "Colors" ) );
1037 book->AddSubPage( CREATE_PANEL( PANEL_FP_DEFAULT_VALUES ), _( "Default Values" ) );
1038
1040 expand.push_back( book->GetPageCount() );
1041
1042 book->AddPage( new wxPanel( book ), _( "PCB Editor" ) );
1043 book->AddSubPage( CREATE_PANEL( PANEL_PCB_DISPLAY_OPTIONS ), _( "Display Options" ) );
1044 book->AddSubPage( CREATE_PANEL( PANEL_PCB_EDIT_OPTIONS ), _( "Editing Options" ) );
1045 book->AddSubPage( CREATE_PANEL( PANEL_PCB_COLORS ), _( "Colors" ) );
1046 book->AddSubPage( CREATE_PANEL( PANEL_PCB_ACTION_PLUGINS ), _( "Action Plugins" ) );
1047 book->AddSubPage( CREATE_PANEL( PANEL_PCB_ORIGINS_AXES ), _( "Origins & Axes" ) );
1048
1050 expand.push_back( book->GetPageCount() );
1051
1052 book->AddPage( new wxPanel( book ), _( "3D Viewer" ) );
1053 book->AddSubPage( CREATE_PANEL( PANEL_3DV_DISPLAY_OPTIONS ), _( "General" ) );
1054 book->AddSubPage( CREATE_PANEL( PANEL_3DV_OPENGL ), _( "Realtime Renderer" ) );
1055 book->AddSubPage( CREATE_PANEL( PANEL_3DV_RAYTRACING ), _( "Raytracing Renderer" ) );
1056 book->AddSubPage( CREATE_PANEL( PANEL_3DV_COLORS ), _( "Colors" ) );
1057 }
1058 catch( ... )
1059 {
1060 }
1061
1062 try
1063 {
1065
1066 kiface->GetActions( hotkeysPanel->ActionsList() );
1067
1068 if( GetFrameType() == FRAME_GERBER )
1069 expand.push_back( book->GetPageCount() );
1070
1071 book->AddPage( new wxPanel( book ), _( "Gerber Viewer" ) );
1072 book->AddSubPage( CREATE_PANEL( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
1073 book->AddSubPage( CREATE_PANEL( PANEL_GBR_COLORS ), _( "Colors" ) );
1074 book->AddSubPage( CREATE_PANEL( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
1075 }
1076 catch( ... )
1077 {
1078 }
1079
1080 try
1081 {
1083 kiface->GetActions( hotkeysPanel->ActionsList() );
1084
1085 if( GetFrameType() == FRAME_PL_EDITOR )
1086 expand.push_back( book->GetPageCount() );
1087
1088 book->AddPage( new wxPanel( book ), _( "Drawing Sheet Editor" ) );
1089 book->AddSubPage( CREATE_PANEL( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
1090 book->AddSubPage( CREATE_PANEL( PANEL_DS_COLORS ), _( "Colors" ) );
1091
1092 book->AddPage( new PANEL_PCM_SETTINGS( book ), _( "Plugin and Content Manager" ) );
1093 }
1094 catch( ... )
1095 {
1096 }
1097
1098 // Update all of the action hotkeys. The process of loading the actions through
1099 // the KiFACE will only get us the default hotkeys
1100 ReadHotKeyConfigIntoActions( wxEmptyString, hotkeysPanel->ActionsList() );
1101
1102 for( size_t i = 0; i < book->GetPageCount(); ++i )
1103 book->GetPage( i )->Layout();
1104
1105 for( int page : expand )
1106 book->ExpandNode( page );
1107
1108 if( dlg.ShowModal() == wxID_OK )
1109 {
1110 Pgm().GetSettingsManager().Save();
1111 dlg.Kiway().CommonSettingsChanged( false, false );
1112 }
1113
1114#undef CREATE_PANEL
1115}
1116
1117
1118void EDA_BASE_FRAME::OnDropFiles( wxDropFilesEvent& aEvent )
1119{
1120 wxString* files = aEvent.GetFiles();
1121 for( int nb = 0; nb < aEvent.GetNumberOfFiles(); nb++ )
1122 {
1123 const wxFileName fn = wxFileName( files[nb] );
1124 for( const auto& [ext, tool] : m_acceptedExts )
1125 {
1126 if( IsExtensionAccepted( fn.GetExt(), { ext.ToStdString() } ) )
1127 {
1128 m_AcceptedFiles.emplace( m_AcceptedFiles.end(), fn );
1129 break;
1130 }
1131 }
1132 }
1134 m_AcceptedFiles.clear();
1135}
1136
1137
1139{
1140 for( const wxFileName& file : m_AcceptedFiles )
1141 {
1142 wxString fn = file.GetFullPath();
1143 m_toolManager->RunAction( *m_acceptedExts.at( file.GetExt() ), true, &fn );
1144 }
1145}
1146
1147
1148bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
1149{
1150 wxString msg;
1151 wxFileName fn = aFileName;
1152
1153 // Check for absence of a file path with a file name. Unfortunately KiCad
1154 // uses paths relative to the current project path without the ./ part which
1155 // confuses wxFileName. Making the file name path absolute may be less than
1156 // elegant but it solves the problem.
1157 if( fn.GetPath().IsEmpty() && fn.HasName() )
1158 fn.MakeAbsolute();
1159
1160 wxCHECK_MSG( fn.IsOk(), false,
1161 wxT( "File name object is invalid. Bad programmer!" ) );
1162 wxCHECK_MSG( !fn.GetPath().IsEmpty(), false,
1163 wxT( "File name object path <" ) + fn.GetFullPath() +
1164 wxT( "> is not set. Bad programmer!" ) );
1165
1166 if( fn.IsDir() && !fn.IsDirWritable() )
1167 {
1168 msg.Printf( _( "Insufficient permissions to folder '%s'." ), fn.GetPath() );
1169 }
1170 else if( !fn.FileExists() && !fn.IsDirWritable() )
1171 {
1172 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1173 }
1174 else if( fn.FileExists() && !fn.IsFileWritable() )
1175 {
1176 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1177 }
1178
1179 if( !msg.IsEmpty() )
1180 {
1181 if( aVerbose )
1182 wxMessageBox( msg );
1183
1184 return false;
1185 }
1186
1187 return true;
1188}
1189
1190
1191void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
1192{
1193 wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) );
1194
1195 wxFileName autoSaveFileName = aFileName;
1196
1197 // Check for auto save file.
1198 autoSaveFileName.SetName( GetAutoSaveFilePrefix() + aFileName.GetName() );
1199
1200 wxLogTrace( traceAutoSave,
1201 wxT( "Checking for auto save file " ) + autoSaveFileName.GetFullPath() );
1202
1203 if( !autoSaveFileName.FileExists() )
1204 return;
1205
1206 wxString msg = wxString::Format( _(
1207 "Well this is potentially embarrassing!\n"
1208 "It appears that the last time you were editing the file\n"
1209 "%s\n"
1210 "it was not saved properly. Do you wish to restore the last saved edits you made?" ),
1211 aFileName.GetFullName()
1212 );
1213
1214 int response = wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxYES_NO | wxICON_QUESTION,
1215 this );
1216
1217 // Make a backup of the current file, delete the file, and rename the auto save file to
1218 // the file name.
1219 if( response == wxYES )
1220 {
1221 if( !wxRenameFile( autoSaveFileName.GetFullPath(), aFileName.GetFullPath() ) )
1222 {
1223 wxMessageBox( _( "The auto save file could not be renamed to the board file name." ),
1224 Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1225 }
1226 }
1227 else
1228 {
1229 wxLogTrace( traceAutoSave,
1230 wxT( "Removing auto save file " ) + autoSaveFileName.GetFullPath() );
1231
1232 // Remove the auto save file when using the previous file as is.
1233 wxRemoveFile( autoSaveFileName.GetFullPath() );
1234 }
1235}
1236
1237
1239{
1240 // This function should be overridden in child classes
1241 return false;
1242}
1243
1244
1246{
1247 wxAcceleratorEntry entries[1];
1248 entries[0].Set( wxACCEL_CTRL, int( 'Q' ), wxID_EXIT );
1249 wxAcceleratorTable accel( 1, entries );
1250 SetAcceleratorTable( accel );
1251}
1252
1253
1255{
1258}
1259
1260
1262{
1263 m_undoList.PushCommand( aNewitem );
1264
1265 // Delete the extra items, if count max reached
1266 if( m_undoRedoCountMax > 0 )
1267 {
1268 int extraitems = GetUndoCommandCount() - m_undoRedoCountMax;
1269
1270 if( extraitems > 0 )
1271 ClearUndoORRedoList( UNDO_LIST, extraitems );
1272 }
1273}
1274
1275
1277{
1278 m_redoList.PushCommand( aNewitem );
1279
1280 // Delete the extra items, if count max reached
1281 if( m_undoRedoCountMax > 0 )
1282 {
1283 int extraitems = GetRedoCommandCount() - m_undoRedoCountMax;
1284
1285 if( extraitems > 0 )
1286 ClearUndoORRedoList( REDO_LIST, extraitems );
1287 }
1288}
1289
1290
1292{
1293 return m_undoList.PopCommand();
1294}
1295
1296
1298{
1299 return m_redoList.PopCommand();
1300}
1301
1302
1304{
1305 SetUserUnits( aUnits );
1307
1308 wxCommandEvent e( UNITS_CHANGED );
1309 ProcessEventLocally( e );
1310}
1311
1312
1313void EDA_BASE_FRAME::OnMaximize( wxMaximizeEvent& aEvent )
1314{
1315 // When we maximize the window, we want to save the old information
1316 // so that we can add it to the settings on next window load.
1317 // Contrary to the documentation, this event seems to be generated
1318 // when the window is also being unmaximized on OSX, so we only
1319 // capture the size information when we maximize the window when on OSX.
1320#ifdef __WXOSX__
1321 if( !IsMaximized() )
1322#endif
1323 {
1325 m_normalFramePos = GetPosition();
1326 wxLogTrace( traceDisplayLocation,
1327 "Maximizing window - Saving position (%d, %d) with size (%d, %d)",
1330 }
1331
1332 // Skip event to actually maximize the window
1333 aEvent.Skip();
1334}
1335
1336
1338{
1339#ifdef __WXGTK__
1340 wxSize winSize = GetSize();
1341
1342 // GTK includes the window decorations in the normal GetSize call,
1343 // so we have to use a GTK-specific sizing call that returns the
1344 // non-decorated window size.
1346 {
1347 int width = 0;
1348 int height = 0;
1349 GTKDoGetSize( &width, &height );
1350
1351 winSize.Set( width, height );
1352 }
1353#else
1354 wxSize winSize = GetSize();
1355#endif
1356
1357 return winSize;
1358}
1359
1360
1362{
1363 // Update the icon theme when the system theme changes and update the toolbars
1365 ThemeChanged();
1366
1367 // This isn't handled by ThemeChanged()
1368 if( GetMenuBar() )
1369 {
1370 // For icons in menus, icon scaling & hotkeys
1372 GetMenuBar()->Refresh();
1373 }
1374}
1375
1376
1377void EDA_BASE_FRAME::onSystemColorChange( wxSysColourChangedEvent& aEvent )
1378{
1379 // Call the handler to update the colors used in the frame
1381
1382 // Skip the change event to ensure the rest of the window controls get it
1383 aEvent.Skip();
1384}
1385
1386
1387void EDA_BASE_FRAME::onIconize( wxIconizeEvent& aEvent )
1388{
1389 // Call the handler
1390 handleIconizeEvent( aEvent );
1391
1392 // Skip the event.
1393 aEvent.Skip();
1394}
1395
1396
1397#ifdef _WIN32
1398WXLRESULT EDA_BASE_FRAME::MSWWindowProc( WXUINT message, WXWPARAM wParam, WXLPARAM lParam )
1399{
1400 // This will help avoid the menu keeping focus when the alt key is released
1401 // You can still trigger accelerators as long as you hold down alt
1402 if( message == WM_SYSCOMMAND )
1403 if( wParam == SC_KEYMENU && ( lParam >> 16 ) <= 0 )
1404 return 0;
1405
1406 return wxFrame::MSWWindowProc( message, wParam, lParam );
1407}
1408#endif
void ShowAboutDialog(EDA_BASE_FRAME *aParent)
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:173
BITMAP_STORE * GetBitmapStore()
Definition: bitmap.cpp:93
static TOOL_ACTION paste
Definition: actions.h:69
static TOOL_ACTION reportBug
Cursor control event types.
Definition: actions.h:186
static TOOL_ACTION copy
Definition: actions.h:68
static TOOL_ACTION donate
Definition: actions.h:184
static TOOL_ACTION listHotKeys
Definition: actions.h:183
static TOOL_ACTION getInvolved
Definition: actions.h:185
static TOOL_ACTION cut
Definition: actions.h:67
static TOOL_ACTION gettingStarted
Definition: actions.h:181
static TOOL_ACTION help
Definition: actions.h:182
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
Define the structure of a toolbar with buttons that invoke ACTIONs.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:101
WINDOW_SETTINGS m_Window
Definition: app_settings.h:184
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:83
bool IsQuasiModal() const
Definition: dialog_shim.h:106
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
Returns 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
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 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()
void LoadWindowSettings(const WINDOW_SETTINGS *aCfg)
Load window settings from the given settings object.
std::vector< wxFileName > m_AcceptedFiles
virtual void CheckForAutoSaveFile(const wxFileName &aFileName)
Check if an auto save file exists for aFileName and takes the appropriate action depending on the use...
void OnKicadAbout(wxCommandEvent &event)
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
virtual void DoWithAcceptedFiles()
Execute action on accepted dropped file.
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.
wxSize m_normalFrameSize
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)
void initExitKey()
Sets the common key-pair for exiting the application (Ctrl-Q) and ties it to the wxID_EXIT event id.
void OnPreferences(wxCommandEvent &event)
Displays the preferences and settings of all opened editors paged dialog.
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.
void FinishAUIInitialization()
virtual wxString GetCurrentFileName() const
Get the full filename + path of the currently opened file in the frame.
void ChangeUserUnits(EDA_UNITS aUnits)
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...
wxTimer * m_autoSaveTimer
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 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.
void ClearFileHistory(FILE_HISTORY *aFileHistory=nullptr)
Removes all files from the file history.
std::map< int, UIUpdateHandler > m_uiUpdateMap
< Map containing the UI update handlers registered with wx for each action.
UNDO_REDO_CONTAINER m_redoList
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
FILE_HISTORY * m_fileHistory
virtual void OnSize(wxSizeEvent &aEvent)
virtual PICKED_ITEMS_LIST * PopCommandFromUndoList()
Return the last command to undo and remove it from list, nothing is deleted.
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)
Checks if aFileName can be written.
wxPoint m_normalFramePos
void OnMaximize(wxMaximizeEvent &aEvent)
virtual void OnDropFiles(wxDropFilesEvent &aEvent)
Handles event fired when a file is dropped to the window.
std::map< const wxString, TOOL_ACTION * > m_acceptedExts
Associates files 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)
Fetches the file name from the file history list.
static wxString GetAutoSaveFilePrefix()
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.
virtual void PushCommandToRedoList(PICKED_ITEMS_LIST *aItem)
Add a command to redo in the redo list.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_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...
bool m_isClosing
Set by NonUserClose() to indicate that the user did not request the current close.
void AddStandardHelpMenu(wxMenuBar *aMenuBar)
Adds the standard KiCad help menu to the menubar.
wxString m_mruPath
virtual void ReCreateMenuBar()
Recreates the menu bar.
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...
Definition: filehistory.h:43
void AddFileToHistory(const wxString &aFile) override
Adds a file to the history.
Definition: filehistory.cpp:96
void ClearFileHistory()
Clear all entries from the file history.
void Save(APP_SETTINGS_BASE &aSettings)
Saves history into a JSON settings object.
Definition: filehistory.cpp:67
void SetMaxFiles(size_t aMaxFiles)
Update the number of files that will be contained inside the file history.
Definition: filehistory.cpp:85
void Load(const APP_SETTINGS_BASE &aSettings)
Loads history from a JSON settings object.
Definition: filehistory.cpp:45
SEARCH_STACK & KifaceSearch()
Only for DSO specific 'non-library' files.
Definition: kiface_base.h:114
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:93
const wxString & GetHelpFileName() const
Return just the basename portion of the current help file.
Definition: kiface_base.h:110
A mix in class which holds the location of a wxWindow's KIWAY.
Definition: kiway_holder.h:37
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:267
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:572
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:198
@ FACE_SCH
eeschema DSO
Definition: kiway.h:274
@ FACE_PL_EDITOR
Definition: kiway.h:278
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:275
@ FACE_GERBVIEW
Definition: kiway.h:277
virtual void GetActions(std::vector< TOOL_ACTION * > &aActions) const
Append all registered actions to the given list.
Definition: kiway.cpp:497
wxTreebook * GetTreebook()
Definition: paged_dialog.h:37
std::vector< TOOL_ACTION * > & ActionsList()
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:139
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:154
Look for files in a number of paths.
Definition: search_stack.h:42
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:170
virtual void ShowChangedLanguage()
TOOL_DISPATCHER * m_toolDispatcher
Definition: tools_holder.h:172
virtual SELECTION & GetCurrentSelection()
Get the current selection from the canvas area.
Definition: tools_holder.h:101
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Notification event that some of the common (suite-wide) settings have changed.
int GetUIId() const
Definition: tool_action.h:130
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
void PushCommand(PICKED_ITEMS_LIST *aCommand)
PICKED_ITEMS_LIST * PopCommand()
void SetUserUnits(EDA_UNITS aUnits)
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:75
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:286
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.
Definition: infobar.cpp:128
MESSAGE_TYPE
Sets the type of message for special handling if needed.
Definition: infobar.h:93
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:276
void SetCallback(std::function< void(void)> aCallback)
Provide a callback to be called when the infobar is dismissed (either by user action or timer).
Definition: infobar.h:157
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:299
This file is part of the common library.
return & kiface
Definition: cvpcb.cpp:112
#define _(s)
static const wxSize minSize(FRAME_T aFrameType)
wxDEFINE_EVENT(UNITS_CHANGED, wxCommandEvent)
static const wxSize defaultSize(FRAME_T aFrameType)
#define CREATE_PANEL(key)
#define DEFAULT_MAX_UNDO_ITEMS
std::function< void(wxUpdateUIEvent &) > UIUpdateHandler
This is the handler functor for the update UI events.
void SocketCleanup()
Definition: eda_dde.cpp:319
DDE server & client.
EDA_UNITS
Definition: eda_units.h:43
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:33
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
@ FRAME_SCH_SYMBOL_EDITOR
Definition: frame_type.h:35
@ PANEL_SCH_FIELD_NAME_TEMPLATES
Definition: frame_type.h:76
@ PANEL_GBR_DISPLAY_OPTIONS
Definition: frame_type.h:94
@ PANEL_3DV_COLORS
Definition: frame_type.h:92
@ PANEL_3DV_OPENGL
Definition: frame_type.h:90
@ PANEL_PCB_ORIGINS_AXES
Definition: frame_type.h:87
@ PANEL_PCB_EDIT_OPTIONS
Definition: frame_type.h:84
@ PANEL_SCH_DISP_OPTIONS
Definition: frame_type.h:72
@ PANEL_FP_DISPLAY_OPTIONS
Definition: frame_type.h:78
@ FRAME_SCH
Definition: frame_type.h:34
@ PANEL_DS_COLORS
Definition: frame_type.h:100
@ PANEL_PCB_COLORS
Definition: frame_type.h:85
@ PANEL_3DV_RAYTRACING
Definition: frame_type.h:91
@ PANEL_SYM_EDIT_OPTIONS
Definition: frame_type.h:69
@ PANEL_SCH_EDIT_OPTIONS
Definition: frame_type.h:73
@ PANEL_SYM_DISP_OPTIONS
Definition: frame_type.h:68
@ PANEL_FP_COLORS
Definition: frame_type.h:80
@ PANEL_SYM_COLORS
Definition: frame_type.h:70
@ FRAME_PL_EDITOR
Definition: frame_type.h:55
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:41
@ FRAME_GERBER
Definition: frame_type.h:53
@ FRAME_PCB_DISPLAY3D
Definition: frame_type.h:45
@ PANEL_FP_EDIT_OPTIONS
Definition: frame_type.h:79
@ PANEL_SCH_ANNO_OPTIONS
Definition: frame_type.h:74
@ PANEL_PCB_ACTION_PLUGINS
Definition: frame_type.h:86
@ PANEL_FP_DEFAULT_VALUES
Definition: frame_type.h:81
@ PANEL_3DV_DISPLAY_OPTIONS
Definition: frame_type.h:89
@ PANEL_DS_DISPLAY_OPTIONS
Definition: frame_type.h:99
@ PANEL_PCB_DISPLAY_OPTIONS
Definition: frame_type.h:83
@ PANEL_SCH_COLORS
Definition: frame_type.h:75
@ PANEL_GBR_COLORS
Definition: frame_type.h:97
@ PANEL_GBR_EXCELLON_OPTIONS
Definition: frame_type.h:96
@ KICAD_MAIN_FRAME_T
Definition: frame_type.h:64
bool IsExtensionAccepted(const wxString &aExt, const std::vector< std::string > acceptedExts)
Checks if the file extension is in accepted extensions.
const wxChar *const traceAutoSave
Flag to enable auto save feature debug tracing.
const wxChar *const traceDisplayLocation
Flag to enable debug output of display positioning logic.
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
void ReadHotKeyConfigIntoActions(const wxString &aFileName, std::vector< TOOL_ACTION * > &aActions)
Reads a hotkey config file into a list of actions.
@ ID_FILE_LIST_CLEAR
Definition: id.h:87
@ ID_FILE1
Definition: id.h:84
@ ID_AUTO_SAVE_TIMER
Definition: id.h:79
Macros and inline functions to create menus items in menubars or popup menus.
void RemoveShutdownBlockReason(wxWindow *aWindow)
Removes any shutdown block reason set.
Definition: gtk/app.cpp:78
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition: pgm_base.cpp:83
see class PGM_BASE
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
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:150
int m_KI_Lang_Identifier
KiCad identifier used in menu selection (See id.h)
Definition: pgm_base.h:65
struct WINDOW_STATE window
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:83
WINDOW_STATE state
Definition: app_settings.h:84
wxString mru_path
Definition: app_settings.h:85
wxString perspective
Definition: app_settings.h:86
Stores the window positioning/state.
Definition: app_settings.h:70
unsigned int display
Definition: app_settings.h:76
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.