KiCad PCB EDA Suite
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 <dick@softplc.com>
5  * Copyright (C) 2012-2018 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <dialog_shim.h>
26 #include <kiway_player.h>
27 #include <wx/evtloop.h>
28 #include <pgm_base.h>
29 #include <eda_rect.h>
30 
31 
34 {
35  wxWindow* m_win;
36 
37 public:
38 
39  WDO_ENABLE_DISABLE( wxWindow* aWindow ) :
40  m_win( aWindow )
41  {
42  if( m_win )
43  m_win->Disable();
44  }
45 
47  {
48  if( m_win )
49  {
50  m_win->Enable();
51  m_win->SetFocus(); // let's focus back on the parent window
52  }
53  }
54 };
55 
56 
57 DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& title,
58  const wxPoint& pos, const wxSize& size, long style, const wxString& name ) :
59  wxDialog( aParent, id, title, pos, size, style, name ),
60  KIWAY_HOLDER( 0 ),
61  m_fixupsRun( false ),
62  m_qmodal_loop( 0 ),
63  m_qmodal_showing( false ),
64  m_qmodal_parent_disabler( 0 )
65 {
66  // pray that aParent is either a KIWAY_PLAYER or DIALOG_SHIM derivation.
67  KIWAY_HOLDER* h = dynamic_cast<KIWAY_HOLDER*>( aParent );
68 
69  // wxASSERT_MSG( h, wxT( "DIALOG_SHIM's parent is NULL or not derived from KIWAY_PLAYER nor DIALOG_SHIM" ) );
70 
71  if( h )
72  SetKiway( this, &h->Kiway() );
73 
74  Bind( wxEVT_CLOSE_WINDOW, &DIALOG_SHIM::OnCloseWindow, this );
75  Bind( wxEVT_BUTTON, &DIALOG_SHIM::OnButton, this );
76 
77 #ifdef __WINDOWS__
78  // On Windows, the app top windows can be brought to the foreground
79  // (at least temporary) in certain circumstances,
80  // for instance when calling an external tool in Eeschema boom generation.
81  // So set the parent KIWAY_PLAYER kicad frame (if exists) to top window
82  // to avoid this annoying behavior
83  KIWAY_PLAYER* parent_kiwayplayer = dynamic_cast<KIWAY_PLAYER*>( aParent );
84 
85  if( parent_kiwayplayer )
86  Pgm().App().SetTopWindow( parent_kiwayplayer );
87 #endif
88 
89  Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_SHIM::OnPaint ) );
90 }
91 
92 
94 {
95  // if the dialog is quasi-modal, this will end its event loop
96  if( IsQuasiModal() )
97  EndQuasiModal( wxID_CANCEL );
98 
100  delete m_qmodal_parent_disabler; // usually NULL by now
101 }
102 
103 
105 {
106  // must be called from the constructor of derived classes,
107  // when all widgets are initialized, and therefore their size fixed
108 
109  // SetSizeHints fixes the minimal size of sizers in the dialog
110  // (SetSizeHints calls Fit(), so no need to call it)
111  GetSizer()->SetSizeHints( this );
112 
113  // the default position, when calling the first time the dlg
114  Center();
115 }
116 
117 
118 void DIALOG_SHIM::SetSizeInDU( int x, int y )
119 {
120  wxSize sz( x, y );
121  SetSize( ConvertDialogToPixels( sz ) );
122 }
123 
124 
126 {
127  wxSize sz( x, 0 );
128  return ConvertDialogToPixels( sz ).x;
129 }
130 
131 
133 {
134  wxSize sz( 0, y );
135  return ConvertDialogToPixels( sz ).y;
136 }
137 
138 
139 // our hashtable is an implementation secret, don't need or want it in a header file
140 #include <hashtables.h>
141 #include <base_struct.h> // EDA_RECT
142 #include <typeinfo>
143 
145 
146 bool DIALOG_SHIM::Show( bool show )
147 {
148  bool ret;
149  const char* hash_key;
150 
151  if( m_hash_key.size() )
152  {
153  // a special case like EDA_LIST_DIALOG, which has multiple uses.
154  hash_key = m_hash_key.c_str();
155  }
156  else
157  {
158  hash_key = typeid(*this).name();
159  }
160 
161  // Show or hide the window. If hiding, save current position and size.
162  // If showing, use previous position and size.
163  if( show )
164  {
165 #ifndef __WINDOWS__
166  wxDialog::Raise(); // Needed on OS X and some other window managers (i.e. Unity)
167 #endif
168  ret = wxDialog::Show( show );
169 
170  // classname is key, returns a zeroed out default EDA_RECT if none existed before.
171  EDA_RECT savedDialogRect = class_map[ hash_key ];
172 
173  if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
174  {
175  SetSize( savedDialogRect.GetPosition().x,
176  savedDialogRect.GetPosition().y,
177  std::max( wxDialog::GetSize().x, savedDialogRect.GetSize().x ),
178  std::max( wxDialog::GetSize().y, savedDialogRect.GetSize().y ),
179  0 );
180  }
181  }
182  else
183  {
184  // Save the dialog's position & size before hiding, using classname as key
185  class_map[ hash_key ] = EDA_RECT( wxDialog::GetPosition(), wxDialog::GetSize() );
186 
187 #ifdef __WXMAC__
188  if ( m_eventLoop )
189  m_eventLoop->Exit( GetReturnCode() ); // Needed for APP-MODAL dlgs on OSX
190 #endif
191 
192  ret = wxDialog::Show( show );
193  }
194 
195  return ret;
196 }
197 
198 
199 bool DIALOG_SHIM::Enable( bool enable )
200 {
201  // so we can do logging of this state change:
202 
203 #if defined(DEBUG)
204  const char* type_id = typeid( *this ).name();
205  printf( "wxDialog %s: %s\n", type_id, enable ? "enabled" : "disabled" );
206 #endif
207 
208  return wxDialog::Enable( enable );
209 }
210 
211 
212 // Traverse all items in the dialog. If selectTextInTextCtrls, do a SelectAll()
213 // in each so that tab followed by typing will replace the existing value.
214 // Also collects the firstTextCtrl and the item with focus (if any).
215 static void recursiveDescent( wxWindowList& children, const bool selectTextInTextCtrls,
216  wxWindow* & firstTextCtrl, wxWindow* & windowWithFocus )
217 {
218  for( wxWindowList::iterator it = children.begin(); it != children.end(); ++it )
219  {
220  wxWindow* child = *it;
221 
222  if( child->HasFocus() )
223  windowWithFocus = child;
224 
225  wxTextCtrl* childTextCtrl = dynamic_cast<wxTextCtrl*>( child );
226  if( childTextCtrl )
227  {
228  if( !firstTextCtrl && childTextCtrl->IsEnabled() && childTextCtrl->IsEditable() )
229  firstTextCtrl = childTextCtrl;
230 
231  if( selectTextInTextCtrls )
232  {
233  wxTextEntry* asTextEntry = dynamic_cast<wxTextEntry*>( childTextCtrl );
234  // Respect an existing selection
235  if( asTextEntry->GetStringSelection().IsEmpty() )
236  asTextEntry->SelectAll();
237  }
238  }
239 
240  recursiveDescent( child->GetChildren(), selectTextInTextCtrls, firstTextCtrl,
241  windowWithFocus );
242  }
243 }
244 
245 #ifdef __WXMAC__
246 static void fixOSXCancelButtonIssue( wxWindow *aWindow )
247 {
248  // A ugly hack to fix an issue on OSX: cmd+c closes the dialog instead of
249  // copying the text if a button with wxID_CANCEL is used in a
250  // wxStdDialogButtonSizer created by wxFormBuilder: the label is &Cancel, and
251  // this accelerator key has priority over the standard copy accelerator.
252  wxButton* button = dynamic_cast<wxButton*>( wxWindow::FindWindowById( wxID_CANCEL, aWindow ) );
253 
254  if( button )
255  {
256  wxString buttonLabel = button->GetLabel();
257  buttonLabel.Replace( wxT( "&C" ), wxT( "C" ) );
258  buttonLabel.Replace( wxT( "&c" ), wxT( "c" ) );
259  button->SetLabel( buttonLabel );
260  }
261 }
262 #endif
263 
264 
265 void DIALOG_SHIM::OnPaint( wxPaintEvent &event )
266 {
267  if( !m_fixupsRun )
268  {
269 #if DLGSHIM_SELECT_ALL_IN_TEXT_CONTROLS
270  const bool selectAllInTextCtrls = true;
271 #else
272  const bool selectAllInTextCtrls = false;
273 #endif
274  wxWindow* firstTextCtrl = NULL;
275  wxWindow* windowWithFocus = NULL;
276 
277  recursiveDescent( GetChildren(), selectAllInTextCtrls, firstTextCtrl,
278  windowWithFocus );
279 
280 #if DLGSHIM_USE_SETFOCUS
281  // While it would be nice to honour any focus already set (which was
282  // recorded in windowWithFocus), the reality is that it's currently wrong
283  // far more often than it's right.
284  // So just focus on the first text control if we have one; otherwise the
285  // focus on the dialog itself, which will at least allow esc, return, etc.
286  // to function.
287  if( firstTextCtrl )
288  firstTextCtrl->SetFocus();
289  else
290  SetFocus();
291 #endif
292 
293 #ifdef __WXMAC__
294  fixOSXCancelButtonIssue( this );
295 #endif
296 
297  m_fixupsRun = true;
298  }
299 
300  event.Skip();
301 }
302 
303 
304 /*
305  Quasi-Modal Mode Explained:
306 
307  The gtk calls in wxDialog::ShowModal() cause event routing problems if that
308  modal dialog then tries to use KIWAY_PLAYER::ShowModal(). The latter shows up
309  and mostly works but does not respond to the window decoration close button.
310  There is no way to get around this without reversing the gtk calls temporarily.
311 
312  Quasi-Modal mode is our own almost modal mode which disables only the parent
313  of the DIALOG_SHIM, leaving other frames operable and while staying captured in the
314  nested event loop. This avoids the gtk calls and leaves event routing pure
315  and sufficient to operate the KIWAY_PLAYER::ShowModal() properly. When using
316  ShowQuasiModal() you have to use EndQuasiModal() in your dialogs and not
317  EndModal(). There is also IsQuasiModal() but its value can only be true
318  when the nested event loop is active. Do not mix the modal and quasi-modal
319  functions. Use one set or the other.
320 
321  You might find this behavior preferable over a pure modal mode, and it was said
322  that only the Mac has this natively, but now other platforms have something
323  similar. You CAN use it anywhere for any dialog. But you MUST use it when
324  you want to use KIWAY_PLAYER::ShowModal() from a dialog event.
325 */
326 
327 
328 
329 /*
333 class ELOOP_ACTIVATOR
334 {
335  friend class EVENT_LOOP;
336 
337 public:
338  ELOOP_ACTIVATOR( WX_EVENT_LOOP* evtLoop )
339  {
340  m_evtLoopOld = wxEventLoopBase::GetActive();
341  // wxEventLoopBase::SetActive( evtLoop );
342  }
343 
344  ~ELOOP_ACTIVATOR()
345  {
346  // restore the previously active event loop
347  wxEventLoopBase::SetActive( m_evtLoopOld );
348  }
349 
350 private:
351  WX_EVENT_LOOP* m_evtLoopOld;
352 };
353 */
354 
355 
356 class EVENT_LOOP : public WX_EVENT_LOOP
357 {
358 public:
359 
361  {
362  ;
363  }
364 
366  {
367  }
368 
369 #if 0 // does not work any better than inherited wxGuiEventLoop functions:
370 
371  // sets the "should exit" flag and wakes up the loop so that it terminates
372  // soon
373  void ScheduleExit( int rc = 0 )
374  {
375  wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not running") );
376 
377  m_exitcode = rc;
378  m_shouldExit = true;
379 
380  OnExit();
381 
382  // all we have to do to exit from the loop is to (maybe) wake it up so that
383  // it can notice that Exit() had been called
384  //
385  // in particular, do *not* use here calls such as PostQuitMessage() (under
386  // MSW) which terminate the current event loop here because we're not sure
387  // that it is going to be processed by the correct event loop: it would be
388  // possible that another one is started and terminated by mistake if we do
389  // this
390  WakeUp();
391  }
392 
393  int Run()
394  {
395  // event loops are not recursive, you need to create another loop!
396  //wxCHECK_MSG( !IsInsideRun(), -1, wxT("can't reenter a message loop") );
397 
398  // ProcessIdle() and ProcessEvents() below may throw so the code here should
399  // be exception-safe, hence we must use local objects for all actions we
400  // should undo
401  wxEventLoopActivator activate(this);
402 
403  // We might be called again, after a previous call to ScheduleExit(), so
404  // reset this flag.
405  m_shouldExit = false;
406 
407  // Set this variable to true for the duration of this method.
408  setInsideRun( true );
409 
410  struct SET_FALSE
411  {
412  EVENT_LOOP* m_loop;
413  SET_FALSE( EVENT_LOOP* aLoop ) : m_loop( aLoop ) {}
414  ~SET_FALSE() { m_loop->setInsideRun( false ); }
415  } t( this );
416 
417  // Finally really run the loop.
418  return DoRun();
419  }
420 
421  bool ProcessEvents()
422  {
423  // process pending wx events first as they correspond to low-level events
424  // which happened before, i.e. typically pending events were queued by a
425  // previous call to Dispatch() and if we didn't process them now the next
426  // call to it might enqueue them again (as happens with e.g. socket events
427  // which would be generated as long as there is input available on socket
428  // and this input is only removed from it when pending event handlers are
429  // executed)
430  if( wxTheApp )
431  {
432  wxTheApp->ProcessPendingEvents();
433 
434  // One of the pending event handlers could have decided to exit the
435  // loop so check for the flag before trying to dispatch more events
436  // (which could block indefinitely if no more are coming).
437  if( m_shouldExit )
438  return false;
439  }
440 
441  return Dispatch();
442  }
443 
444 
445  int DoRun()
446  {
447  // we must ensure that OnExit() is called even if an exception is thrown
448  // from inside ProcessEvents() but we must call it from Exit() in normal
449  // situations because it is supposed to be called synchronously,
450  // wxModalEventLoop depends on this (so we can't just use ON_BLOCK_EXIT or
451  // something similar here)
452  #if wxUSE_EXCEPTIONS
453  for( ; ; )
454  {
455  try
456  {
457  #endif // wxUSE_EXCEPTIONS
458 
459  // this is the event loop itself
460  for( ; ; )
461  {
462  // generate and process idle events for as long as we don't
463  // have anything else to do
464  while ( !m_shouldExit && !Pending() && ProcessIdle() )
465  ;
466 
467  if ( m_shouldExit )
468  break;
469 
470  // a message came or no more idle processing to do, dispatch
471  // all the pending events and call Dispatch() to wait for the
472  // next message
473  if ( !ProcessEvents() )
474  {
475  // we got WM_QUIT
476  break;
477  }
478  }
479 
480  // Process the remaining queued messages, both at the level of the
481  // underlying toolkit level (Pending/Dispatch()) and wx level
482  // (Has/ProcessPendingEvents()).
483  //
484  // We do run the risk of never exiting this loop if pending event
485  // handlers endlessly generate new events but they shouldn't do
486  // this in a well-behaved program and we shouldn't just discard the
487  // events we already have, they might be important.
488  for( ; ; )
489  {
490  bool hasMoreEvents = false;
491  if ( wxTheApp && wxTheApp->HasPendingEvents() )
492  {
493  wxTheApp->ProcessPendingEvents();
494  hasMoreEvents = true;
495  }
496 
497  if ( Pending() )
498  {
499  Dispatch();
500  hasMoreEvents = true;
501  }
502 
503  if ( !hasMoreEvents )
504  break;
505  }
506 
507  #if wxUSE_EXCEPTIONS
508  // exit the outer loop as well
509  break;
510  }
511  catch ( ... )
512  {
513  try
514  {
515  if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() )
516  {
517  OnExit();
518  break;
519  }
520  //else: continue running the event loop
521  }
522  catch ( ... )
523  {
524  // OnException() throwed, possibly rethrowing the same
525  // exception again: very good, but we still need OnExit() to
526  // be called
527  OnExit();
528  throw;
529  }
530  }
531  }
532  #endif // wxUSE_EXCEPTIONS
533 
534  return m_exitcode;
535  }
536 
537 protected:
538  int m_exitcode;
539 
540  /* this only works if you add
541  friend class EVENT_LOOP
542  to EventLoopBase
543  */
544  void setInsideRun( bool aValue )
545  {
546  m_isInsideRun = aValue;
547  }
548 #endif
549 };
550 
551 
553 {
554  // This is an exception safe way to zero a pointer before returning.
555  // Yes, even though DismissModal() clears this first normally, this is
556  // here in case there's an exception before the dialog is dismissed.
557  struct NULLER
558  {
559  void*& m_what;
560  NULLER( void*& aPtr ) : m_what( aPtr ) {}
561  ~NULLER() { m_what = 0; } // indeed, set it to NULL on destruction
562  } clear_this( (void*&) m_qmodal_loop );
563 
564  // release the mouse if it's currently captured as the window having it
565  // will be disabled when this dialog is shown -- but will still keep the
566  // capture making it impossible to do anything in the modal dialog itself
567  wxWindow* win = wxWindow::GetCapture();
568  if( win )
569  win->ReleaseMouse();
570 
571  // Get the optimal parent
572  wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
573 
574  // Show the optimal parent
575  DBG( if( parent ) printf( "%s: optimal parent: %s\n", __func__, typeid(*parent).name() );)
576 
577  wxASSERT_MSG( !m_qmodal_parent_disabler,
578  wxT( "Caller using ShowQuasiModal() twice on same window?" ) );
579 
580  // quasi-modal: disable only my "optimal" parent
582 
583 #ifdef __WXMAC__
584  // Apple in its infinite wisdom will raise a disabled window before even passing
585  // us the event, so we have no way to stop it. Instead, we must set an order on
586  // the windows so that the quasi-modal will be pushed in front of the disabled
587  // window when it is raised.
588  ReparentQuasiModal();
589 #endif
590  Show( true );
591 
592  m_qmodal_showing = true;
593 
594  EVENT_LOOP event_loop;
595 
596  m_qmodal_loop = &event_loop;
597 
598  event_loop.Run();
599 
600  return GetReturnCode();
601 }
602 
603 
604 void DIALOG_SHIM::EndQuasiModal( int retCode )
605 {
606  // Hook up validator and transfer data from controls handling so quasi-modal dialogs
607  // handle validation in the same way as other dialogs.
608  if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
609  return;
610 
611  SetReturnCode( retCode );
612 
613  if( !IsQuasiModal() )
614  {
615  wxFAIL_MSG( wxT( "either DIALOG_SHIM::EndQuasiModal called twice or ShowQuasiModal wasn't called" ) );
616  return;
617  }
618 
619  m_qmodal_showing = false;
620 
621  if( m_qmodal_loop )
622  {
623  if( m_qmodal_loop->IsRunning() )
624  m_qmodal_loop->Exit( 0 );
625  else
626  m_qmodal_loop->ScheduleExit( 0 );
627 
628  m_qmodal_loop = NULL;
629  }
630 
633 
634  Show( false );
635 }
636 
637 
638 void DIALOG_SHIM::OnCloseWindow( wxCloseEvent& aEvent )
639 {
640  if( IsQuasiModal() )
641  {
642  EndQuasiModal( wxID_CANCEL );
643  return;
644  }
645 
646  // This is mandatory to allow wxDialogBase::OnCloseWindow() to be called.
647  aEvent.Skip();
648 }
649 
650 
651 void DIALOG_SHIM::OnButton( wxCommandEvent& aEvent )
652 {
653  if( IsQuasiModal() )
654  {
655  const int id = aEvent.GetId();
656 
657  if( id == GetAffirmativeId() )
658  {
659  EndQuasiModal( id );
660  }
661  else if( id == wxID_APPLY )
662  {
663  // Dialogs that provide Apply buttons should make sure data is valid before
664  // allowing a transfer, as there is no other way to indicate failure
665  // (i.e. the dialog can't refuse to close as it might with OK, because it
666  // isn't closing anyway)
667  if( Validate() )
668  {
669  bool success = TransferDataFromWindow();
670  (void) success;
671  }
672  }
673  else if( id == GetEscapeId() ||
674  (id == wxID_CANCEL && GetEscapeId() == wxID_ANY) )
675  {
676  EndQuasiModal( wxID_CANCEL );
677  }
678  else // not a standard button
679  {
680  aEvent.Skip();
681  }
682 
683  return;
684  }
685 
686  // This is mandatory to allow wxDialogBase::OnButton() to be called.
687  aEvent.Skip();
688 }
bool m_qmodal_showing
Definition: dialog_shim.h:155
Class KIWAY_HOLDER is a mix in class which holds the location of a wxWindow&#39;s KIWAY.
Definition: kiway_player.h:48
Class KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a porti...
Definition: kiway_player.h:111
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
Function SetKiway.
#define WX_EVENT_LOOP
Definition: kiway_player.h:91
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
void OnButton(wxCommandEvent &aEvent)
Function OnCloseWindow.
const wxSize GetSize() const
Definition: eda_rect.h:101
std::string m_hash_key
Definition: dialog_shim.h:151
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
VTBL_ENTRY wxApp & App()
Function App returns a bare naked wxApp, which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:323
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
EVENT_LOOP * m_qmodal_loop
Definition: dialog_shim.h:154
void OnCloseWindow(wxCloseEvent &aEvent)
Function OnCloseWindow.
int ShowQuasiModal()
static RECT_MAP class_map
void SetSizeInDU(int x, int y)
Set the dialog to the given dimensions in "dialog units".
bool IsQuasiModal()
Definition: dialog_shim.h:103
void OnPaint(wxPaintEvent &event)
const wxPoint GetPosition() const
Definition: eda_rect.h:113
bool Show(bool show) override
int VertPixelsFromDU(int y)
Convert an integer number of dialog units to pixels, vertically.
WDO_ENABLE_DISABLE * m_qmodal_parent_disabler
Definition: dialog_shim.h:156
void EndQuasiModal(int retCode)
see class PGM_BASE
DIALOG_SHIM(wxWindow *aParent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE, const wxString &name=wxDialogNameStr)
Definition: dialog_shim.cpp:57
const char * name
Definition: DXF_plotter.cpp:61
#define max(a, b)
Definition: auxiliary.h:86
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Toggle a window&#39;s "enable" status to disabled, then enabled on destruction.
Definition: dialog_shim.cpp:33
static void recursiveDescent(wxWindowList &children, const bool selectTextInTextCtrls, wxWindow *&firstTextCtrl, wxWindow *&windowWithFocus)
bool m_fixupsRun
Definition: dialog_shim.h:149
int HorizPixelsFromDU(int x)
Convert an integer number of dialog units to pixels, horizontally.
bool Enable(bool enable) override
#define DBG(x)
Definition: fctsys.h:33
Basic classes for most KiCad items.
WDO_ENABLE_DISABLE(wxWindow *aWindow)
Definition: dialog_shim.cpp:39
std::unordered_map< std::string, EDA_RECT > RECT_MAP
Map a C string to an EDA_RECT.
Definition: hashtables.h:136