KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_shim.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) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright The 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 <dialog_shim.h>
27#include <core/ignore.h>
28#include <kiway_player.h>
29#include <kiway.h>
30#include <pgm_base.h>
31#include <tool/tool_manager.h>
32#include <kiplatform/ui.h>
33
34#include <wx/display.h>
35#include <wx/evtloop.h>
36#include <wx/app.h>
37#include <wx/event.h>
38#include <wx/grid.h>
39#include <wx/bmpbuttn.h>
40#include <wx/textctrl.h>
41#include <wx/stc/stc.h>
42
43#include <algorithm>
44
45BEGIN_EVENT_TABLE( DIALOG_SHIM, wxDialog )
46 EVT_CHAR_HOOK( DIALOG_SHIM::OnCharHook )
47END_EVENT_TABLE()
48
49
50DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& title,
51 const wxPoint& pos, const wxSize& size, long style,
52 const wxString& name ) :
53 wxDialog( aParent, id, title, pos, size, style, name ),
54 KIWAY_HOLDER( nullptr, KIWAY_HOLDER::DIALOG ),
55 m_units( EDA_UNITS::MM ),
56 m_useCalculatedSize( false ),
57 m_firstPaintEvent( true ),
58 m_initialFocusTarget( nullptr ),
59 m_isClosing( false ),
60 m_qmodal_loop( nullptr ),
61 m_qmodal_showing( false ),
62 m_qmodal_parent_disabler( nullptr ),
63 m_parentFrame( nullptr )
64{
65 KIWAY_HOLDER* kiwayHolder = nullptr;
66 m_initialSize = size;
67
68 if( aParent )
69 {
70 kiwayHolder = dynamic_cast<KIWAY_HOLDER*>( aParent );
71
72 while( !kiwayHolder && aParent->GetParent() )
73 {
74 aParent = aParent->GetParent();
75 kiwayHolder = dynamic_cast<KIWAY_HOLDER*>( aParent );
76 }
77 }
78
79 // Inherit units from parent
80 if( kiwayHolder && kiwayHolder->GetType() == KIWAY_HOLDER::FRAME )
81 m_units = static_cast<EDA_BASE_FRAME*>( kiwayHolder )->GetUserUnits();
82 else if( kiwayHolder && kiwayHolder->GetType() == KIWAY_HOLDER::DIALOG )
83 m_units = static_cast<DIALOG_SHIM*>( kiwayHolder )->GetUserUnits();
84
85 // Don't mouse-warp after a dialog run from the context menu
86 if( kiwayHolder && kiwayHolder->GetType() == KIWAY_HOLDER::FRAME )
87 {
88 m_parentFrame = static_cast<EDA_BASE_FRAME*>( kiwayHolder );
89 TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager();
90
91 if( toolMgr && toolMgr->IsContextMenuActive() )
92 toolMgr->VetoContextMenuMouseWarp();
93 }
94
95 // Set up the message bus
96 if( kiwayHolder )
97 SetKiway( this, &kiwayHolder->Kiway() );
98
99 if( HasKiway() )
100 Kiway().SetBlockingDialog( this );
101
102 Bind( wxEVT_CLOSE_WINDOW, &DIALOG_SHIM::OnCloseWindow, this );
103 Bind( wxEVT_BUTTON, &DIALOG_SHIM::OnButton, this );
104
105#ifdef __WINDOWS__
106 // On Windows, the app top windows can be brought to the foreground (at least temporarily)
107 // in certain circumstances such as when calling an external tool in Eeschema BOM generation.
108 // So set the parent frame (if exists) to top window to avoid this annoying behavior.
109 if( kiwayHolder && kiwayHolder->GetType() == KIWAY_HOLDER::FRAME )
110 Pgm().App().SetTopWindow( (EDA_BASE_FRAME*) kiwayHolder );
111#endif
112
113 Bind( wxEVT_PAINT, &DIALOG_SHIM::OnPaint, this );
114}
115
116
118{
119 m_isClosing = true;
120
121 Unbind( wxEVT_CLOSE_WINDOW, &DIALOG_SHIM::OnCloseWindow, this );
122 Unbind( wxEVT_BUTTON, &DIALOG_SHIM::OnButton, this );
123 Unbind( wxEVT_PAINT, &DIALOG_SHIM::OnPaint, this );
124
125 std::function<void( wxWindowList& )> disconnectFocusHandlers = [&]( wxWindowList& children )
126 {
127 for( wxWindow* child : children )
128 {
129 if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( child ) )
130 {
131 textCtrl->Disconnect( wxEVT_SET_FOCUS,
132 wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ),
133 nullptr, this );
134 }
135 else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( child ) )
136 {
137 scintilla->Disconnect( wxEVT_SET_FOCUS,
138 wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ),
139 nullptr, this );
140 }
141 else
142 {
143 disconnectFocusHandlers( child->GetChildren() );
144 }
145 }
146 };
147
148 disconnectFocusHandlers( GetChildren() );
149
150 // if the dialog is quasi-modal, this will end its event loop
151 if( IsQuasiModal() )
152 EndQuasiModal( wxID_CANCEL );
153
154 if( HasKiway() )
155 Kiway().SetBlockingDialog( nullptr );
156
158}
159
160
162{
163 // must be called from the constructor of derived classes,
164 // when all widgets are initialized, and therefore their size fixed
165
166 // SetSizeHints fixes the minimal size of sizers in the dialog
167 // (SetSizeHints calls Fit(), so no need to call it)
168 GetSizer()->SetSizeHints( this );
169}
170
171
172void DIALOG_SHIM::setSizeInDU( int x, int y )
173{
174 wxSize sz( x, y );
175 SetSize( ConvertDialogToPixels( sz ) );
176}
177
178
180{
181 wxSize sz( x, 0 );
182 return ConvertDialogToPixels( sz ).x;
183}
184
185
187{
188 wxSize sz( 0, y );
189 return ConvertDialogToPixels( sz ).y;
190}
191
192
193// our hashtable is an implementation secret, don't need or want it in a header file
194#include <hashtables.h>
195#include <typeinfo>
196
197static std::unordered_map<std::string, wxRect> class_map;
198
199
200void DIALOG_SHIM::SetPosition( const wxPoint& aNewPosition )
201{
202 wxDialog::SetPosition( aNewPosition );
203
204 // Now update the stored position:
205 const char* hash_key;
206
207 if( m_hash_key.size() )
208 {
209 // a special case like EDA_LIST_DIALOG, which has multiple uses.
210 hash_key = m_hash_key.c_str();
211 }
212 else
213 {
214 hash_key = typeid(*this).name();
215 }
216
217 std::unordered_map<std::string, wxRect>::iterator it = class_map.find( hash_key );
218
219 if( it == class_map.end() )
220 return;
221
222 wxRect rect = it->second;
223 rect.SetPosition( aNewPosition );
224
225 class_map[ hash_key ] = rect;
226}
227
228
229bool DIALOG_SHIM::Show( bool show )
230{
231 bool ret;
232 const char* hash_key;
233
234 if( m_hash_key.size() )
235 {
236 // a special case like EDA_LIST_DIALOG, which has multiple uses.
237 hash_key = m_hash_key.c_str();
238 }
239 else
240 {
241 hash_key = typeid(*this).name();
242 }
243
244 // Show or hide the window. If hiding, save current position and size.
245 // If showing, use previous position and size.
246 if( show )
247 {
248#ifndef __WINDOWS__
249 wxDialog::Raise(); // Needed on OS X and some other window managers (i.e. Unity)
250#endif
251 ret = wxDialog::Show( show );
252
253 // classname is key, returns a zeroed-out default wxRect if none existed before.
254 wxRect savedDialogRect = class_map[ hash_key ];
255
256 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
257 {
259 {
260 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
261 wxDialog::GetSize().x, wxDialog::GetSize().y, 0 );
262 }
263 else
264 {
265 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
266 std::max( wxDialog::GetSize().x, savedDialogRect.GetSize().x ),
267 std::max( wxDialog::GetSize().y, savedDialogRect.GetSize().y ),
268 0 );
269 }
270#ifdef __WXMAC__
271 if( m_parent != nullptr )
272 {
273 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
274 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
275 Centre();
276 }
277#endif
278 }
279 else if( m_initialSize != wxDefaultSize )
280 {
281 SetSize( m_initialSize );
282 Centre();
283 }
284
285 // Be sure that the dialog appears in a visible area
286 // (the dialog position might have been stored at the time when it was
287 // shown on another display)
288 if( wxDisplay::GetFromWindow( this ) == wxNOT_FOUND )
289 Centre();
290 }
291 else
292 {
293 // Save the dialog's position & size before hiding, using classname as key
294 class_map[ hash_key ] = wxRect( wxDialog::GetPosition(), wxDialog::GetSize() );
295
296#ifdef __WXMAC__
297 if ( m_eventLoop )
298 m_eventLoop->Exit( GetReturnCode() ); // Needed for APP-MODAL dlgs on OSX
299#endif
300
301 ret = wxDialog::Show( show );
302
303 if( m_parent )
304 m_parent->SetFocus();
305 }
306
307 return ret;
308}
309
310
312{
313 const char* hash_key;
314
315 if( m_hash_key.size() )
316 {
317 // a special case like EDA_LIST_DIALOG, which has multiple uses.
318 hash_key = m_hash_key.c_str();
319 }
320 else
321 {
322 hash_key = typeid(*this).name();
323 }
324
325 std::unordered_map<std::string, wxRect>::iterator it = class_map.find( hash_key );
326
327 if( it == class_map.end() )
328 return;
329
330 wxRect rect = it->second;
331 rect.SetSize( wxSize( 0, 0 ) );
332 class_map[ hash_key ] = rect;
333}
334
335
336bool DIALOG_SHIM::Enable( bool enable )
337{
338 // so we can do logging of this state change:
339 return wxDialog::Enable( enable );
340}
341
342
343// Recursive descent doing a SelectAll() in wxTextCtrls.
344// MacOS User Interface Guidelines state that when tabbing to a text control all its
345// text should be selected. Since wxWidgets fails to implement this, we do it here.
346void DIALOG_SHIM::SelectAllInTextCtrls( wxWindowList& children )
347{
348 for( wxWindow* child : children )
349 {
350 if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( child ) )
351 {
352 m_beforeEditValues[ textCtrl ] = textCtrl->GetValue();
353 textCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ),
354 nullptr, this );
355
356 // We don't currently run this on GTK because some window managers don't hide the
357 // selection in non-active controls, and other window managers do the selection
358 // automatically anyway.
359#if defined( __WXMAC__ ) || defined( __WXMSW__ )
360 if( !textCtrl->GetStringSelection().IsEmpty() )
361 {
362 // Respect an existing selection
363 }
364 else if( textCtrl->IsEditable() )
365 {
366 textCtrl->SelectAll();
367 }
368#else
369 ignore_unused( textCtrl );
370#endif
371 }
372 else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( child ) )
373 {
374 m_beforeEditValues[ scintilla ] = scintilla->GetText();
375 scintilla->Connect( wxEVT_SET_FOCUS,
376 wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ),
377 nullptr, this );
378
379 if( !scintilla->GetSelectedText().IsEmpty() )
380 {
381 // Respect an existing selection
382 }
383 else if( scintilla->GetMarginWidth( 0 ) > 0 )
384 {
385 // Don't select-all in Custom Rules, etc.
386 }
387 else if( scintilla->IsEditable() )
388 {
389 scintilla->SelectAll();
390 }
391 }
392#ifdef __WXMAC__
393 // Temp hack for square (looking) buttons on OSX. Will likely be made redundant
394 // by the image store....
395 else if( dynamic_cast<wxBitmapButton*>( child ) != nullptr )
396 {
397 wxSize minSize( 29, 27 );
398 wxRect rect = child->GetRect();
399
400 child->ConvertDialogToPixels( minSize );
401
402 rect.Inflate( std::max( 0, minSize.x - rect.GetWidth() ),
403 std::max( 0, minSize.y - rect.GetHeight() ) );
404
405 child->SetMinSize( rect.GetSize() );
406 child->SetSize( rect );
407 }
408#endif
409 else
410 {
411 SelectAllInTextCtrls( child->GetChildren() );
412 }
413 }
414}
415
416
417void DIALOG_SHIM::OnPaint( wxPaintEvent &event )
418{
420 {
422
423 SelectAllInTextCtrls( GetChildren() );
424
427 else
428 KIPLATFORM::UI::ForceFocus( this ); // Focus the dialog itself
429
430 m_firstPaintEvent = false;
431 }
432
433 event.Skip();
434}
435
436
438{
439 if( !GetTitle().StartsWith( wxS( "*" ) ) )
440 SetTitle( wxS( "*" ) + GetTitle() );
441}
442
443
445{
446 if( GetTitle().StartsWith( wxS( "*" ) ) )
447 SetTitle( GetTitle().AfterFirst( '*' ) );
448}
449
451{
452 // Apple in its infinite wisdom will raise a disabled window before even passing
453 // us the event, so we have no way to stop it. Instead, we must set an order on
454 // the windows so that the modal will be pushed in front of the disabled
455 // window when it is raised.
457
458 // Call the base class ShowModal() method
459 return wxDialog::ShowModal();
460}
461
462/*
463 Quasi-Modal Mode Explained:
464
465 The gtk calls in wxDialog::ShowModal() cause event routing problems if that
466 modal dialog then tries to use KIWAY_PLAYER::ShowModal(). The latter shows up
467 and mostly works but does not respond to the window decoration close button.
468 There is no way to get around this without reversing the gtk calls temporarily.
469
470 Quasi-Modal mode is our own almost modal mode which disables only the parent
471 of the DIALOG_SHIM, leaving other frames operable and while staying captured in the
472 nested event loop. This avoids the gtk calls and leaves event routing pure
473 and sufficient to operate the KIWAY_PLAYER::ShowModal() properly. When using
474 ShowQuasiModal() you have to use EndQuasiModal() in your dialogs and not
475 EndModal(). There is also IsQuasiModal() but its value can only be true
476 when the nested event loop is active. Do not mix the modal and quasi-modal
477 functions. Use one set or the other.
478
479 You might find this behavior preferable over a pure modal mode, and it was said
480 that only the Mac has this natively, but now other platforms have something
481 similar. You CAN use it anywhere for any dialog. But you MUST use it when
482 you want to use KIWAY_PLAYER::ShowModal() from a dialog event.
483*/
484
486{
487 NULLER raii_nuller( (void*&) m_qmodal_loop );
488
489 // release the mouse if it's currently captured as the window having it
490 // will be disabled when this dialog is shown -- but will still keep the
491 // capture making it impossible to do anything in the modal dialog itself
492 wxWindow* win = wxWindow::GetCapture();
493 if( win )
494 win->ReleaseMouse();
495
496 // Get the optimal parent
497 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
498
499 wxASSERT_MSG( !m_qmodal_parent_disabler, wxT( "Caller using ShowQuasiModal() twice on same "
500 "window?" ) );
501
502 // quasi-modal: disable only my "optimal" parent
504
505 // Apple in its infinite wisdom will raise a disabled window before even passing
506 // us the event, so we have no way to stop it. Instead, we must set an order on
507 // the windows so that the quasi-modal will be pushed in front of the disabled
508 // window when it is raised.
510
511 Show( true );
512
513 m_qmodal_showing = true;
514
515 wxGUIEventLoop event_loop;
516
517 m_qmodal_loop = &event_loop;
518
519 event_loop.Run();
520
521 m_qmodal_showing = false;
522
523 if( parent )
524 parent->SetFocus();
525
526 return GetReturnCode();
527}
528
529
531{
534}
535
536
538{
541}
542
543
544void DIALOG_SHIM::EndQuasiModal( int retCode )
545{
546 // Hook up validator and transfer data from controls handling so quasi-modal dialogs
547 // handle validation in the same way as other dialogs.
548 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
549 return;
550
551 SetReturnCode( retCode );
552
553 if( !IsQuasiModal() )
554 {
555 wxFAIL_MSG( wxT( "Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal"
556 "wasn't called" ) );
557 return;
558 }
559
561
562 if( m_qmodal_loop )
563 {
564 if( m_qmodal_loop->IsRunning() )
565 m_qmodal_loop->Exit( 0 );
566 else
567 m_qmodal_loop->ScheduleExit( 0 );
568
569 m_qmodal_loop = nullptr;
570 }
571
573 m_qmodal_parent_disabler = nullptr;
574
575 Show( false );
576}
577
578
579void DIALOG_SHIM::OnCloseWindow( wxCloseEvent& aEvent )
580{
581 if( IsQuasiModal() )
582 {
583 EndQuasiModal( wxID_CANCEL );
584 return;
585 }
586
587 // This is mandatory to allow wxDialogBase::OnCloseWindow() to be called.
588 aEvent.Skip();
589}
590
591
592void DIALOG_SHIM::OnButton( wxCommandEvent& aEvent )
593{
594 const int id = aEvent.GetId();
595
596 if( IsQuasiModal() )
597 {
598 if( id == GetAffirmativeId() )
599 {
600 EndQuasiModal( id );
601 }
602 else if( id == wxID_APPLY )
603 {
604 // Dialogs that provide Apply buttons should make sure data is valid before
605 // allowing a transfer, as there is no other way to indicate failure
606 // (i.e. the dialog can't refuse to close as it might with OK, because it
607 // isn't closing anyway)
608 if( Validate() )
609 {
610 ignore_unused( TransferDataFromWindow() );
611 }
612 }
613 else if( id == wxID_CANCEL )
614 {
615 EndQuasiModal( wxID_CANCEL );
616 }
617 else // not a standard button
618 {
619 aEvent.Skip();
620 }
621
622 return;
623 }
624
625 // This is mandatory to allow wxDialogBase::OnButton() to be called.
626 aEvent.Skip();
627}
628
629
630void DIALOG_SHIM::onChildSetFocus( wxFocusEvent& aEvent )
631{
632 // When setting focus to a text control reset the before-edit value.
633
634 if( !m_isClosing )
635 {
636 if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( aEvent.GetEventObject() ) )
637 m_beforeEditValues[ textCtrl ] = textCtrl->GetValue();
638 else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( aEvent.GetEventObject() ) )
639 m_beforeEditValues[ scintilla ] = scintilla->GetText();
640 }
641
642 aEvent.Skip();
643}
644
645
646void DIALOG_SHIM::OnCharHook( wxKeyEvent& aEvt )
647{
648 if( aEvt.GetKeyCode() == 'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
649 {
650 if( m_parentFrame )
651 {
653 return;
654 }
655 }
656 // shift-return (Mac default) or Ctrl-Return (GTK) for OK
657 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER )
658 && ( aEvt.ShiftDown() || aEvt.ControlDown() ) )
659 {
660 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
661 return;
662 }
663 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
664 {
665 wxWindow* currentWindow = wxWindow::FindFocus();
666 int currentIdx = -1;
667 int delta = aEvt.ShiftDown() ? -1 : 1;
668
669 auto advance =
670 [&]( int& idx )
671 {
672 // Wrap-around modulus
673 int size = (int) m_tabOrder.size();
674 idx = ( ( idx + delta ) % size + size ) % size;
675 };
676
677 for( size_t i = 0; i < m_tabOrder.size(); ++i )
678 {
679 if( m_tabOrder[i] == currentWindow )
680 {
681 currentIdx = (int) i;
682 break;
683 }
684 }
685
686 if( currentIdx >= 0 )
687 {
688 advance( currentIdx );
689
690 //todo: We don't currently have non-textentry dialog boxes but this will break if
691 // we add them.
692#ifdef __APPLE__
693 while( dynamic_cast<wxTextEntry*>( m_tabOrder[ currentIdx ] ) == nullptr )
694 advance( currentIdx );
695#endif
696
697 m_tabOrder[ currentIdx ]->SetFocus();
698 return;
699 }
700 }
701 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
702 {
703 wxObject* eventSource = aEvt.GetEventObject();
704
705 if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( eventSource ) )
706 {
707 // First escape after an edit cancels edit
708 if( textCtrl->GetValue() != m_beforeEditValues[ textCtrl ] )
709 {
710 textCtrl->SetValue( m_beforeEditValues[ textCtrl ] );
711 textCtrl->SelectAll();
712 return;
713 }
714 }
715 else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( eventSource ) )
716 {
717 // First escape after an edit cancels edit
718 if( scintilla->GetText() != m_beforeEditValues[ scintilla ] )
719 {
720 scintilla->SetText( m_beforeEditValues[ scintilla ] );
721 scintilla->SelectAll();
722 return;
723 }
724 }
725 }
726
727 aEvt.Skip();
728}
729
730
731static void recursiveDescent( wxSizer* aSizer, std::map<int, wxString>& aLabels )
732{
733 wxStdDialogButtonSizer* sdbSizer = dynamic_cast<wxStdDialogButtonSizer*>( aSizer );
734
735 auto setupButton =
736 [&]( wxButton* aButton )
737 {
738 if( aLabels.count( aButton->GetId() ) > 0 )
739 {
740 aButton->SetLabel( aLabels[ aButton->GetId() ] );
741 }
742 else
743 {
744 // wxWidgets has an uneven track record when the language is changed on
745 // the fly so we set them even when they don't appear in the label map
746 switch( aButton->GetId() )
747 {
748 case wxID_OK: aButton->SetLabel( _( "&OK" ) ); break;
749 case wxID_CANCEL: aButton->SetLabel( _( "&Cancel" ) ); break;
750 case wxID_YES: aButton->SetLabel( _( "&Yes" ) ); break;
751 case wxID_NO: aButton->SetLabel( _( "&No" ) ); break;
752 case wxID_APPLY: aButton->SetLabel( _( "&Apply" ) ); break;
753 case wxID_SAVE: aButton->SetLabel( _( "&Save" ) ); break;
754 case wxID_HELP: aButton->SetLabel( _( "&Help" ) ); break;
755 case wxID_CONTEXT_HELP: aButton->SetLabel( _( "&Help" ) ); break;
756 }
757 }
758 };
759
760 if( sdbSizer )
761 {
762 if( sdbSizer->GetAffirmativeButton() )
763 setupButton( sdbSizer->GetAffirmativeButton() );
764
765 if( sdbSizer->GetApplyButton() )
766 setupButton( sdbSizer->GetApplyButton() );
767
768 if( sdbSizer->GetNegativeButton() )
769 setupButton( sdbSizer->GetNegativeButton() );
770
771 if( sdbSizer->GetCancelButton() )
772 setupButton( sdbSizer->GetCancelButton() );
773
774 if( sdbSizer->GetHelpButton() )
775 setupButton( sdbSizer->GetHelpButton() );
776
777 sdbSizer->Layout();
778
779 if( sdbSizer->GetAffirmativeButton() )
780 sdbSizer->GetAffirmativeButton()->SetDefault();
781 }
782
783 for( wxSizerItem* item : aSizer->GetChildren() )
784 {
785 if( item->GetSizer() )
786 recursiveDescent( item->GetSizer(), aLabels );
787 }
788}
789
790
791void DIALOG_SHIM::SetupStandardButtons( std::map<int, wxString> aLabels )
792{
793 recursiveDescent( GetSizer(), aLabels );
794}
const char * name
Definition: DXF_plotter.cpp:59
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:52
void SelectAllInTextCtrls(wxWindowList &children)
bool m_isClosing
Definition: dialog_shim.h:205
std::vector< wxWindow * > m_tabOrder
Definition: dialog_shim.h:214
void OnPaint(wxPaintEvent &event)
bool m_qmodal_showing
Definition: dialog_shim.h:209
virtual void TearDownQuasiModal()
Override this method to perform dialog tear down actions not suitable for object dtor.
Definition: dialog_shim.h:173
int vertPixelsFromDU(int y) const
Convert an integer number of dialog units to pixels, vertically.
bool Show(bool show) override
wxGUIEventLoop * m_qmodal_loop
Definition: dialog_shim.h:207
void onChildSetFocus(wxFocusEvent &aEvent)
void SetupStandardButtons(std::map< int, wxString > aLabels={})
WINDOW_DISABLER * m_qmodal_parent_disabler
Definition: dialog_shim.h:210
int ShowQuasiModal()
std::string m_hash_key
Definition: dialog_shim.h:194
bool m_firstPaintEvent
Definition: dialog_shim.h:203
int horizPixelsFromDU(int x) const
Convert an integer number of dialog units to pixels, horizontally.
void resetSize()
Clear the existing dialog size and position.
void ClearModify()
std::map< wxWindow *, wxString > m_beforeEditValues
Definition: dialog_shim.h:220
void setSizeInDU(int x, int y)
Set the dialog to the given dimensions in "dialog units".
bool IsQuasiModal() const
Definition: dialog_shim.h:77
bool m_useCalculatedSize
Definition: dialog_shim.h:198
void EndQuasiModal(int retCode)
void CleanupAfterModalSubDialog()
void PrepareForModalSubDialog()
void OnModify()
void OnButton(wxCommandEvent &aEvent)
Properly handle the default button events when in the quasimodal mode when not calling EndQuasiModal ...
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
wxWindow * m_initialFocusTarget
Definition: dialog_shim.h:204
bool Enable(bool enable) override
void SetPosition(const wxPoint &aNewPosition)
Force the position of the dialog to a new position.
void OnCloseWindow(wxCloseEvent &aEvent)
Properly handle the wxCloseEvent when in the quasimodal mode when not calling EndQuasiModal which is ...
wxSize m_initialSize
Definition: dialog_shim.h:217
EDA_BASE_FRAME * m_parentFrame
Definition: dialog_shim.h:212
virtual void OnCharHook(wxKeyEvent &aEvt)
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:102
int ShowModal() override
The base frame for deriving all KiCad main window classes.
virtual void ToggleUserUnits()
A mix in class which holds the location of a wxWindow's KIWAY.
Definition: kiway_holder.h:39
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
bool HasKiway() const
Safety check before asking for the Kiway reference.
Definition: kiway_holder.h:65
HOLDER_TYPE GetType() const
Definition: kiway_holder.h:48
void SetBlockingDialog(wxWindow *aWin)
Definition: kiway.cpp:676
Definition: raii.h:38
virtual wxApp & App()
Return a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:182
Master controller class:
Definition: tool_manager.h:62
bool IsContextMenuActive() const
True while processing a context menu.
Definition: tool_manager.h:500
void VetoContextMenuMouseWarp()
Disable mouse warping after the current context menu is closed.
Definition: tool_manager.h:511
EDA_UNITS GetUserUnits() const
Temporarily disable a window, and then re-enable on destruction.
Definition: raii.h:87
void SuspendForTrueModal()
Definition: raii.h:105
void ResumeAfterTrueModal()
Definition: raii.h:111
static void recursiveDescent(wxSizer *aSizer, std::map< int, wxString > &aLabels)
static std::unordered_map< std::string, wxRect > class_map
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
EDA_UNITS
Definition: eda_units.h:46
void ignore_unused(const T &)
Definition: ignore.h:24
void FixupCancelButtonCmdKeyCollision(wxWindow *aWindow)
Definition: wxgtk/ui.cpp:151
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition: wxgtk/ui.cpp:124
void ReparentModal(wxNonOwnedWindow *aWindow)
Move a window's parent to be the top-level window and force the window to be on top.
Definition: wxgtk/ui.cpp:145
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
see class PGM_BASE
KIWAY Kiway(KFCTL_STANDALONE)
constexpr int delta