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-2020 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>
27 #include <wx/statline.h>
28 #include <wx/treelist.h>
29 #include <wx/msgdlg.h>
30 #include <wx/menu.h>
31 #include <tool/tool_action.h>
32 #include <dialog_shim.h>
33 #include <wx/dcclient.h>
34 
39 {
44 };
45 
46 
53 class WIDGET_HOTKEY_CLIENT_DATA : public wxClientData
54 {
56 
57 public:
58  WIDGET_HOTKEY_CLIENT_DATA( HOTKEY& aChangedHotkey ) :
59  m_changed_hotkey( aChangedHotkey )
60  {}
61 
63 };
64 
65 
70 {
71  wxKeyEvent m_event;
72 
73 public:
74  HK_PROMPT_DIALOG( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
75  const wxString& aName, const wxString& aCurrentKey ) :
76  DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
77  {
78  wxPanel* panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize );
79  wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
80 
81  /* Dialog layout:
82  *
83  * inst_label........................
84  * ----------------------------------
85  *
86  * cmd_label_0 cmd_label_1 \
87  * | fgsizer
88  * key_label_0 key_label_1 /
89  */
90 
91  wxStaticText* inst_label = new wxStaticText( panel, wxID_ANY, wxEmptyString,
92  wxDefaultPosition, wxDefaultSize,
93  wxALIGN_CENTRE_HORIZONTAL );
94 
95  inst_label->SetLabelText( _( "Press a new hotkey, or press Esc to cancel..." ) );
96  sizer->Add( inst_label, 0, wxALL, 5 );
97 
98  sizer->Add( new wxStaticLine( panel ), 0, wxALL | wxEXPAND, 2 );
99 
100  wxFlexGridSizer* fgsizer = new wxFlexGridSizer( 2 );
101 
102  wxStaticText* cmd_label_0 = new wxStaticText( panel, wxID_ANY, _( "Command:" ) );
103  fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
104 
105  wxStaticText* cmd_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
106  cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
107  cmd_label_1->SetLabel( aName );
108  fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
109 
110  wxStaticText* key_label_0 = new wxStaticText( panel, wxID_ANY, _( "Current key:" ) );
111  fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
112 
113  wxStaticText* key_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
114  key_label_1->SetFont( key_label_1->GetFont().Bold() );
115  key_label_1->SetLabel( aCurrentKey );
116  fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
117 
118  sizer->Add( fgsizer, 1, wxEXPAND );
119 
120  // Wrap the sizer in a second to give a larger border around the whole dialog
121  wxBoxSizer* outer_sizer = new wxBoxSizer( wxVERTICAL );
122  outer_sizer->Add( sizer, 0, wxALL | wxEXPAND, 10 );
123  panel->SetSizer( outer_sizer );
124 
125  Layout();
126  outer_sizer->Fit( this );
127  Center();
128 
129  SetMinClientSize( GetClientSize() );
130 
131  // Binding both EVT_CHAR and EVT_CHAR_HOOK ensures that all key events, including
132  // specials like Tab and Return, are received, particularly on MSW.
133  panel->Bind( wxEVT_CHAR, &HK_PROMPT_DIALOG::OnChar, this );
134  panel->Bind( wxEVT_CHAR_HOOK, &HK_PROMPT_DIALOG::OnCharHook, this );
135  SetInitialFocus( panel );
136  }
137 
141  void EndFlexible( int aRtnCode )
142  {
143  if( IsQuasiModal() )
144  EndQuasiModal( aRtnCode );
145  else
146  EndModal( aRtnCode );
147  }
148 
149  static wxKeyEvent PromptForKey( wxWindow* aParent, const wxString& aName,
150  const wxString& aCurrentKey )
151  {
152  HK_PROMPT_DIALOG dialog( aParent, wxID_ANY, _( "Set Hotkey" ), aName, aCurrentKey );
153 
154  if( dialog.ShowModal() == wxID_OK )
155  return dialog.m_event;
156  else
157  return wxKeyEvent();
158  }
159 
160 protected:
161  void OnCharHook( wxKeyEvent& aEvent ) override
162  {
163  // On certain platforms, EVT_CHAR_HOOK is the only handler that receives certain
164  // "special" keys. However, it doesn't always receive "normal" keys correctly. For
165  // example, with a US keyboard, it sees ? as shift+/.
166  //
167  // Untangling these incorrect keys would be too much trouble, so we bind both events,
168  // and simply skip the EVT_CHAR_HOOK if it receives a "normal" key.
169 
170  const enum wxKeyCode skipped_keys[] =
171  {
172  WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL, WXK_NUMLOCK, WXK_SCROLL,
173  WXK_RAW_CONTROL
174  };
175 
176  int key = aEvent.GetKeyCode();
177 
178  for( wxKeyCode skipped_key : skipped_keys )
179  {
180  if( key == skipped_key )
181  return;
182  }
183 
184  if( key <= 255 && isprint( key ) && !isspace( key ) )
185  {
186  // Let EVT_CHAR handle this one
187  aEvent.DoAllowNextEvent();
188 
189  // On Windows, wxEvent::Skip must NOT be called.
190  // On Linux and OSX, wxEvent::Skip MUST be called.
191  // No, I don't know why.
192 #ifndef __WXMSW__
193  aEvent.Skip();
194 #endif
195  }
196  else
197  {
198  OnChar( aEvent );
199  }
200  }
201 
202  void OnChar( wxKeyEvent& aEvent )
203  {
204  m_event = aEvent;
205  EndFlexible( wxID_OK );
206  }
207 };
208 
209 
214 {
215 public:
216  HOTKEY_FILTER( const wxString& aFilterStr )
217  {
218  m_normalised_filter_str = aFilterStr.Upper();
219  m_valid = m_normalised_filter_str.size() > 0;
220  }
221 
227  bool FilterMatches( const HOTKEY& aHotkey ) const
228  {
229  if( !m_valid )
230  return true;
231 
232  // Match in the (translated) filter string
233  const auto normedInfo = wxGetTranslation( aHotkey.m_Actions[ 0 ]->GetLabel() ).Upper();
234 
235  if( normedInfo.Contains( m_normalised_filter_str ) )
236  return true;
237 
238  const wxString keyName = KeyNameFromKeyCode( aHotkey.m_EditKeycode );
239 
240  if( keyName.Upper().Contains( m_normalised_filter_str ) )
241  return true;
242 
243  return false;
244  }
245 
246 private:
247  bool m_valid;
249 };
250 
251 
253 {
254  if( aItem.IsOk() )
255  {
256  wxClientData* data = GetItemData( aItem );
257 
258  if( data )
259  return static_cast<WIDGET_HOTKEY_CLIENT_DATA*>( data );
260  }
261 
262  return nullptr;
263 }
264 
265 
267 {
268  const auto hkdata = getHKClientData( aItem );
269 
270  // This probably means a hotkey-only action is being attempted on
271  // a row that is not a hotkey (like a section heading)
272  wxASSERT_MSG( hkdata != nullptr, "No hotkey data found for list item" );
273 
274  return hkdata;
275 }
276 
277 
279 {
280  for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
281  {
283 
284  if( hkdata )
285  {
286  const HOTKEY& changed_hk = hkdata->GetChangedHotkey();
287  wxString label = changed_hk.m_Actions[ 0 ]->GetLabel();
288  wxString key_text = KeyNameFromKeyCode( changed_hk.m_EditKeycode );
289  wxString description = changed_hk.m_Actions[ 0 ]->GetDescription( false );
290 
291  if( label.IsEmpty() )
292  label = changed_hk.m_Actions[ 0 ]->GetName();
293 
294  // mark unsaved changes
295  if( changed_hk.m_EditKeycode != changed_hk.m_Actions[ 0 ]->GetHotKey() )
296  label += " *";
297 
298  SetItemText( i, 0, label );
299  SetItemText( i, 1, key_text);
300  SetItemText( i, 2, description );
301  }
302  }
303 }
304 
305 
306 void WIDGET_HOTKEY_LIST::changeHotkey( HOTKEY& aHotkey, long aKey )
307 {
308  // See if this key code is handled in hotkeys names list
309  bool exists;
310  KeyNameFromKeyCode( aKey, &exists );
311 
312  if( exists && aHotkey.m_EditKeycode != aKey )
313  {
314  if( aKey == 0 || resolveKeyConflicts( aHotkey.m_Actions[ 0 ], aKey ) )
315  aHotkey.m_EditKeycode = aKey;
316  }
317 }
318 
319 
320 void WIDGET_HOTKEY_LIST::editItem( wxTreeListItem aItem )
321 {
323 
324  if( !hkdata )
325  return;
326 
327  wxString name = GetItemText( aItem, 0 );
328  wxString current_key = GetItemText( aItem, 1 );
329 
330  wxKeyEvent key_event = HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key );
331  long key = MapKeypressToKeycode( key_event );
332 
333  if( key )
334  {
335  changeHotkey( hkdata->GetChangedHotkey(), key );
337  }
338 }
339 
340 
341 void WIDGET_HOTKEY_LIST::resetItem( wxTreeListItem aItem, int aResetId )
342 {
344 
345  if( !hkdata )
346  return;
347 
348  HOTKEY& changed_hk = hkdata->GetChangedHotkey();
349 
350  if( aResetId == ID_RESET )
351  changeHotkey( changed_hk, changed_hk.m_Actions[ 0 ]->GetHotKey() );
352  else if( aResetId == ID_CLEAR )
353  changeHotkey( changed_hk, 0 );
354  else if( aResetId == ID_DEFAULT )
355  changeHotkey( changed_hk, changed_hk.m_Actions[ 0 ]->GetDefaultHotKey() );
356 
358 }
359 
360 
361 void WIDGET_HOTKEY_LIST::onActivated( wxTreeListEvent& aEvent )
362 {
363  editItem( aEvent.GetItem());
364 }
365 
366 
367 void WIDGET_HOTKEY_LIST::onContextMenu( wxTreeListEvent& aEvent )
368 {
369  // Save the active event for use in OnMenu
370  m_context_menu_item = aEvent.GetItem();
371 
372  wxMenu menu;
373 
375 
376  // Some actions only apply if the row is hotkey data
377  if( hkdata )
378  {
379  menu.Append( ID_EDIT_HOTKEY, _( "Edit..." ) );
380  menu.Append( ID_RESET, _( "Undo Changes" ) );
381  menu.Append( ID_CLEAR, _( "Clear Assigned Hotkey" ) );
382  menu.Append( ID_DEFAULT, _( "Restore Default" ) );
383  menu.Append( wxID_SEPARATOR );
384 
385  PopupMenu( &menu );
386  }
387 }
388 
389 
390 void WIDGET_HOTKEY_LIST::onMenu( wxCommandEvent& aEvent )
391 {
392  switch( aEvent.GetId() )
393  {
395  break;
396 
397  case ID_RESET:
398  case ID_CLEAR:
399  case ID_DEFAULT:resetItem( m_context_menu_item, aEvent.GetId());
400  break;
401 
402  default:
403  wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
404  }
405 }
406 
407 
409 {
410  HOTKEY* conflictingHotKey = nullptr;
411 
412  m_hk_store.CheckKeyConflicts( aAction, aKey, &conflictingHotKey );
413 
414  if( !conflictingHotKey )
415  return true;
416 
417  TOOL_ACTION* conflictingAction = conflictingHotKey->m_Actions[ 0 ];
418  wxString msg = wxString::Format( _( "\"%s\" is already assigned to \"%s\" in section \"%s\". "
419  "Are you sure you want to change its assignment?" ),
420  KeyNameFromKeyCode( aKey ),
421  conflictingAction->GetLabel(),
422  HOTKEY_STORE::GetSectionName( conflictingAction ) );
423 
424  wxMessageDialog dlg( GetParent(), msg, _( "Confirm change" ), wxYES_NO | wxNO_DEFAULT );
425 
426  if( dlg.ShowModal() == wxID_YES )
427  {
428  // Reset the other hotkey
429  conflictingHotKey->m_EditKeycode = 0;
431  return true;
432  }
433 
434  return false;
435 }
436 
437 
438 WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST( wxWindow* aParent, HOTKEY_STORE& aHotkeyStore,
439  bool aReadOnly ) :
440  wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
441  m_hk_store( aHotkeyStore ),
442  m_readOnly( aReadOnly )
443 {
444  wxString command_header = _( "Command" );
445 
446  if( !m_readOnly )
447  command_header << " " << _( "(double-click to edit)" );
448 
449  AppendColumn( command_header, 450, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
450  AppendColumn( _( "Hotkey" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
451  AppendColumn( _( "Description" ), 900, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
452 
453 
454 #if defined( __WXGTK__ )// && !wxCHECK_VERSION( 3, 1, 0 )
455  // Automatic column widths are broken in wxGTK 3.0.x; set min widths to ensure visibility
456  // They are also broken in wxGTK 3.1.4
457 
458  wxDataViewCtrl* dv = GetDataView();
459 
460  wxString longKey = wxT( "Ctrl+Alt+Shift+X" );
461  int pad = 20;
462 
463  dv->GetColumn( 0 )->SetMinWidth( dv->GetMainWindow()->GetTextExtent( command_header ).x + pad );
464  dv->GetColumn( 1 )->SetMinWidth( dv->GetMainWindow()->GetTextExtent( longKey ).x + pad );
465 #endif
466 
467  GetDataView()->SetIndent( 10 );
468 
469  if( !m_readOnly )
470  {
471  // The event only apply if the widget is in editable mode
472  Bind( wxEVT_TREELIST_ITEM_ACTIVATED, &WIDGET_HOTKEY_LIST::onActivated, this );
473  Bind( wxEVT_TREELIST_ITEM_CONTEXT_MENU, &WIDGET_HOTKEY_LIST::onContextMenu, this );
474  Bind( wxEVT_MENU, &WIDGET_HOTKEY_LIST::onMenu, this );
475  }
476 }
477 
478 
479 void WIDGET_HOTKEY_LIST::ApplyFilterString( const wxString& aFilterStr )
480 {
481  updateShownItems( aFilterStr );
482 }
483 
484 
485 void WIDGET_HOTKEY_LIST::ResetAllHotkeys( bool aResetToDefault )
486 {
487  Freeze();
488 
489  // Reset all the hotkeys, not just the ones shown
490  // Should not need to check conflicts, as the state we're about
491  // to set to a should be consistent
492  if( aResetToDefault )
494  else
496 
499 
500  Thaw();
501 }
502 
503 
505 {
506  updateShownItems( "" );
508 
509  return true;
510 }
511 
512 
514 {
515  wxDataViewColumn* col = GetDataView()->GetColumn( 0 );
516  col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
517  col->SetWidth( col->GetWidth() );
518 
519 #if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 1, 0 )
520  col->SetResizeable( true );
521 #endif
522 
523  col = GetDataView()->GetColumn( 1 );
524  col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
525  col->SetWidth( col->GetWidth() );
526 
527 #if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 1, 0 )
528  col->SetResizeable( true );
529 #endif
530 }
531 
532 
533 void WIDGET_HOTKEY_LIST::updateShownItems( const wxString& aFilterStr )
534 {
535  Freeze();
536  DeleteAllItems();
537 
538  HOTKEY_FILTER filter( aFilterStr );
539 
540  for( HOTKEY_SECTION& section: m_hk_store.GetSections() )
541  {
542  // Create parent tree item
543  wxTreeListItem parent = AppendItem( GetRootItem(), section.m_SectionName );
544 
545  for( HOTKEY& hotkey: section.m_HotKeys )
546  {
547  if( filter.FilterMatches( hotkey ) )
548  {
549  wxTreeListItem item = AppendItem( parent, wxEmptyString );
550  SetItemData( item, new WIDGET_HOTKEY_CLIENT_DATA( hotkey ) );
551  }
552  }
553 
554  Expand( parent );
555  }
556 
558  Thaw();
559 }
560 
561 
563 {
565  return true;
566 }
567 
568 
569 long WIDGET_HOTKEY_LIST::MapKeypressToKeycode( const wxKeyEvent& aEvent )
570 {
571  long key = aEvent.GetKeyCode();
572 
573  if( key == WXK_ESCAPE )
574  {
575  return 0;
576  }
577  else
578  {
579  if( key >= 'a' && key <= 'z' ) // convert to uppercase
580  key = key + ('A' - 'a');
581 
582  // Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL)
583  // to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z'
584  if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
585  key += 'A' - 1;
586 
587  /* Disallow shift for keys that have two keycodes on them (e.g. number and
588  * punctuation keys) leaving only the "letter keys" of A-Z.
589  * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
590  * and Ctrl-( and Ctrl-5 (FR layout).
591  * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
592  */
593  bool keyIsLetter = key >= 'A' && key <= 'Z';
594 
595  if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) )
596  key |= MD_SHIFT;
597 
598  if( aEvent.ControlDown() )
599  key |= MD_CTRL;
600 
601  if( aEvent.AltDown() )
602  key |= MD_ALT;
603 
604  return key;
605  }
606 }
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.
void changeHotkey(HOTKEY &aHotkey, long aKey)
Attempt to change the given hotkey to the given key code.
void editItem(wxTreeListItem aItem)
Method editItem Prompt the user for a new hotkey given a list item.
A class that contains a set of hotkeys, arranged into "sections" and provides some book-keeping funct...
Definition: hotkey_store.h:62
bool TransferDataToControl()
Method TransferDataToControl Load the hotkey data from the store into the control.
bool IsQuasiModal() const
Definition: dialog_shim.h:107
void onActivated(wxTreeListEvent &aEvent)
Method onActivated Handle activation of a row.
void onContextMenu(wxTreeListEvent &aEvent)
Method onContextMenu Handle right-click on a row.
void SaveAllHotkeys()
Persist all changes to hotkeys in the store to the underlying data structures.
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:83
wxString m_normalised_filter_str
ID_WHKL_MENU_IDS
Menu IDs for the hotkey context menu.
static wxKeyEvent PromptForKey(wxWindow *aParent, const wxString &aName, const wxString &aCurrentKey)
WIDGET_HOTKEY_CLIENT_DATA * getExpectedHkClientData(wxTreeListItem aItem)
Get the WIDGET_HOTKEY_CLIENT_DATA form an item and assert if it isn't found.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:98
HOTKEY_STORE & m_hk_store
void updateShownItems(const wxString &aFilterStr)
Method updateShownItems.
void updateFromClientData()
Method updateFromClientData Refresh the visible text on the widget from the rows' client data objects...
wxTreeListItem m_context_menu_item
Store the hotkey change data associated with each row.
void ResetAllHotkeysToDefault()
Reset every hotkey in the store to the default values.
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.
bool CheckKeyConflicts(TOOL_ACTION *aAction, long aKey, HOTKEY **aConflict)
Check whether the given key conflicts with anything in this store.
wxDataViewItem GetNextItem(wxDataViewCtrl const &aView, wxDataViewItem const &aItem)
Get the next item in list order.
void onMenu(wxCommandEvent &aEvent)
Method onMenu Handle activation of a context menu item.
void updateColumnWidths()
Recalculates column widths after model has changed.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
std::vector< TOOL_ACTION * > m_Actions
Definition: hotkey_store.h:36
void EndQuasiModal(int retCode)
bool FilterMatches(const HOTKEY &aHotkey) const
Check if the filter matches the given hotkey.
wxString GetLabel() const
Definition: tool_action.cpp:69
std::vector< HOTKEY_SECTION > & GetSections()
Get the list of sections managed by this store.
void EndFlexible(int aRtnCode)
End the dialog whether modal or quasimodal.
const char * name
Definition: DXF_plotter.cpp:59
void OnChar(wxKeyEvent &aEvent)
#define _(s)
Definition: 3d_actions.cpp:33
void OnCharHook(wxKeyEvent &aEvent) override
Represent a single user action.
Definition: tool_action.h:49
void ResetAllHotkeysToOriginal()
Resets every hotkey to the original values.
Class to manage logic for filtering hotkeys based on user input.
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
void resetItem(wxTreeListItem aItem, int aResetId)
Method resetItem Reset the item to either the default, the value when the dialog was opened,...
WIDGET_HOTKEY_CLIENT_DATA(HOTKEY &aChangedHotkey)
bool resolveKeyConflicts(TOOL_ACTION *aAction, long aKey)
Method resolveKeyConflicts Check if we can set a hotkey, and prompt the user if there is a conflict b...
int m_EditKeycode
Definition: hotkey_store.h:37
HOTKEY_FILTER(const wxString &aFilterStr)
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...
Dialog to prompt the user to enter a key.
void ResetAllHotkeys(bool aResetToDefault)
Set hotkeys in the control to default or original values.
static wxString GetSectionName(TOOL_ACTION *aAction)
bool TransferDataFromControl()
Method TransferDataFromControl Save the hotkey data from the control.