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) 1992-2023 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 <file_history.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/wx_infobar.h>
58#include <widgets/wx_grid.h>
59#include <widgets/wx_treebook.h>
60#include <wx/app.h>
61#include <wx/config.h>
62#include <wx/display.h>
63#include <wx/stdpaths.h>
64#include <wx/string.h>
65#include <kiplatform/app.h>
66#include <kiplatform/io.h>
67#include <kiplatform/ui.h>
68
69#include <functional>
70#include <kiface_ids.h>
71
72wxDEFINE_EVENT( EDA_EVT_UNITS_CHANGED, wxCommandEvent );
73
74
75// Minimum window size
76static const wxSize minSize( FRAME_T aFrameType )
77{
78 switch( aFrameType )
79 {
81 return wxSize( 406, 354 );
82
83 default:
84 return wxSize( 500, 400 );
85 }
86}
87
88
89static const wxSize defaultSize( FRAME_T aFrameType )
90{
91 switch( aFrameType )
92 {
94 return wxSize( 850, 540 );
95
96 default:
97 return wxSize( 1280, 720 );
98 }
99}
100
101
102BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
103 EVT_MENU( wxID_ABOUT, EDA_BASE_FRAME::OnKicadAbout )
104 EVT_MENU( wxID_PREFERENCES, EDA_BASE_FRAME::OnPreferences )
105
106 EVT_CHAR_HOOK( EDA_BASE_FRAME::OnCharHook )
107 EVT_MENU_OPEN( EDA_BASE_FRAME::OnMenuEvent )
108 EVT_MENU_CLOSE( EDA_BASE_FRAME::OnMenuEvent )
109 EVT_MENU_HIGHLIGHT_ALL( EDA_BASE_FRAME::OnMenuEvent )
110 EVT_MOVE( EDA_BASE_FRAME::OnMove )
111 EVT_SIZE( EDA_BASE_FRAME::OnSize )
112 EVT_MAXIMIZE( EDA_BASE_FRAME::OnMaximize )
113
114 EVT_SYS_COLOUR_CHANGED( EDA_BASE_FRAME::onSystemColorChange )
115 EVT_ICONIZE( EDA_BASE_FRAME::onIconize )
116END_EVENT_TABLE()
117
118
119void EDA_BASE_FRAME::commonInit( FRAME_T aFrameType )
120{
121 m_ident = aFrameType;
122 m_maximizeByDefault = false;
123 m_infoBar = nullptr;
124 m_settingsManager = nullptr;
125 m_fileHistory = nullptr;
126 m_supportsAutoSave = false;
127 m_autoSavePending = false;
128 m_undoRedoCountMax = DEFAULT_MAX_UNDO_ITEMS;
129 m_isClosing = false;
130 m_isNonUserClose = false;
131 m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
132 m_autoSaveRequired = false;
134 m_frameSize = defaultSize( aFrameType );
135 m_displayIndex = -1;
136
137 m_auimgr.SetArtProvider( new WX_AUI_DOCK_ART() );
138
139 m_settingsManager = &Pgm().GetSettingsManager();
140
141 // Set a reasonable minimal size for the frame
142 SetSizeHints( minSize( aFrameType ).x, minSize( aFrameType ).y, -1, -1, -1, -1 );
143
144 // Store dimensions of the user area of the main window.
145 GetClientSize( &m_frameSize.x, &m_frameSize.y );
146
147 Connect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER,
148 wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) );
149
150 // hook wxEVT_CLOSE_WINDOW so we can call SaveSettings(). This function seems
151 // to be called before any other hook for wxCloseEvent, which is necessary.
152 Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
153
154 initExitKey();
155}
156
157
158EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle,
159 const wxPoint& aPos, const wxSize& aSize, long aStyle,
160 const wxString& aFrameName, KIWAY* aKiway,
161 const EDA_IU_SCALE& aIuScale ) :
162 wxFrame( aParent, wxID_ANY, aTitle, aPos, aSize, aStyle, aFrameName ),
163 TOOLS_HOLDER(),
164 KIWAY_HOLDER( aKiway, KIWAY_HOLDER::FRAME ),
166{
167 commonInit( aFrameType );
168}
169
170
171wxWindow* findQuasiModalDialog( wxWindow* aParent )
172{
173 for( wxWindow* child : aParent->GetChildren() )
174 {
175 if( DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( child ) )
176 {
177 if( dlg->IsQuasiModal() )
178 return dlg;
179
180 if( wxWindow* nestedDlg = findQuasiModalDialog( child ) )
181 return nestedDlg;
182 }
183 }
184
185 return nullptr;
186}
187
188
190{
191 if( wxWindow* dlg = ::findQuasiModalDialog( this ) )
192 return dlg;
193
194 // FIXME: CvPcb is currently implemented on top of KIWAY_PLAYER rather than DIALOG_SHIM,
195 // so we have to look for it separately.
196 if( m_ident == FRAME_SCH )
197 {
198 wxWindow* cvpcb = wxWindow::FindWindowByName( wxS( "CvpcbFrame" ) );
199
200 if( cvpcb )
201 return cvpcb;
202 }
203
204 return nullptr;
205}
206
207
208void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event )
209{
210 // Don't allow closing when a quasi-modal is open.
211 wxWindow* quasiModal = findQuasiModalDialog();
212
213 if( quasiModal )
214 {
215 // Raise and notify; don't give the user a warning regarding "quasi-modal dialogs"
216 // when they have no idea what those are.
217 quasiModal->Raise();
218 wxBell();
219
220 if( event.CanVeto() )
221 event.Veto();
222
223 return;
224 }
225
226
227 if( event.GetId() == wxEVT_QUERY_END_SESSION
228 || event.GetId() == wxEVT_END_SESSION )
229 {
230 // End session means the OS is going to terminate us
231 m_isNonUserClose = true;
232 }
233
234 if( canCloseWindow( event ) )
235 {
236 m_isClosing = true;
237
238 if( m_infoBar )
240
241 APP_SETTINGS_BASE* cfg = config();
242
243 if( cfg )
244 SaveSettings( cfg ); // virtual, wxFrame specific
245
247
248 // Destroy (safe delete frame) this frame only in non modal mode.
249 // In modal mode, the caller will call Destroy().
250 if( !IsModal() )
251 Destroy();
252 }
253 else
254 {
255 if( event.CanVeto() )
256 event.Veto();
257 }
258}
259
260
262{
263 delete m_autoSaveTimer;
264 delete m_fileHistory;
265
267
269
271}
272
273
274bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent )
275{
276#ifdef __WXMAC__
277 // Apple in its infinite wisdom will raise a disabled window before even passing
278 // us the event, so we have no way to stop it. Instead, we have to catch an
279 // improperly ordered disabled window and quasi-modal dialog here and reorder
280 // them.
281 if( !IsEnabled() && IsActive() )
282 {
283 wxWindow* dlg = findQuasiModalDialog();
284 if( dlg )
285 dlg->Raise();
286 }
287#endif
288
289 if( !wxFrame::ProcessEvent( aEvent ) )
290 return false;
291
292 if( Pgm().m_Quitting )
293 return true;
294
295 if( !m_isClosing && m_supportsAutoSave && IsShown() && IsActive()
297 && GetAutoSaveInterval() > 0 )
298 {
299 if( !m_autoSavePending )
300 {
301 wxLogTrace( traceAutoSave, wxT( "Starting auto save timer." ) );
302 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
303 m_autoSavePending = true;
304 }
305 else if( m_autoSaveTimer->IsRunning() )
306 {
307 wxLogTrace( traceAutoSave, wxT( "Stopping auto save timer." ) );
308 m_autoSaveTimer->Stop();
309 m_autoSavePending = false;
310 }
311 }
312
313 return true;
314}
315
316
318{
319 return Pgm().GetCommonSettings()->m_System.autosave_interval;
320}
321
322
323void EDA_BASE_FRAME::onAutoSaveTimer( wxTimerEvent& aEvent )
324{
325 // Don't stomp on someone else's timer event.
326 if( aEvent.GetId() != ID_AUTO_SAVE_TIMER )
327 {
328 aEvent.Skip();
329 return;
330 }
331
332 if( !doAutoSave() )
333 m_autoSaveTimer->Start( GetAutoSaveInterval() * 1000, wxTIMER_ONE_SHOT );
334}
335
336
338{
339 wxCHECK_MSG( false, true, wxT( "Auto save timer function not overridden. Bad programmer!" ) );
340}
341
342
343void EDA_BASE_FRAME::OnCharHook( wxKeyEvent& aKeyEvent )
344{
345 wxLogTrace( kicadTraceKeyEvent, wxS( "EDA_BASE_FRAME::OnCharHook %s" ), dump( aKeyEvent ) );
346
347 // Key events can be filtered here.
348 // Currently no filtering is made.
349 aKeyEvent.Skip();
350}
351
352
353void EDA_BASE_FRAME::OnMenuEvent( wxMenuEvent& aEvent )
354{
355 if( !m_toolDispatcher )
356 aEvent.Skip();
357 else
359}
360
361
363{
365 std::placeholders::_1,
366 this,
367 aConditions );
368
369 m_uiUpdateMap[aID] = evtFunc;
370
371 Bind( wxEVT_UPDATE_UI, evtFunc, aID );
372}
373
374
376{
377 const auto it = m_uiUpdateMap.find( aID );
378
379 if( it == m_uiUpdateMap.end() )
380 return;
381
382 Unbind( wxEVT_UPDATE_UI, it->second, aID );
383}
384
385
386void EDA_BASE_FRAME::HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAME* aFrame,
387 ACTION_CONDITIONS aCond )
388{
389 bool checkRes = false;
390 bool enableRes = true;
391 bool showRes = true;
392 bool isCut = aEvent.GetId() == ACTIONS::cut.GetUIId();
393 bool isCopy = aEvent.GetId() == ACTIONS::copy.GetUIId();
394 bool isPaste = aEvent.GetId() == ACTIONS::paste.GetUIId();
395 SELECTION& selection = aFrame->GetCurrentSelection();
396
397 try
398 {
399 checkRes = aCond.checkCondition( selection );
400 enableRes = aCond.enableCondition( selection );
401 showRes = aCond.showCondition( selection );
402 }
403 catch( std::exception& )
404 {
405 // Something broke with the conditions, just skip the event.
406 aEvent.Skip();
407 return;
408 }
409
410 if( showRes && aEvent.GetId() == ACTIONS::undo.GetUIId() )
411 {
412 wxString msg = _( "Undo" );
413
414 if( enableRes )
415 msg += wxS( " " ) + aFrame->GetUndoActionDescription();
416
417 aEvent.SetText( msg );
418 }
419 else if( showRes && aEvent.GetId() == ACTIONS::redo.GetUIId() )
420 {
421 wxString msg = _( "Redo" );
422
423 if( enableRes )
424 msg += wxS( " " ) + aFrame->GetRedoActionDescription();
425
426 aEvent.SetText( msg );
427 }
428
429 if( isCut || isCopy || isPaste )
430 {
431 wxWindow* focus = wxWindow::FindFocus();
432 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
433
434 if( textEntry && isCut && textEntry->CanCut() )
435 enableRes = true;
436 else if( textEntry && isCopy && textEntry->CanCopy() )
437 enableRes = true;
438 else if( textEntry && isPaste && textEntry->CanPaste() )
439 enableRes = true;
440 else if( dynamic_cast<WX_GRID*>( focus ) )
441 enableRes = false; // Must disable menu in order to get command as CharHook event
442 }
443
444 aEvent.Enable( enableRes );
445 aEvent.Show( showRes );
446
447 // wxWidgets 3.1.5+ includes a field in the event that says if the event supports being
448 // checked, since wxMenuItems don't want to be checked unless they actually are checkable
449#if wxCHECK_VERSION( 3, 1, 5 )
450 if( aEvent.IsCheckable() )
451 aEvent.Check( checkRes );
452#else
453 bool canCheck = true;
454
455 // wxMenuItems don't want to be checked unless they actually are checkable, so we have to
456 // check to see if they can be and can't just universally apply a check in this event.
457 if( wxMenu* menu = dynamic_cast<wxMenu*>( aEvent.GetEventObject() ) )
458 canCheck = menu->FindItem( aEvent.GetId() )->IsCheckable();
459
460 if( canCheck )
461 aEvent.Check( checkRes );
462#endif
463}
464
465
467{
468 // Setup the conditions to check a language menu item
469 auto isCurrentLang =
470 [] ( const SELECTION& aSel, int aLangIdentifier )
471 {
472 return Pgm().GetSelectedLanguageIdentifier() == aLangIdentifier;
473 };
474
475 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
476 {
478 cond.Check( std::bind( isCurrentLang, std::placeholders::_1,
479 LanguagesList[ii].m_WX_Lang_Identifier ) );
480
481 RegisterUIUpdateHandler( LanguagesList[ii].m_KI_Lang_Identifier, cond );
482 }
483}
484
485
487{
495 CallAfter( [=]()
496 {
498 } );
499}
500
501
502void EDA_BASE_FRAME::AddStandardHelpMenu( wxMenuBar* aMenuBar )
503{
505 ACTION_MENU* helpMenu = new ACTION_MENU( false, commonControl );
506
507 helpMenu->Add( ACTIONS::help );
508 helpMenu->Add( ACTIONS::gettingStarted );
509 helpMenu->Add( ACTIONS::listHotKeys );
510 helpMenu->Add( ACTIONS::getInvolved );
511 helpMenu->Add( ACTIONS::donate );
512 helpMenu->Add( ACTIONS::reportBug );
513
514 helpMenu->AppendSeparator();
515 helpMenu->Add( _( "&About KiCad" ), "", wxID_ABOUT, BITMAPS::about );
516
517 // Trailing space keeps OSX from hijacking our menu (and disabling everything in it).
518 aMenuBar->Append( helpMenu, _( "&Help" ) + wxS( " " ) );
519}
520
521
523{
525
526 if( GetMenuBar() )
527 {
529 GetMenuBar()->Refresh();
530 }
531}
532
533
534void EDA_BASE_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
535{
536 TOOLS_HOLDER::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
537
538 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
539
540 if( m_fileHistory )
541 {
542 int historySize = settings->m_System.file_history_size;
543 m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) );
544 }
545
547 ThemeChanged();
548
549 if( GetMenuBar() )
550 {
551 // For icons in menus, icon scaling & hotkeys
553 GetMenuBar()->Refresh();
554 }
555}
556
557
559{
561
562 // Update all the toolbars to have new icons
563 wxAuiPaneInfoArray panes = m_auimgr.GetAllPanes();
564
565 for( size_t i = 0; i < panes.GetCount(); ++i )
566 {
567 if( ACTION_TOOLBAR* toolbar = dynamic_cast<ACTION_TOOLBAR*>( panes[i].window ) )
568 toolbar->RefreshBitmaps();
569 }
570}
571
572
573void EDA_BASE_FRAME::OnSize( wxSizeEvent& aEvent )
574{
575#ifdef __WXMAC__
576 int currentDisplay = wxDisplay::GetFromWindow( this );
577
578 if( m_displayIndex >= 0 && currentDisplay >= 0 && currentDisplay != m_displayIndex )
579 {
580 wxLogTrace( traceDisplayLocation, wxS( "OnSize: current display changed %d to %d" ),
581 m_displayIndex, currentDisplay );
582 m_displayIndex = currentDisplay;
584 }
585#endif
586
587 aEvent.Skip();
588}
589
590
591void EDA_BASE_FRAME::LoadWindowState( const wxString& aFileName )
592{
593 if( !Pgm().GetCommonSettings()->m_Session.remember_open_files )
594 return;
595
596 const PROJECT_FILE_STATE* state = Prj().GetLocalSettings().GetFileState( aFileName );
597
598 if( state != nullptr )
599 {
600 LoadWindowState( state->window );
601 }
602}
603
604
606{
607 bool wasDefault = false;
608
609 m_framePos.x = aState.pos_x;
610 m_framePos.y = aState.pos_y;
611 m_frameSize.x = aState.size_x;
612 m_frameSize.y = aState.size_y;
613
614 wxLogTrace( traceDisplayLocation, wxS( "Config position (%d, %d) with size (%d, %d)" ),
616
617 // Ensure minimum size is set if the stored config was zero-initialized
618 if( m_frameSize.x < minSize( m_ident ).x || m_frameSize.y < minSize( m_ident ).y )
619 {
621 wasDefault = true;
622
623 wxLogTrace( traceDisplayLocation, wxS( "Using minimum size (%d, %d)" ),
625 }
626
627 wxLogTrace( traceDisplayLocation, wxS( "Number of displays: %d" ), wxDisplay::GetCount() );
628
629 if( aState.display >= wxDisplay::GetCount() )
630 {
631 wxLogTrace( traceDisplayLocation, wxS( "Previous display not found" ) );
632
633 // If it isn't attached, use the first display
634 // Warning wxDisplay has 2 ctor variants. the parameter needs a type:
635 const unsigned int index = 0;
636 wxDisplay display( index );
637 wxRect clientSize = display.GetGeometry();
638
639 m_framePos = wxDefaultPosition;
640
641 // Ensure the window fits on the display, since the other one could have been larger
642 if( m_frameSize.x > clientSize.width )
643 m_frameSize.x = clientSize.width;
644
645 if( m_frameSize.y > clientSize.height )
646 m_frameSize.y = clientSize.height;
647 }
648 else
649 {
650 wxPoint upperRight( m_framePos.x + m_frameSize.x, m_framePos.y );
651 wxPoint upperLeft( m_framePos.x, m_framePos.y );
652
653 wxDisplay display( aState.display );
654 wxRect clientSize = display.GetClientArea();
655
656 int yLimTop = clientSize.y;
657 int yLimBottom = clientSize.y + clientSize.height;
658 int xLimLeft = clientSize.x;
659 int xLimRight = clientSize.x + clientSize.width;
660
661 if( upperLeft.x > xLimRight || // Upper left corner too close to right edge of screen
662 upperRight.x < xLimLeft || // Upper right corner too close to left edge of screen
663 upperLeft.y < yLimTop || // Upper corner too close to the bottom of the screen
664 upperLeft.y > yLimBottom )
665 {
666 m_framePos = wxDefaultPosition;
667 wxLogTrace( traceDisplayLocation, wxS( "Resetting to default position" ) );
668 }
669 }
670
671 wxLogTrace( traceDisplayLocation, wxS( "Final window position (%d, %d) with size (%d, %d)" ),
673
674 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
675
676 // Center the window if we reset to default
677 if( m_framePos.x == -1 )
678 {
679 wxLogTrace( traceDisplayLocation, wxS( "Centering window" ) );
680 Center();
681 m_framePos = GetPosition();
682 }
683
684 // Record the frame sizes in an un-maximized state
687
688 // Maximize if we were maximized before
689 if( aState.maximized || ( wasDefault && m_maximizeByDefault ) )
690 {
691 wxLogTrace( traceDisplayLocation, wxS( "Maximizing window" ) );
692 Maximize();
693 }
694
695 m_displayIndex = wxDisplay::GetFromWindow( this );
696}
697
698
700{
701 wxDisplay display( wxDisplay::GetFromWindow( this ) );
702 wxRect clientSize = display.GetClientArea();
703 wxPoint pos = GetPosition();
704 wxSize size = GetWindowSize();
705
706 wxLogTrace( traceDisplayLocation,
707 wxS( "ensureWindowIsOnScreen: clientArea (%d, %d) w %d h %d" ),
708 clientSize.x, clientSize.y,
709 clientSize.width, clientSize.height );
710
711 if( pos.y < clientSize.y )
712 {
713 wxLogTrace( traceDisplayLocation,
714 wxS( "ensureWindowIsOnScreen: y pos %d below minimum, setting to %d" ), pos.y,
715 clientSize.y );
716 pos.y = clientSize.y;
717 }
718
719 if( pos.x < clientSize.x )
720 {
721 wxLogTrace( traceDisplayLocation,
722 wxS( "ensureWindowIsOnScreen: x pos %d is off the client rect, setting to %d" ),
723 pos.x, clientSize.x );
724 pos.x = clientSize.x;
725 }
726
727 if( pos.x + size.x - clientSize.x > clientSize.width )
728 {
729 int newWidth = clientSize.width - ( pos.x - clientSize.x );
730 wxLogTrace( traceDisplayLocation,
731 wxS( "ensureWindowIsOnScreen: effective width %d above available %d, setting "
732 "to %d" ), pos.x + size.x, clientSize.width, newWidth );
733 size.x = newWidth;
734 }
735
736 if( pos.y + size.y - clientSize.y > clientSize.height )
737 {
738 int newHeight = clientSize.height - ( pos.y - clientSize.y );
739 wxLogTrace( traceDisplayLocation,
740 wxS( "ensureWindowIsOnScreen: effective height %d above available %d, setting "
741 "to %d" ), pos.y + size.y, clientSize.height, newHeight );
742 size.y = newHeight;
743 }
744
745 wxLogTrace( traceDisplayLocation, wxS( "Updating window position (%d, %d) with size (%d, %d)" ),
746 pos.x, pos.y, size.x, size.y );
747
748 SetSize( pos.x, pos.y, size.x, size.y );
749}
750
751
753{
754 LoadWindowState( aCfg->state );
755
757 m_mruPath = aCfg->mru_path;
758
760}
761
762
764{
765 if( IsIconized() )
766 return;
767
768 // If the window is maximized, we use the saved window size from before it was maximized
769 if( IsMaximized() )
770 {
773 }
774 else
775 {
777 m_framePos = GetPosition();
778 }
779
780 aCfg->state.pos_x = m_framePos.x;
781 aCfg->state.pos_y = m_framePos.y;
782 aCfg->state.size_x = m_frameSize.x;
783 aCfg->state.size_y = m_frameSize.y;
784 aCfg->state.maximized = IsMaximized();
785 aCfg->state.display = wxDisplay::GetFromWindow( this );
786
787 wxLogTrace( traceDisplayLocation, wxS( "Saving window maximized: %s" ),
788 IsMaximized() ? wxS( "true" ) : wxS( "false" ) );
789 wxLogTrace( traceDisplayLocation, wxS( "Saving config position (%d, %d) with size (%d, %d)" ),
791
792 // Once this is fully implemented, wxAuiManager will be used to maintain
793 // the persistence of the main frame and all it's managed windows and
794 // all of the legacy frame persistence position code can be removed.
795 aCfg->perspective = m_auimgr.SavePerspective().ToStdString();
796
797 aCfg->mru_path = m_mruPath;
798}
799
800
802{
804
805 // Get file history size from common settings
806 int fileHistorySize = Pgm().GetCommonSettings()->m_System.file_history_size;
807
808 // Load the recently used files into the history menu
809 m_fileHistory = new FILE_HISTORY( (unsigned) std::max( 0, fileHistorySize ),
811 m_fileHistory->Load( *aCfg );
812}
813
814
816{
817 wxCHECK( config(), /* void */ );
818
820
821 bool fileOpen = m_isClosing && m_isNonUserClose;
822
823 wxString currentlyOpenedFile = GetCurrentFileName();
824
825 if( Pgm().GetCommonSettings()->m_Session.remember_open_files && !currentlyOpenedFile.IsEmpty() )
826 {
827 wxFileName rfn( currentlyOpenedFile );
828 rfn.MakeRelativeTo( Prj().GetProjectPath() );
829 Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &aCfg->m_Window, fileOpen );
830 }
831
832 // Save the recently used files list
833 if( m_fileHistory )
834 {
835 // Save the currently opened file in the file history
836 if( !currentlyOpenedFile.IsEmpty() )
837 UpdateFileHistory( currentlyOpenedFile );
838
839 m_fileHistory->Save( *aCfg );
840 }
841}
842
843
845{
846 return &aCfg->m_Window;
847}
848
849
851{
852 // KICAD_MANAGER_FRAME overrides this
853 return Kiface().KifaceSettings();
854}
855
856
858{
859 return Kiface().KifaceSearch();
860}
861
862
864{
865 return Kiface().GetHelpFileName();
866}
867
868
869void EDA_BASE_FRAME::PrintMsg( const wxString& text )
870{
871 SetStatusText( text );
872}
873
874
876{
877#if defined( __WXOSX_MAC__ )
879#else
880 m_infoBar = new WX_INFOBAR( this, &m_auimgr );
881
882 m_auimgr.AddPane( m_infoBar, EDA_PANE().InfoBar().Name( wxS( "InfoBar" ) ).Top().Layer(1) );
883#endif
884}
885
886
888{
889#if defined( __WXOSX_MAC__ )
890 m_auimgr.Update();
891#else
892 // Call Update() to fix all pane default sizes, especially the "InfoBar" pane before
893 // hiding it.
894 m_auimgr.Update();
895
896 // We don't want the infobar displayed right away
897 m_auimgr.GetPane( wxS( "InfoBar" ) ).Hide();
898 m_auimgr.Update();
899#endif
900}
901
902
903void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
905{
907
908 if( aShowCloseButton )
910
911 GetInfoBar()->ShowMessageFor( aErrorMsg, 8000, wxICON_ERROR, aType );
912}
913
914
915void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
916 std::function<void(void)> aCallback )
917{
919
920 if( aShowCloseButton )
922
923 if( aCallback )
924 m_infoBar->SetCallback( aCallback );
925
926 GetInfoBar()->ShowMessageFor( aErrorMsg, 6000, wxICON_ERROR );
927}
928
929
930void EDA_BASE_FRAME::ShowInfoBarWarning( const wxString& aWarningMsg, bool aShowCloseButton )
931{
933
934 if( aShowCloseButton )
936
937 GetInfoBar()->ShowMessageFor( aWarningMsg, 6000, wxICON_WARNING );
938}
939
940
941void EDA_BASE_FRAME::ShowInfoBarMsg( const wxString& aMsg, bool aShowCloseButton )
942{
944
945 if( aShowCloseButton )
947
948 GetInfoBar()->ShowMessageFor( aMsg, 8000, wxICON_INFORMATION );
949}
950
951
952void EDA_BASE_FRAME::UpdateFileHistory( const wxString& FullFileName, FILE_HISTORY* aFileHistory )
953{
954 if( !aFileHistory )
955 aFileHistory = m_fileHistory;
956
957 wxASSERT( aFileHistory );
958
959 aFileHistory->AddFileToHistory( FullFileName );
960
961 // Update the menubar to update the file history menu
962 if( !m_isClosing && GetMenuBar() )
963 {
965 GetMenuBar()->Refresh();
966 }
967}
968
969
970wxString EDA_BASE_FRAME::GetFileFromHistory( int cmdId, const wxString& type,
971 FILE_HISTORY* aFileHistory )
972{
973 if( !aFileHistory )
974 aFileHistory = m_fileHistory;
975
976 wxASSERT( aFileHistory );
977
978 int baseId = aFileHistory->GetBaseId();
979
980 wxASSERT( cmdId >= baseId && cmdId < baseId + (int) aFileHistory->GetCount() );
981
982 unsigned i = cmdId - baseId;
983
984 if( i < aFileHistory->GetCount() )
985 {
986 wxString fn = aFileHistory->GetHistoryFile( i );
987
988 if( wxFileName::FileExists( fn ) )
989 {
990 return fn;
991 }
992 else
993 {
994 DisplayErrorMessage( this, wxString::Format( _( "File '%s' was not found." ), fn ) );
995 aFileHistory->RemoveFileFromHistory( i );
996 }
997 }
998
999 // Update the menubar to update the file history menu
1000 if( GetMenuBar() )
1001 {
1003 GetMenuBar()->Refresh();
1004 }
1005
1006 return wxEmptyString;
1007}
1008
1009
1011{
1012 if( !aFileHistory )
1013 aFileHistory = m_fileHistory;
1014
1015 wxASSERT( aFileHistory );
1016
1017 aFileHistory->ClearFileHistory();
1018
1019 // Update the menubar to update the file history menu
1020 if( GetMenuBar() )
1021 {
1023 GetMenuBar()->Refresh();
1024 }
1025}
1026
1027
1028void EDA_BASE_FRAME::OnKicadAbout( wxCommandEvent& event )
1029{
1030 void ShowAboutDialog( EDA_BASE_FRAME * aParent ); // See AboutDialog_main.cpp
1031 ShowAboutDialog( this );
1032}
1033
1034
1035void EDA_BASE_FRAME::OnPreferences( wxCommandEvent& event )
1036{
1037 ShowPreferences( wxEmptyString, wxEmptyString );
1038}
1039
1040
1041void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParentPage )
1042{
1043 wxBeginBusyCursor( wxHOURGLASS_CURSOR );
1044
1045 PAGED_DIALOG dlg( this, _( "Preferences" ), true );
1046
1047 dlg.SetEvtHandlerEnabled( false );
1048
1049 WX_TREEBOOK* book = dlg.GetTreebook();
1050 PANEL_HOTKEYS_EDITOR* hotkeysPanel = new PANEL_HOTKEYS_EDITOR( this, book, false );
1051 KIFACE* kiface = nullptr;
1052 std::vector<int> expand;
1053
1054 Kiway().GetActions( hotkeysPanel->ActionsList() );
1055
1056 book->AddLazyPage(
1057 []( wxWindow* aParent ) -> wxWindow*
1058 {
1059 return new PANEL_COMMON_SETTINGS( aParent );
1060 },
1061 _( "Common" ) );
1062
1063 book->AddLazyPage(
1064 []( wxWindow* aParent ) -> wxWindow*
1065 {
1066 return new PANEL_MOUSE_SETTINGS( aParent );
1067 }, _( "Mouse and Touchpad" ) );
1068
1069 book->AddPage( hotkeysPanel, _( "Hotkeys" ) );
1070
1071#ifdef KICAD_USE_SENTRY
1072 book->AddLazyPage(
1073 []( wxWindow* aParent ) -> wxWindow*
1074 {
1075 return new PANEL_DATA_COLLECTION( aParent );
1076 }, _( "Data Collection" ) );
1077#endif
1078
1079#define LAZY_CTOR( key ) \
1080 [=]( wxWindow* aParent ) \
1081 { \
1082 return kiface->CreateKiWindow( aParent, key, &Kiway() ); \
1083 }
1084
1085 // If a dll is not loaded, the loader will show an error message.
1086
1087 try
1088 {
1090
1091 kiface->GetActions( hotkeysPanel->ActionsList() );
1092
1094 expand.push_back( book->GetPageCount() );
1095
1096 book->AddPage( new wxPanel( book ), _( "Symbol Editor" ) );
1097 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_DISP_OPTIONS ), _( "Display Options" ) );
1098 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_EDIT_OPTIONS ), _( "Editing Options" ) );
1099 book->AddLazySubPage( LAZY_CTOR( PANEL_SYM_COLORS ), _( "Colors" ) );
1100
1101 if( GetFrameType() == FRAME_SCH )
1102 expand.push_back( book->GetPageCount() );
1103
1104 book->AddPage( new wxPanel( book ), _( "Schematic Editor" ) );
1105 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DISP_OPTIONS ), _( "Display Options" ) );
1106 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_EDIT_OPTIONS ), _( "Editing Options" ) );
1107 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_ANNO_OPTIONS ), _( "Annotation Options" ) );
1108 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_COLORS ), _( "Colors" ) );
1109 book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) );
1110 }
1111 catch( ... )
1112 {
1113 }
1114
1115 try
1116 {
1118
1119 kiface->GetActions( hotkeysPanel->ActionsList() );
1120
1122 expand.push_back( book->GetPageCount() );
1123
1124 book->AddPage( new wxPanel( book ), _( "Footprint Editor" ) );
1125 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DISPLAY_OPTIONS ), _( "Display Options" ) );
1126 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_EDIT_OPTIONS ), _( "Editing Options" ) );
1127 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_COLORS ), _( "Colors" ) );
1128 book->AddLazySubPage( LAZY_CTOR( PANEL_FP_DEFAULT_VALUES ), _( "Default Values" ) );
1129
1131 expand.push_back( book->GetPageCount() );
1132
1133 book->AddPage( new wxPanel( book ), _( "PCB Editor" ) );
1134 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_DISPLAY_OPTIONS ), _( "Display Options" ) );
1135 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_EDIT_OPTIONS ), _( "Editing Options" ) );
1136 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_COLORS ), _( "Colors" ) );
1137 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ACTION_PLUGINS ), _( "Action Plugins" ) );
1138 book->AddLazySubPage( LAZY_CTOR( PANEL_PCB_ORIGINS_AXES ), _( "Origins & Axes" ) );
1139
1141 expand.push_back( book->GetPageCount() );
1142
1143 book->AddPage( new wxPanel( book ), _( "3D Viewer" ) );
1144 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_DISPLAY_OPTIONS ), _( "General" ) );
1145 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_OPENGL ), _( "Realtime Renderer" ) );
1146 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_RAYTRACING ), _( "Raytracing Renderer" ) );
1147 book->AddLazySubPage( LAZY_CTOR( PANEL_3DV_COLORS ), _( "Colors" ) );
1148 }
1149 catch( ... )
1150 {
1151 }
1152
1153 try
1154 {
1156
1157 kiface->GetActions( hotkeysPanel->ActionsList() );
1158
1159 if( GetFrameType() == FRAME_GERBER )
1160 expand.push_back( book->GetPageCount() );
1161
1162 book->AddPage( new wxPanel( book ), _( "Gerber Viewer" ) );
1163 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
1164 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_COLORS ), _( "Colors" ) );
1165 book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
1166 }
1167 catch( ... )
1168 {
1169 }
1170
1171 try
1172 {
1174 kiface->GetActions( hotkeysPanel->ActionsList() );
1175
1176 if( GetFrameType() == FRAME_PL_EDITOR )
1177 expand.push_back( book->GetPageCount() );
1178
1179 book->AddPage( new wxPanel( book ), _( "Drawing Sheet Editor" ) );
1180 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
1181 book->AddLazySubPage( LAZY_CTOR( PANEL_DS_COLORS ), _( "Colors" ) );
1182
1183 book->AddLazyPage(
1184 []( wxWindow* aParent ) -> wxWindow*
1185 {
1186 return new PANEL_PCM_SETTINGS( aParent );
1187 }, _( "Plugin and Content Manager" ) );
1188 }
1189 catch( ... )
1190 {
1191 }
1192
1193 // Update all of the action hotkeys. The process of loading the actions through
1194 // the KiFACE will only get us the default hotkeys
1195 ReadHotKeyConfigIntoActions( wxEmptyString, hotkeysPanel->ActionsList() );
1196
1197 for( size_t i = 0; i < book->GetPageCount(); ++i )
1198 book->GetPage( i )->Layout();
1199
1200 for( int page : expand )
1201 book->ExpandNode( page );
1202
1203 if( !aStartPage.IsEmpty() )
1204 dlg.SetInitialPage( aStartPage, aStartParentPage );
1205
1206 // This is unfortunate, but it's the cost of lazy-loading the panels
1207 book->SetMinSize( wxSize( 980, 560 ) );
1208 book->SetInitialSize( wxSize( 980, 560 ) );
1209
1210 dlg.SetEvtHandlerEnabled( true );
1211 wxEndBusyCursor();
1212
1213 if( dlg.ShowModal() == wxID_OK )
1214 {
1215 Pgm().GetSettingsManager().Save();
1216 dlg.Kiway().CommonSettingsChanged( false, false );
1217 }
1218
1219#undef LAZY_CTOR
1220}
1221
1222
1223void EDA_BASE_FRAME::OnDropFiles( wxDropFilesEvent& aEvent )
1224{
1225 wxString* files = aEvent.GetFiles();
1226
1227 for( int nb = 0; nb < aEvent.GetNumberOfFiles(); nb++ )
1228 {
1229 const wxFileName fn = wxFileName( files[nb] );
1230 wxString ext = fn.GetExt();
1231
1232 // Alias all gerber files as GerberFileExtension
1233 if( IsGerberFileExtension( ext ) )
1234 ext = GerberFileExtension;
1235
1236 if( m_acceptedExts.find( ext.ToStdString() ) != m_acceptedExts.end() )
1237 m_AcceptedFiles.emplace_back( fn );
1238 }
1239
1241 m_AcceptedFiles.clear();
1242}
1243
1244
1246{
1247 for( const wxFileName& file : m_AcceptedFiles )
1248 {
1249 wxString fn = file.GetFullPath();
1250 m_toolManager->RunAction( *m_acceptedExts.at( file.GetExt() ), true, &fn );
1251 }
1252}
1253
1254
1255bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
1256{
1257 wxString msg;
1258 wxFileName fn = aFileName;
1259
1260 // Check for absence of a file path with a file name. Unfortunately KiCad
1261 // uses paths relative to the current project path without the ./ part which
1262 // confuses wxFileName. Making the file name path absolute may be less than
1263 // elegant but it solves the problem.
1264 if( fn.GetPath().IsEmpty() && fn.HasName() )
1265 fn.MakeAbsolute();
1266
1267 wxCHECK_MSG( fn.IsOk(), false,
1268 wxT( "File name object is invalid. Bad programmer!" ) );
1269 wxCHECK_MSG( !fn.GetPath().IsEmpty(), false,
1270 wxT( "File name object path <" ) + fn.GetFullPath() +
1271 wxT( "> is not set. Bad programmer!" ) );
1272
1273 if( fn.IsDir() && !fn.IsDirWritable() )
1274 {
1275 msg.Printf( _( "Insufficient permissions to folder '%s'." ), fn.GetPath() );
1276 }
1277 else if( !fn.FileExists() && !fn.IsDirWritable() )
1278 {
1279 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1280 }
1281 else if( fn.FileExists() && !fn.IsFileWritable() )
1282 {
1283 msg.Printf( _( "Insufficient permissions to save file '%s'." ), fn.GetFullPath() );
1284 }
1285
1286 if( !msg.IsEmpty() )
1287 {
1288 if( aVerbose )
1289 DisplayErrorMessage( this, msg );
1290
1291 return false;
1292 }
1293
1294 return true;
1295}
1296
1297
1298void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
1299{
1300 if( !Pgm().IsGUI() )
1301 return;
1302
1303 wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) );
1304
1305 wxFileName autoSaveFileName = aFileName;
1306
1307 // Check for auto save file.
1308 autoSaveFileName.SetName( GetAutoSaveFilePrefix() + aFileName.GetName() );
1309
1310 wxLogTrace( traceAutoSave,
1311 wxT( "Checking for auto save file " ) + autoSaveFileName.GetFullPath() );
1312
1313 if( !autoSaveFileName.FileExists() )
1314 return;
1315
1316 wxString msg = wxString::Format( _( "Well this is potentially embarrassing!\n"
1317 "It appears that the last time you were editing\n"
1318 "%s\n"
1319 "KiCad exited before saving.\n"
1320 "\n"
1321 "Do you wish to open the auto-saved file instead?" ),
1322 aFileName.GetFullName() );
1323
1324 int response = wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxYES_NO | wxICON_QUESTION,
1325 this );
1326
1327 // Make a backup of the current file, delete the file, and rename the auto save file to
1328 // the file name.
1329 if( response == wxYES )
1330 {
1331 // Preserve the permissions of the current file
1332 KIPLATFORM::IO::DuplicatePermissions( aFileName.GetFullPath(), autoSaveFileName.GetFullPath() );
1333
1334 if( !wxRenameFile( autoSaveFileName.GetFullPath(), aFileName.GetFullPath() ) )
1335 {
1336 wxMessageBox( _( "The auto save file could not be renamed to the board file name." ),
1337 Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1338 }
1339 }
1340 else
1341 {
1342 wxLogTrace( traceAutoSave,
1343 wxT( "Removing auto save file " ) + autoSaveFileName.GetFullPath() );
1344
1345 // Remove the auto save file when using the previous file as is.
1346 wxRemoveFile( autoSaveFileName.GetFullPath() );
1347 }
1348}
1349
1350
1352{
1353 // This function should be overridden in child classes
1354 return false;
1355}
1356
1357
1359{
1360 wxAcceleratorEntry entries[1];
1361 entries[0].Set( wxACCEL_CTRL, int( 'Q' ), wxID_EXIT );
1362 wxAcceleratorTable accel( 1, entries );
1363 SetAcceleratorTable( accel );
1364}
1365
1366
1368{
1371}
1372
1373
1375{
1376 m_undoList.PushCommand( aNewitem );
1377
1378 // Delete the extra items, if count max reached
1379 if( m_undoRedoCountMax > 0 )
1380 {
1381 int extraitems = GetUndoCommandCount() - m_undoRedoCountMax;
1382
1383 if( extraitems > 0 )
1384 ClearUndoORRedoList( UNDO_LIST, extraitems );
1385 }
1386}
1387
1388
1390{
1391 m_redoList.PushCommand( aNewitem );
1392
1393 // Delete the extra items, if count max reached
1394 if( m_undoRedoCountMax > 0 )
1395 {
1396 int extraitems = GetRedoCommandCount() - m_undoRedoCountMax;
1397
1398 if( extraitems > 0 )
1399 ClearUndoORRedoList( REDO_LIST, extraitems );
1400 }
1401}
1402
1403
1405{
1406 return m_undoList.PopCommand();
1407}
1408
1409
1411{
1412 return m_redoList.PopCommand();
1413}
1414
1415
1417{
1418 if( GetUndoCommandCount() > 0 )
1419 return m_undoList.m_CommandsList.back()->GetDescription();
1420
1421 return wxEmptyString;
1422}
1423
1424
1426{
1427 if( GetRedoCommandCount() > 0 )
1428 return m_redoList.m_CommandsList.back()->GetDescription();
1429
1430 return wxEmptyString;
1431}
1432
1433
1435{
1436 m_autoSaveRequired = true;
1437}
1438
1439
1441{
1442 SetUserUnits( aUnits );
1444
1445 wxCommandEvent e( EDA_EVT_UNITS_CHANGED );
1446 e.SetInt( static_cast<int>( aUnits ) );
1447 e.SetClientData( this );
1448 ProcessEventLocally( e );
1449}
1450
1451
1452void EDA_BASE_FRAME::OnMaximize( wxMaximizeEvent& aEvent )
1453{
1454 // When we maximize the window, we want to save the old information
1455 // so that we can add it to the settings on next window load.
1456 // Contrary to the documentation, this event seems to be generated
1457 // when the window is also being unmaximized on OSX, so we only
1458 // capture the size information when we maximize the window when on OSX.
1459#ifdef __WXOSX__
1460 if( !IsMaximized() )
1461#endif
1462 {
1464 m_normalFramePos = GetPosition();
1465 wxLogTrace( traceDisplayLocation,
1466 "Maximizing window - Saving position (%d, %d) with size (%d, %d)",
1469 }
1470
1471 // Skip event to actually maximize the window
1472 aEvent.Skip();
1473}
1474
1475
1477{
1478#ifdef __WXGTK__
1479 wxSize winSize = GetSize();
1480
1481 // GTK includes the window decorations in the normal GetSize call,
1482 // so we have to use a GTK-specific sizing call that returns the
1483 // non-decorated window size.
1485 {
1486 int width = 0;
1487 int height = 0;
1488 GTKDoGetSize( &width, &height );
1489
1490 winSize.Set( width, height );
1491 }
1492#else
1493 wxSize winSize = GetSize();
1494#endif
1495
1496 return winSize;
1497}
1498
1499
1501{
1502 // Update the icon theme when the system theme changes and update the toolbars
1504 ThemeChanged();
1505
1506 // This isn't handled by ThemeChanged()
1507 if( GetMenuBar() )
1508 {
1509 // For icons in menus, icon scaling & hotkeys
1511 GetMenuBar()->Refresh();
1512 }
1513}
1514
1515
1516void EDA_BASE_FRAME::onSystemColorChange( wxSysColourChangedEvent& aEvent )
1517{
1518 // Call the handler to update the colors used in the frame
1520
1521 // Skip the change event to ensure the rest of the window controls get it
1522 aEvent.Skip();
1523}
1524
1525
1526void EDA_BASE_FRAME::onIconize( wxIconizeEvent& aEvent )
1527{
1528 // Call the handler
1529 handleIconizeEvent( aEvent );
1530
1531 // Skip the event.
1532 aEvent.Skip();
1533}
1534
1535
1536#ifdef _WIN32
1537WXLRESULT EDA_BASE_FRAME::MSWWindowProc( WXUINT message, WXWPARAM wParam, WXLPARAM lParam )
1538{
1539 // This will help avoid the menu keeping focus when the alt key is released
1540 // You can still trigger accelerators as long as you hold down alt
1541 if( message == WM_SYSCOMMAND )
1542 {
1543 if( wParam == SC_KEYMENU && ( lParam >> 16 ) <= 0 )
1544 return 0;
1545 }
1546
1547 return wxFrame::MSWWindowProc( message, wParam, lParam );
1548}
1549#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:182
BITMAP_STORE * GetBitmapStore()
Definition: bitmap.cpp:94
static TOOL_ACTION paste
Definition: actions.h:69
static TOOL_ACTION reportBug
Cursor control event types.
Definition: actions.h:188
static TOOL_ACTION copy
Definition: actions.h:68
static TOOL_ACTION donate
Definition: actions.h:186
static TOOL_ACTION listHotKeys
Definition: actions.h:185
static TOOL_ACTION getInvolved
Definition: actions.h:187
static TOOL_ACTION undo
Definition: actions.h:65
static TOOL_ACTION redo
Definition: actions.h:66
static TOOL_ACTION cut
Definition: actions.h:67
static TOOL_ACTION gettingStarted
Definition: actions.h:183
static TOOL_ACTION help
Definition: actions.h:184
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:110
WINDOW_SETTINGS m_Window
Definition: app_settings.h:187
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
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.
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.
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 ShowPreferences(wxString aStartPage, wxString aStartParentPage)
Displays the preferences and settings of all opened editors paged dialog, starting with a particular ...
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.
virtual wxString GetRedoActionDescription() const
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 wxString GetUndoActionDescription() const
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
void ReCreateMenuBar()
Recreates 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...
Definition: file_history.h:43
void AddFileToHistory(const wxString &aFile) override
Adds a file to the history.
void ClearFileHistory()
Clear all entries from the file history.
void Save(APP_SETTINGS_BASE &aSettings)
Saves history into a JSON settings object.
void SetMaxFiles(size_t aMaxFiles)
Update the number of files that will be contained inside the file history.
void Load(const APP_SETTINGS_BASE &aSettings)
Loads history from a JSON settings object.
SEARCH_STACK & KifaceSearch()
Only for DSO specific 'non-library' files.
Definition: kiface_base.h:116
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
const wxString & GetHelpFileName() const
Return just the basename portion of the current help file.
Definition: kiface_base.h:112
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:279
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:633
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:202
@ FACE_SCH
eeschema DSO
Definition: kiway.h:286
@ FACE_PL_EDITOR
Definition: kiway.h:290
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:287
@ FACE_GERBVIEW
Definition: kiway.h:289
virtual void GetActions(std::vector< TOOL_ACTION * > &aActions) const
Append all registered actions to the given list.
Definition: kiway.cpp:558
WX_TREEBOOK * GetTreebook()
Definition: paged_dialog.h:38
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: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:155
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()
std::vector< PICKED_ITEMS_LIST * > m_CommandsList
void SetUserUnits(EDA_UNITS aUnits)
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:75
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:301
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: wx_infobar.cpp:140
MESSAGE_TYPE
Sets the type of message for special handling if needed.
Definition: wx_infobar.h:93
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:187
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:291
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: wx_infobar.h:157
bool AddLazyPage(std::function< wxWindow *(wxWindow *aParent)> aLazyCtor, const wxString &text, bool bSelect=false, int imageId=NO_IMAGE)
Definition: wx_treebook.cpp:85
bool AddLazySubPage(std::function< wxWindow *(wxWindow *aParent)> aLazyCtor, const wxString &text, bool bSelect=false, int imageId=NO_IMAGE)
Definition: wx_treebook.cpp:92
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:308
This file is part of the common library.
return & kiface
Definition: cvpcb.cpp:112
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
static const wxSize defaultSize(FRAME_T aFrameType)
#define LAZY_CTOR(key)
wxDEFINE_EVENT(EDA_EVT_UNITS_CHANGED, wxCommandEvent)
wxWindow * findQuasiModalDialog(wxWindow *aParent)
#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 IsGerberFileExtension(const wxString &ext)
const std::string GerberFileExtension
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
bool DuplicatePermissions(const wxString &aSrc, const wxString &aDest)
Duplicates the file security data from one file to another ensuring that they are the same between bo...
Definition: gtk/io.cpp:38
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition: pgm_base.cpp:87
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
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:151
int m_KI_Lang_Identifier
KiCad identifier used in menu selection (See id.h)
Definition: pgm_base.h:67
struct WINDOW_STATE window
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:92
WINDOW_STATE state
Definition: app_settings.h:93
wxString mru_path
Definition: app_settings.h:94
wxString perspective
Definition: app_settings.h:95
Stores the window positioning/state.
Definition: app_settings.h:79
unsigned int display
Definition: app_settings.h:85
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.