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