KiCad PCB EDA Suite
widget_hotkey_list.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) 2016 Chris Pavlina <pavlina.chris@gmail.com>
5  * Copyright (C) 2016-2017 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 3
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 <cctype>
26 
28 
29 #include <wx/statline.h>
30 
31 #include <draw_frame.h>
32 #include <dialog_shim.h>
33 
34 
38 static const int HOTKEY_MIN_WIDTH = 100;
39 
40 
45 {
46  ID_EDIT = 2001,
51 };
52 
53 
60 class WIDGET_HOTKEY_CLIENT_DATA : public wxClientData
61 {
63 
64 public:
66  : m_changed_hotkey( aChangedHotkey )
67  {}
68 
70 };
71 
72 
78 {
79  wxKeyEvent m_event;
80 
81 public:
82  HK_PROMPT_DIALOG( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
83  const wxString& aName, const wxString& aCurrentKey )
84  : DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
85  {
86  wxPanel* panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize );
87  wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
88 
89  /* Dialog layout:
90  *
91  * inst_label........................
92  * ----------------------------------
93  *
94  * cmd_label_0 cmd_label_1 \
95  * | fgsizer
96  * key_label_0 key_label_1 /
97  */
98 
99  wxStaticText* inst_label = new wxStaticText( panel, wxID_ANY, wxEmptyString,
100  wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL );
101 
102  inst_label->SetLabelText( _( "Press a new hotkey, or press Esc to cancel..." ) );
103  sizer->Add( inst_label, 0, wxALL, 5 );
104 
105  sizer->Add( new wxStaticLine( panel ), 0, wxALL | wxEXPAND, 2 );
106 
107  wxFlexGridSizer* fgsizer = new wxFlexGridSizer( 2 );
108 
109  wxStaticText* cmd_label_0 = new wxStaticText( panel, wxID_ANY, _( "Command:" ) );
110  fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
111 
112  wxStaticText* cmd_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
113  cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
114  cmd_label_1->SetLabel( aName );
115  fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
116 
117  wxStaticText* key_label_0 = new wxStaticText( panel, wxID_ANY, _( "Current key:" ) );
118  fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
119 
120  wxStaticText* key_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
121  key_label_1->SetFont( key_label_1->GetFont().Bold() );
122  key_label_1->SetLabel( aCurrentKey );
123  fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
124 
125  sizer->Add( fgsizer, 1, wxEXPAND );
126 
127  // Wrap the sizer in a second to give a larger border around the whole dialog
128  wxBoxSizer* outer_sizer = new wxBoxSizer( wxVERTICAL );
129  outer_sizer->Add( sizer, 0, wxALL | wxEXPAND, 10 );
130  panel->SetSizer( outer_sizer );
131 
132  Layout();
133  outer_sizer->Fit( this );
134  Center();
135 
136  SetMinClientSize( GetClientSize() );
137 
138  // Binding both EVT_CHAR and EVT_CHAR_HOOK ensures that all key events,
139  // including specials like Tab and Return, are received, particularly
140  // on MSW.
141  panel->Bind( wxEVT_CHAR, &HK_PROMPT_DIALOG::OnChar, this );
142  panel->Bind( wxEVT_CHAR_HOOK, &HK_PROMPT_DIALOG::OnCharHook, this );
143  }
144 
145 
146  void OnCharHook( wxKeyEvent& aEvent )
147  {
148  // On certain platforms, EVT_CHAR_HOOK is the only handler that receives
149  // certain "special" keys. However, it doesn't always receive "normal"
150  // keys correctly. For example, with a US keyboard, it sees ? as shift+/.
151  //
152  // Untangling these incorrect keys would be too much trouble, so we bind
153  // both events, and simply skip the EVT_CHAR_HOOK if it receives a
154  // "normal" key.
155 
156  const enum wxKeyCode skipped_keys[] =
157  {
158  WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL,
159  WXK_NUMLOCK, WXK_SCROLL, WXK_RAW_CONTROL
160  };
161 
162  int key = aEvent.GetKeyCode();
163 
164  for( size_t i = 0; i < sizeof( skipped_keys ) / sizeof( skipped_keys[0] ); ++i )
165  {
166  if( key == skipped_keys[i] )
167  return;
168  }
169 
170  if( key <= 255 && isprint( key ) && !isspace( key ) )
171  {
172  // Let EVT_CHAR handle this one
173  aEvent.DoAllowNextEvent();
174 
175  // On Windows, wxEvent::Skip must NOT be called.
176  // On Linux and OSX, wxEvent::Skip MUST be called.
177  // No, I don't know why.
178 #ifndef __WXMSW__
179  aEvent.Skip();
180 #endif
181  }
182  else
183  {
184  OnChar( aEvent );
185  }
186  }
187 
188 
189  void OnChar( wxKeyEvent& aEvent )
190  {
191  m_event = aEvent;
192  EndFlexible( wxID_OK );
193  }
194 
195 
199  void EndFlexible( int aRtnCode )
200  {
201  if( IsQuasiModal() )
202  EndQuasiModal( aRtnCode );
203  else
204  EndModal( aRtnCode );
205  }
206 
207 
208  static wxKeyEvent PromptForKey( wxWindow* aParent, const wxString& aName,
209  const wxString& aCurrentKey )
210  {
211  HK_PROMPT_DIALOG dialog( aParent, wxID_ANY, _( "Set Hotkey" ), aName, aCurrentKey );
212 
213  if( dialog.ShowModal() == wxID_OK )
214  {
215  return dialog.m_event;
216  }
217  else
218  {
219  wxKeyEvent dummy;
220  return dummy;
221  }
222  }
223 };
224 
225 
232 {
233 public:
234  HOTKEY_FILTER( const wxString& aFilterStr )
235  {
236  m_normalised_filter_str = aFilterStr.Upper();
237  m_valid = m_normalised_filter_str.size() > 0;
238  }
239 
240 
248  bool FilterMatches( const EDA_HOTKEY& aHotkey ) const
249  {
250  if( !m_valid )
251  return true;
252 
253  // Match in the (translated) filter string
254  const auto normedInfo = wxGetTranslation( aHotkey.m_InfoMsg ).Upper();
255  if( normedInfo.Contains( m_normalised_filter_str ) )
256  return true;
257 
258  const wxString keyName = KeyNameFromKeyCode( aHotkey.m_KeyCode );
259  if( keyName.Upper().Contains( m_normalised_filter_str ) )
260  return true;
261 
262  return false;
263  }
264 
265 private:
266 
267  bool m_valid;
269 };
270 
271 
273 {
274  if( aItem.IsOk() )
275  {
276  wxClientData* data = GetItemData( aItem );
277 
278  if( !data )
279  {
280  return NULL;
281  }
282  else
283  {
284  return static_cast<WIDGET_HOTKEY_CLIENT_DATA*>( data );
285  }
286  }
287  else
288  {
289  return NULL;
290  }
291 }
292 
293 
295 {
296  return GetHKClientData( GetSelection() );
297 }
298 
299 
301 {
302  const auto hkdata = GetHKClientData( aItem );
303 
304  // This probably means a hotkey-only action is being attempted on
305  // a row that is not a hotkey (like a section heading)
306  wxASSERT_MSG( hkdata != nullptr, "No hotkey data found for list item" );
307 
308  return hkdata;
309 }
310 
311 
313 {
314  for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
315  {
316  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( i );
317 
318  if( hkdata )
319  {
320  const auto& changed_hk = hkdata->GetChangedHotkey();
321  const EDA_HOTKEY& hk = changed_hk.GetCurrentValue();
322 
323  wxString key_text = KeyNameFromKeyCode( hk.m_KeyCode );
324 
325  // mark unsaved changes
326  if( changed_hk.HasUnsavedChange() )
327  key_text += " *";
328 
329  SetItemText( i, 0, wxGetTranslation( hk.m_InfoMsg ) );
330  SetItemText( i, 1, key_text);
331  }
332  }
333 
334  // Trigger a resize in case column widths have changed
335  wxSizeEvent dummy_evt;
336  TWO_COLUMN_TREE_LIST::OnSize( dummy_evt );
337 }
338 
339 
341 {
342  // See if this key code is handled in hotkeys names list
343  bool exists;
344  KeyNameFromKeyCode( aKey, &exists );
345 
346  auto& curr_hk = aHotkey.GetCurrentValue();
347 
348  if( exists && curr_hk.m_KeyCode != aKey )
349  {
350  const auto& tag = aHotkey.GetSectionTag();
351  bool can_update = ResolveKeyConflicts( aKey, tag );
352 
353  if( can_update )
354  {
355  curr_hk.m_KeyCode = aKey;
356  }
357  }
358 }
359 
360 
361 void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
362 {
363  WIDGET_HOTKEY_CLIENT_DATA* hkdata = getExpectedHkClientData( aItem );
364 
365  if( !hkdata )
366  return;
367 
368  wxString name = GetItemText( aItem, 0 );
369  wxString current_key = GetItemText( aItem, 1 );
370 
371  wxKeyEvent key_event = HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key );
372  long key = MapKeypressToKeycode( key_event );
373 
374  if( key )
375  {
376  changeHotkey( hkdata->GetChangedHotkey(), key );
377  UpdateFromClientData();
378  }
379 }
380 
381 
382 void WIDGET_HOTKEY_LIST::ResetItem( wxTreeListItem aItem )
383 {
384  WIDGET_HOTKEY_CLIENT_DATA* hkdata = getExpectedHkClientData( aItem );
385 
386  if( !hkdata )
387  return;
388 
389  auto& changed_hk = hkdata->GetChangedHotkey();
390  const auto& orig_hk = changed_hk.GetOriginalValue();
391 
392  changeHotkey( changed_hk, orig_hk.m_KeyCode );
393  UpdateFromClientData();
394 }
395 
396 
397 void WIDGET_HOTKEY_LIST::ResetItemToDefault( wxTreeListItem aItem )
398 {
399  WIDGET_HOTKEY_CLIENT_DATA* hkdata = getExpectedHkClientData( aItem );
400 
401  if( !hkdata )
402  return;
403 
404  auto& changed_hk = hkdata->GetChangedHotkey();
405 
406  changeHotkey( changed_hk, changed_hk.GetCurrentValue().GetDefaultKeyCode() );
407  UpdateFromClientData();
408 }
409 
410 
411 void WIDGET_HOTKEY_LIST::OnActivated( wxTreeListEvent& aEvent )
412 {
413  EditItem( aEvent.GetItem() );
414 }
415 
416 
417 void WIDGET_HOTKEY_LIST::OnContextMenu( wxTreeListEvent& aEvent )
418 {
419  // Save the active event for use in OnMenu
420  m_context_menu_item = aEvent.GetItem();
421 
422  wxMenu menu;
423 
424  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( m_context_menu_item );
425 
426  // Some actions only apply if the row is hotkey data
427  if( hkdata )
428  {
429  menu.Append( ID_EDIT, _( "Edit..." ) );
430  menu.Append( ID_RESET, _( "Undo Changes" ) );
431  menu.Append( ID_DEFAULT, _( "Restore Default" ) );
432  menu.Append( wxID_SEPARATOR );
433  }
434 
435  menu.Append( ID_RESET_ALL, _( "Undo All Changes" ) );
436  menu.Append( ID_DEFAULT_ALL, _( "Restore All to Default" ) );
437 
438  PopupMenu( &menu );
439 }
440 
441 
442 void WIDGET_HOTKEY_LIST::OnMenu( wxCommandEvent& aEvent )
443 {
444  switch( aEvent.GetId() )
445  {
446  case ID_EDIT:
447  EditItem( m_context_menu_item );
448  break;
449 
450  case ID_RESET:
451  ResetItem( m_context_menu_item );
452  break;
453 
454  case ID_DEFAULT:
455  ResetItemToDefault( m_context_menu_item );
456  break;
457 
458  case ID_RESET_ALL:
459  ResetAllHotkeys( false );
460  break;
461 
462  case ID_DEFAULT_ALL:
463  ResetAllHotkeys( true );
464  break;
465 
466  default:
467  wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
468  }
469 }
470 
471 
472 bool WIDGET_HOTKEY_LIST::ResolveKeyConflicts( long aKey, const wxString& aSectionTag )
473 {
474  EDA_HOTKEY* conflicting_key = nullptr;
475  EDA_HOTKEY_CONFIG* conflicting_section = nullptr;
476 
477  m_hk_store.CheckKeyConflicts( aKey, aSectionTag, &conflicting_key, &conflicting_section );
478 
479  if( conflicting_key != nullptr )
480  {
481  wxString info = wxGetTranslation( conflicting_key->m_InfoMsg );
482  wxString msg = wxString::Format(
483  _( "\"%s\" is already assigned to \"%s\" in section \"%s\". Are you sure you want "
484  "to change its assignment?" ),
485  KeyNameFromKeyCode( aKey ), GetChars( info ),
486  *(conflicting_section->m_Title) );
487 
488  wxMessageDialog dlg( GetParent(), msg, _( "Confirm change" ), wxYES_NO | wxNO_DEFAULT );
489 
490  if( dlg.ShowModal() == wxID_YES )
491  {
492  // Reset the other hotkey
493  conflicting_key->m_KeyCode = 0;
494  UpdateFromClientData();
495  return true;
496  }
497  else
498  {
499  return false;
500  }
501  }
502  else
503  {
504  return true;
505  }
506 }
507 
508 
509 WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST( wxWindow* aParent, HOTKEY_STORE& aHotkeyStore,
510  bool aReadOnly )
511  : TWO_COLUMN_TREE_LIST( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
512  m_hk_store( aHotkeyStore ),
513  m_readOnly( aReadOnly )
514 {
515  wxString command_header = _( "Command" );
516 
517  if( !m_readOnly )
518  command_header << " " << _( "(double-click to edit)" );
519 
520  AppendColumn( command_header );
521  AppendColumn( _( "Hotkey" ) );
522  SetRubberBandColumn( 0 );
524 
525  if( !m_readOnly )
526  {
527  // The event only apply if the widget is in editable mode
528  Bind( wxEVT_TREELIST_ITEM_ACTIVATED, &WIDGET_HOTKEY_LIST::OnActivated, this );
529  Bind( wxEVT_TREELIST_ITEM_CONTEXT_MENU, &WIDGET_HOTKEY_LIST::OnContextMenu, this );
530  Bind( wxEVT_MENU, &WIDGET_HOTKEY_LIST::OnMenu, this );
531  }
532 }
533 
534 
535 void WIDGET_HOTKEY_LIST::ApplyFilterString( const wxString& aFilterStr )
536 {
537  updateShownItems( aFilterStr );
538 }
539 
540 
541 void WIDGET_HOTKEY_LIST::ResetAllHotkeys( bool aResetToDefault )
542 {
543  Freeze();
544 
545  // Reset all the hotkeys, not just the ones shown
546  // Should not need to check conflicts, as the state we're about
547  // to set to a should be consistent
548  if( aResetToDefault )
549  {
551  }
552  else
553  {
555  }
556 
558  Thaw();
559 }
560 
561 
563 {
564  updateShownItems( "" );
565  return true;
566 }
567 
568 
569 void WIDGET_HOTKEY_LIST::updateShownItems( const wxString& aFilterStr )
570 {
571  Freeze();
572  DeleteAllItems();
573 
574  HOTKEY_FILTER filter( aFilterStr );
575 
576  for( auto& section: m_hk_store.GetSections() )
577  {
578  // Create parent tree item
579  wxTreeListItem parent = AppendItem( GetRootItem(), section.m_name );
580 
581  for( auto& hotkey: section.m_hotkeys )
582  {
583  if( filter.FilterMatches( hotkey.GetCurrentValue() ) )
584  {
585  wxTreeListItem item = AppendItem( parent, wxEmptyString );
586  SetItemData( item, new WIDGET_HOTKEY_CLIENT_DATA( hotkey ) );
587  }
588  }
589 
590  Expand( parent );
591  }
592 
594  Thaw();
595 }
596 
597 
599 {
601  return true;
602 }
603 
604 
605 long WIDGET_HOTKEY_LIST::MapKeypressToKeycode( const wxKeyEvent& aEvent )
606 {
607  long key = aEvent.GetKeyCode();
608 
609  if( key == WXK_ESCAPE )
610  {
611  return 0;
612  }
613  else
614  {
615  if( key >= 'a' && key <= 'z' ) // convert to uppercase
616  key = key + ('A' - 'a');
617 
618  // Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL)
619  // to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z'
620  if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
621  key += 'A' - 1;
622 
623  /* Disallow shift for keys that have two keycodes on them (e.g. number and
624  * punctuation keys) leaving only the "letter keys" of A-Z.
625  * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
626  * and Ctrl-( and Ctrl-5 (FR layout).
627  * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
628  */
629  bool keyIsLetter = key >= 'A' && key <= 'Z';
630 
631  if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) )
632  key |= GR_KB_SHIFT;
633 
634  if( aEvent.ControlDown() )
635  key |= GR_KB_CTRL;
636 
637  if( aEvent.AltDown() )
638  key |= GR_KB_ALT;
639 
640  return key;
641  }
642 }
#define GR_KB_ALT
void ResetItemToDefault(wxTreeListItem aItem)
Method ResetItemToDefault Reset the item to the default value.
void OnActivated(wxTreeListEvent &aEvent)
Method OnActivated Handle activation of a row.
HK_PROMPT_DIALOG(wxWindow *aParent, wxWindowID aId, const wxString &aTitle, const wxString &aName, const wxString &aCurrentKey)
static long MapKeypressToKeycode(const wxKeyEvent &aEvent)
Static method MapKeypressToKeycode Map a keypress event to the correct key code for use as a hotkey...
Structure EDA_HOTKEY_CONFIG contains the information required to save hot key information to a config...
Definition: hotkeys_basic.h:94
Modified wxTreeListCtrl designed for use with two columns, with better column resizing.
Class that manages a hotkey that can be changed, reset to its old value, a default or saved...
Definition: hotkey_store.h:39
A class that contains a set of hotkeys, arranged into "sections" and provides some book-keeping funct...
Definition: hotkey_store.h:123
CHANGED_HOTKEY & GetChangedHotkey()
void OnMenu(wxCommandEvent &aEvent)
Method OnMenu Handle activation of a context menu item.
void changeHotkey(CHANGED_HOTKEY &aHotkey, long aKey)
Attempt to change the given hotkey to the given key code.
bool TransferDataToControl()
Method TransferDataToControl Load the hotkey data from the store into the control.
#define GR_KB_CTRL
void SaveAllHotkeys()
Persist all changes to hotkeys in the store to the underlying data structures.
Class DIALOG_SHIM may sit in the inheritance tree between wxDialog and any class written by wxFormBui...
Definition: dialog_shim.h:53
wxString m_normalised_filter_str
EDA_HOTKEY & GetCurrentValue()
Definition: hotkey_store.h:48
ID_WHKL_MENU_IDS
Menu IDs for the hotkey context menu.
static wxKeyEvent PromptForKey(wxWindow *aParent, const wxString &aName, const wxString &aCurrentKey)
void OnCharHook(wxKeyEvent &aEvent)
WIDGET_HOTKEY_CLIENT_DATA * getExpectedHkClientData(wxTreeListItem aItem)
Get the WIDGET_HOTKEY_CLIENT_DATA form an item and assert if it isn&#39;t found.
static const int HOTKEY_MIN_WIDTH
Minimum width of the hotkey column.
const wxString & GetSectionTag() const
Definition: hotkey_store.h:86
HOTKEY_STORE & m_hk_store
void UpdateFromClientData()
Method UpdateFromClientData Refresh the visible text on the widget from the rows&#39; client data objects...
WIDGET_HOTKEY_CLIENT_DATA * GetSelHKClientData()
Method GetSelHKClientData Return the WIDGET_HOTKEY_CLIENT_DATA for the item being edited...
void updateShownItems(const wxString &aFilterStr)
Method updateShownItems.
void SetClampedMinWidth(int aClampedMinWidth)
Set the minimum width of the non-rubber-band column.
Class WIDGET_HOTKEY_CLIENT_DATA Stores the hotkey change data associated with each row...
WIDGET_HOTKEY_CLIENT_DATA(CHANGED_HOTKEY &aChangedHotkey)
void ResetAllHotkeysToDefault()
Reset every hotkey in the store to the default values.
bool FilterMatches(const EDA_HOTKEY &aHotkey) const
Method FilterMatches.
void ApplyFilterString(const wxString &aFilterStr)
Method ApplyFilterString Apply a filter string to the hotkey list, selecting which hotkeys to show...
WIDGET_HOTKEY_LIST(wxWindow *aParent, HOTKEY_STORE &aHotkeyStore, bool aReadOnly)
Constructor WIDGET_HOTKEY_LIST Create a WIDGET_HOTKEY_LIST.
#define GR_KB_SHIFT
wxDataViewItem GetNextItem(wxDataViewCtrl const &aView, wxDataViewItem const &aItem)
Get the next item in list order.
void SetRubberBandColumn(int aRubberBandColumn)
Set the column number that will "rubber-band" (expand with available space).
const EDA_HOTKEY & GetOriginalValue() const
Gets the original value of the hotkey.
Definition: hotkey_store.h:64
wxString m_InfoMsg
Definition: hotkeys_basic.h:66
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
SECTION_LIST & GetSections()
Get the list of sections managed by this store.
class EDA_HOTKEY is a class to handle hot key commands.
Definition: hotkeys_basic.h:59
void EndFlexible(int aRtnCode)
End the dialog whether modal or quasimodal.
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void OnChar(wxKeyEvent &aEvent)
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
wxString * m_Title
Definition: hotkeys_basic.h:99
size_t i
Definition: json11.cpp:597
void ResetAllHotkeysToOriginal()
Resets every hotkey to the original values.
Class HOTKEY_FILTER.
WIDGET_HOTKEY_CLIENT_DATA * GetHKClientData(wxTreeListItem aItem)
Method GetHKClientData Return the WIDGET_HOTKEY_CLIENT_DATA for the given item, or NULL if the item i...
bool ResolveKeyConflicts(long aKey, const wxString &aSectionTag)
Method ResolveKeyConflicts Check if we can set a hotkey, and prompt the user if there is a conflict b...
void OnSize(wxSizeEvent &aEvent)
Override buggy wxTreeListCtrl size handler.
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Function KeyNameFromKeyCode return the key name from the key code Only some wxWidgets key values are ...
void ResetItem(wxTreeListItem aItem)
Method ResetItem Reset the item to the original from the dialog was created.
void EditItem(wxTreeListItem aItem)
Method EditItem Prompt the user for a new hotkey given a list item.
HOTKEY_FILTER(const wxString &aFilterStr)
Class HK_PROMPT_DIALOG Dialog to prompt the user to enter a key.
void ResetAllHotkeys(bool aResetToDefault)
Set hotkeys in the control to default or original values.
void OnContextMenu(wxTreeListEvent &aEvent)
Method OnContextMenu Handle right-click on a row.
bool TransferDataFromControl()
Method TransferDataFromControl Save the hotkey data from the control.