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 
59 class WIDGET_HOTKEY_CLIENT_DATA : public wxClientData
60 {
62  wxString m_section_tag;
63 
64 public:
65  WIDGET_HOTKEY_CLIENT_DATA( const EDA_HOTKEY& aHotkey, const wxString& aSectionTag )
66  : m_hotkey( aHotkey ), m_section_tag( aSectionTag )
67  {}
68 
69 
70  EDA_HOTKEY& GetHotkey() { return m_hotkey; }
71  const wxString& GetSectionTag() const { return m_section_tag; }
72 };
73 
74 
80 {
81  wxKeyEvent m_event;
82 
83 public:
84  HK_PROMPT_DIALOG( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
85  const wxString& aName, const wxString& aCurrentKey )
86  : DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
87  {
88  wxPanel* panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize );
89  wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
90 
91  /* Dialog layout:
92  *
93  * inst_label........................
94  * ----------------------------------
95  *
96  * cmd_label_0 cmd_label_1 \
97  * | fgsizer
98  * key_label_0 key_label_1 /
99  */
100 
101  wxStaticText* inst_label = new wxStaticText( panel, wxID_ANY, wxEmptyString,
102  wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL );
103 
104  inst_label->SetLabelText( _( "Press a new hotkey, or press Esc to cancel..." ) );
105  sizer->Add( inst_label, 0, wxALL, 5 );
106 
107  sizer->Add( new wxStaticLine( panel ), 0, wxALL | wxEXPAND, 2 );
108 
109  wxFlexGridSizer* fgsizer = new wxFlexGridSizer( 2 );
110 
111  wxStaticText* cmd_label_0 = new wxStaticText( panel, wxID_ANY, _( "Command:" ) );
112  fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
113 
114  wxStaticText* cmd_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
115  cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
116  cmd_label_1->SetLabel( aName );
117  fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
118 
119  wxStaticText* key_label_0 = new wxStaticText( panel, wxID_ANY, _( "Current key:" ) );
120  fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
121 
122  wxStaticText* key_label_1 = new wxStaticText( panel, wxID_ANY, wxEmptyString );
123  key_label_1->SetFont( key_label_1->GetFont().Bold() );
124  key_label_1->SetLabel( aCurrentKey );
125  fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
126 
127  sizer->Add( fgsizer, 1, wxEXPAND );
128 
129  // Wrap the sizer in a second to give a larger border around the whole dialog
130  wxBoxSizer* outer_sizer = new wxBoxSizer( wxVERTICAL );
131  outer_sizer->Add( sizer, 0, wxALL | wxEXPAND, 10 );
132  panel->SetSizer( outer_sizer );
133 
134  Layout();
135  outer_sizer->Fit( this );
136  Center();
137 
138  SetMinClientSize( GetClientSize() );
139 
140  // Binding both EVT_CHAR and EVT_CHAR_HOOK ensures that all key events,
141  // including specials like Tab and Return, are received, particularly
142  // on MSW.
143  panel->Bind( wxEVT_CHAR, &HK_PROMPT_DIALOG::OnChar, this );
144  panel->Bind( wxEVT_CHAR_HOOK, &HK_PROMPT_DIALOG::OnCharHook, this );
145  }
146 
147 
148  void OnCharHook( wxKeyEvent& aEvent )
149  {
150  // On certain platforms, EVT_CHAR_HOOK is the only handler that receives
151  // certain "special" keys. However, it doesn't always receive "normal"
152  // keys correctly. For example, with a US keyboard, it sees ? as shift+/.
153  //
154  // Untangling these incorrect keys would be too much trouble, so we bind
155  // both events, and simply skip the EVT_CHAR_HOOK if it receives a
156  // "normal" key.
157 
158  const enum wxKeyCode skipped_keys[] =
159  {
160  WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL,
161  WXK_NUMLOCK, WXK_SCROLL, WXK_RAW_CONTROL
162  };
163 
164  int key = aEvent.GetKeyCode();
165 
166  for( size_t i = 0; i < sizeof( skipped_keys ) / sizeof( skipped_keys[0] ); ++i )
167  {
168  if( key == skipped_keys[i] )
169  return;
170  }
171 
172  if( key <= 255 && isprint( key ) && !isspace( key ) )
173  {
174  // Let EVT_CHAR handle this one
175  aEvent.DoAllowNextEvent();
176 
177  // On Windows, wxEvent::Skip must NOT be called.
178  // On Linux and OSX, wxEvent::Skip MUST be called.
179  // No, I don't know why.
180 #ifndef __WXMSW__
181  aEvent.Skip();
182 #endif
183  }
184  else
185  {
186  OnChar( aEvent );
187  }
188  }
189 
190 
191  void OnChar( wxKeyEvent& aEvent )
192  {
193  m_event = aEvent;
194  EndFlexible( wxID_OK );
195  }
196 
197 
201  void EndFlexible( int aRtnCode )
202  {
203  if( IsQuasiModal() )
204  EndQuasiModal( aRtnCode );
205  else
206  EndModal( aRtnCode );
207  }
208 
209 
210  static wxKeyEvent PromptForKey( wxWindow* aParent, const wxString& aName,
211  const wxString& aCurrentKey )
212  {
213  HK_PROMPT_DIALOG dialog( aParent, wxID_ANY, _( "Set Hotkey" ), aName, aCurrentKey );
214 
215  if( dialog.ShowModal() == wxID_OK )
216  {
217  return dialog.m_event;
218  }
219  else
220  {
221  wxKeyEvent dummy;
222  return dummy;
223  }
224  }
225 };
226 
227 
229 {
230  if( aItem.IsOk() )
231  {
232  wxClientData* data = GetItemData( aItem );
233 
234  if( !data )
235  {
236  return NULL;
237  }
238  else
239  {
240  return static_cast<WIDGET_HOTKEY_CLIENT_DATA*>( data );
241  }
242  }
243  else
244  {
245  return NULL;
246  }
247 }
248 
249 
251 {
252  return GetHKClientData( GetSelection() );
253 }
254 
255 
257 {
258  for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
259  {
261 
262  if( hkdata )
263  {
264  EDA_HOTKEY& hk = hkdata->GetHotkey();
265 
266  SetItemText( i, 0, wxGetTranslation( hk.m_InfoMsg ) );
267  SetItemText( i, 1, KeyNameFromKeyCode( hk.m_KeyCode ) );
268  }
269  }
270 }
271 
272 
274 {
275  HOTKEY_LIST list;
276 
277  for( EDA_HOTKEY** info_ptr = aSection->m_HK_InfoList; *info_ptr; ++info_ptr )
278  {
279  list.push_back( **info_ptr );
280  }
281 
282  m_hotkeys.push_back( list );
283 }
284 
285 
286 void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
287 {
288  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
289 
290  if( !hkdata )
291  {
292  // Activated item was not a hotkey row
293  return;
294  }
295 
296  wxString name = GetItemText( aItem, 0 );
297  wxString current_key = GetItemText( aItem, 1 );
298 
299  wxKeyEvent key_event = HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key );
300  long key = MapKeypressToKeycode( key_event );
301 
302  if( hkdata && key )
303  {
304  // See if this key code is handled in hotkeys names list
305  bool exists;
306  KeyNameFromKeyCode( key, &exists );
307 
308  if( exists && hkdata->GetHotkey().m_KeyCode != key )
309  {
310  wxString tag = hkdata->GetSectionTag();
311  bool canUpdate = ResolveKeyConflicts( key, tag );
312 
313  if( canUpdate )
314  {
315  hkdata->GetHotkey().m_KeyCode = key;
316  }
317  }
318 
320 
321  // Trigger a resize in case column widths have changed
322  wxSizeEvent dummy_evt;
323  TWO_COLUMN_TREE_LIST::OnSize( dummy_evt );
324  }
325 }
326 
327 
328 void WIDGET_HOTKEY_LIST::ResetItem( wxTreeListItem aItem )
329 {
330  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
331  EDA_HOTKEY* hk = &hkdata->GetHotkey();
332 
333  for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index )
334  {
335  wxString& section_tag = *( m_sections[sec_index].m_section->m_SectionTag );
336 
337  if( section_tag != hkdata->GetSectionTag() )
338  continue;
339 
340  HOTKEY_LIST& each_list = m_hotkeys[sec_index];
341  HOTKEY_LIST::iterator hk_it;
342 
343  for( hk_it = each_list.begin(); hk_it != each_list.end(); ++hk_it )
344  {
345  if( hk_it->m_Idcommand == hk->m_Idcommand )
346  {
347  hk->m_KeyCode = hk_it->m_KeyCode;
348  break;
349  }
350  }
351  }
352 
354 }
355 
356 
357 void WIDGET_HOTKEY_LIST::ResetItemToDefault( wxTreeListItem aItem )
358 {
359  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
360  EDA_HOTKEY* hk = &hkdata->GetHotkey();
361  hk->ResetKeyCodeToDefault();
363 }
364 
365 
366 void WIDGET_HOTKEY_LIST::OnActivated( wxTreeListEvent& aEvent )
367 {
368  EditItem( aEvent.GetItem() );
369 }
370 
371 
372 void WIDGET_HOTKEY_LIST::OnContextMenu( wxTreeListEvent& aEvent )
373 {
374  // Save the active event for use in OnMenu
375  m_context_menu_item = aEvent.GetItem();
376 
377  wxMenu menu;
378 
379  menu.Append( ID_EDIT, _( "Edit..." ) );
380  menu.Append( ID_RESET, _( "Reset" ) );
381  menu.Append( ID_DEFAULT, _( "Default" ) );
382  menu.Append( wxID_SEPARATOR );
383  menu.Append( ID_RESET_ALL, _( "Reset all" ) );
384  menu.Append( ID_DEFAULT_ALL, _( "Reset all to default" ) );
385 
386  PopupMenu( &menu );
387 }
388 
389 
390 void WIDGET_HOTKEY_LIST::OnMenu( wxCommandEvent& aEvent )
391 {
392  switch( aEvent.GetId() )
393  {
394  case ID_EDIT:
396  break;
397 
398  case ID_RESET:
400  break;
401 
402  case ID_DEFAULT:
404  break;
405 
406  case ID_RESET_ALL:
408  break;
409 
410  case ID_DEFAULT_ALL:
412  break;
413 
414  default:
415  wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
416  }
417 }
418 
419 
420 bool WIDGET_HOTKEY_LIST::CheckKeyConflicts( long aKey, const wxString& aSectionTag,
421  EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect )
422 {
423  EDA_HOTKEY* conflicting_key = NULL;
424  struct EDA_HOTKEY_CONFIG* conflicting_section = NULL;
425 
426  for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
427  {
428  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item );
429 
430  if( !hkdata )
431  continue;
432 
433  EDA_HOTKEY& hk = hkdata->GetHotkey();
434  wxString tag = hkdata->GetSectionTag();
435 
436  if( aSectionTag != g_CommonSectionTag
437  && tag != g_CommonSectionTag
438  && tag != aSectionTag )
439  {
440  // This key and its conflict candidate are in orthogonal sections, so skip.
441  continue;
442  }
443 
444  if( aKey == hk.m_KeyCode )
445  {
446  conflicting_key = &hk;
447 
448  // Find the section
449  HOTKEY_SECTIONS::iterator it;
450 
451  for( it = m_sections.begin(); it != m_sections.end(); ++it )
452  {
453  if( *it->m_section->m_SectionTag == tag )
454  {
455  conflicting_section = it->m_section;
456  break;
457  }
458  }
459  }
460  }
461 
462  // Write the outparams
463  if( aConfKey )
464  *aConfKey = conflicting_key;
465 
466  if( aConfSect )
467  *aConfSect = conflicting_section;
468 
469  return conflicting_key == NULL;
470 }
471 
472 
473 bool WIDGET_HOTKEY_LIST::ResolveKeyConflicts( long aKey, const wxString& aSectionTag )
474 {
475  EDA_HOTKEY* conflicting_key = NULL;
476  EDA_HOTKEY_CONFIG* conflicting_section = NULL;
477 
478  CheckKeyConflicts( aKey, aSectionTag, &conflicting_key, &conflicting_section );
479 
480  if( conflicting_key != NULL )
481  {
482  wxString info = wxGetTranslation( conflicting_key->m_InfoMsg );
483  wxString msg = wxString::Format(
484  _( "<%s> is already assigned to \"%s\" in section \"%s\". Are you sure you want "
485  "to change its assignment?" ),
486  KeyNameFromKeyCode( aKey ), GetChars( info ),
487  *(conflicting_section->m_Title) );
488 
489  wxMessageDialog dlg( GetParent(), msg, _( "Confirm change" ), wxYES_NO | wxNO_DEFAULT );
490 
491  if( dlg.ShowModal() == wxID_YES )
492  {
493  conflicting_key->m_KeyCode = 0;
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, const HOTKEY_SECTIONS& aSections )
510  : TWO_COLUMN_TREE_LIST( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
511  m_sections( aSections )
512 {
513  AppendColumn( _( "Command" ) );
514  AppendColumn( _( "Hotkey" ) );
515  SetRubberBandColumn( 0 );
517 
518  Bind( wxEVT_TREELIST_ITEM_ACTIVATED, &WIDGET_HOTKEY_LIST::OnActivated, this );
519  Bind( wxEVT_TREELIST_ITEM_CONTEXT_MENU, &WIDGET_HOTKEY_LIST::OnContextMenu, this );
520  Bind( wxEVT_MENU, &WIDGET_HOTKEY_LIST::OnMenu, this );
521 }
522 
523 
525 {
526  HOTKEY_SECTIONS sections;
527 
528  for( EDA_HOTKEY_CONFIG* section = aHotkeys; section->m_HK_InfoList; ++section )
529  {
530  HOTKEY_SECTION sec;
531  sec.m_name = wxGetTranslation( *section->m_Title );
532  sec.m_section = section;
533  sections.push_back( sec );
534  }
535 
536  return sections;
537 }
538 
539 
540 void WIDGET_HOTKEY_LIST::InstallOnPanel( wxPanel* aPanel )
541 {
542  wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
543 
544  sizer->Add( this, 1, wxALL | wxEXPAND, 0 );
545  aPanel->SetSizer( sizer );
546 }
547 
548 
550 {
551  Freeze();
552 
553  for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
554  {
555  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item );
556  if( hkdata == NULL)
557  continue;
558 
559  hkdata->GetHotkey().ResetKeyCodeToDefault();
560  }
561 
563  Thaw();
564 
565  return true;
566 }
567 
568 
570 {
571  Freeze();
572  DeleteAllItems();
573  m_hotkeys.clear();
574 
575  for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index )
576  {
577  // LoadSection pushes into m_hotkeys
578  LoadSection( m_sections[sec_index].m_section );
579  wxASSERT( m_hotkeys.size() == sec_index + 1 );
580 
581  wxString section_tag = *( m_sections[sec_index].m_section->m_SectionTag );
582 
583  // Create parent tree item
584  wxTreeListItem parent = AppendItem( GetRootItem(), m_sections[sec_index].m_name );
585 
586  HOTKEY_LIST& each_list = m_hotkeys[sec_index];
587  HOTKEY_LIST::iterator hk_it;
588 
589  for( hk_it = each_list.begin(); hk_it != each_list.end(); ++hk_it )
590  {
591  wxTreeListItem item = AppendItem( parent, wxEmptyString );
592  SetItemData( item, new WIDGET_HOTKEY_CLIENT_DATA( &*hk_it, section_tag ) );
593  }
594 
595  Expand( parent );
596  }
597 
599  Thaw();
600 
601  return true;
602 }
603 
604 
606 {
607  for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index )
608  {
609  EDA_HOTKEY_CONFIG* section = m_sections[sec_index].m_section;
610 
611  for( EDA_HOTKEY** info_ptr = section->m_HK_InfoList; *info_ptr; ++info_ptr )
612  {
613  EDA_HOTKEY* info = *info_ptr;
614 
615  for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) )
616  {
617  WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item );
618 
619  if( !hkdata )
620  continue;
621 
622  EDA_HOTKEY& hk = hkdata->GetHotkey();
623 
624  if( hk.m_Idcommand == info->m_Idcommand )
625  {
626  info->m_KeyCode = hk.m_KeyCode;
627  break;
628  }
629  }
630  }
631  }
632 
633  return true;
634 }
635 
636 
637 long WIDGET_HOTKEY_LIST::MapKeypressToKeycode( const wxKeyEvent& aEvent )
638 {
639  long key = aEvent.GetKeyCode();
640 
641  if( key == WXK_ESCAPE )
642  {
643  return 0;
644  }
645  else
646  {
647  if( key >= 'a' && key <= 'z' ) // convert to uppercase
648  key = key + ('A' - 'a');
649 
650  // Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL)
651  // to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z'
652  if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
653  key += 'A' - 1;
654 
655  /* Disallow shift for keys that have two keycodes on them (e.g. number and
656  * punctuation keys) leaving only the "letter keys" of A-Z.
657  * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout)
658  * and Ctrl-( and Ctrl-5 (FR layout).
659  * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout
660  */
661  bool keyIsLetter = key >= 'A' && key <= 'Z';
662 
663  if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) )
664  key |= GR_KB_SHIFT;
665 
666  if( aEvent.ControlDown() )
667  key |= GR_KB_CTRL;
668 
669  if( aEvent.AltDown() )
670  key |= GR_KB_ALT;
671 
672  return key;
673  }
674 }
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)
void ResetKeyCodeToDefault()
Definition: hotkeys_basic.h:71
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:87
HOTKEY_SECTIONS m_sections
Modified wxTreeListCtrl designed for use with two columns, with better column resizing.
static wxDataViewItem GetNextItem(const wxDataViewCtrl &ctrl, const wxDataViewItem &item)
EDA_HOTKEY ** m_HK_InfoList
Definition: hotkeys_basic.h:91
void OnMenu(wxCommandEvent &aEvent)
Method OnMenu Handle activation of a context menu item.
bool TransferDataToControl()
Method TransferDataToControl Load the hotkey data into the control.
Class DIALOG_SHIM may sit in the inheritance tree between wxDialog and any class written by wxFormBui...
Definition: dialog_shim.h:60
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)
static const int HOTKEY_MIN_WIDTH
Minimum width of the hotkey column.
#define GR_KB_ALT
Definition: common.h:65
bool CheckKeyConflicts(long aKey, const wxString &aSectionTag, EDA_HOTKEY **aConfKey, EDA_HOTKEY_CONFIG **aConfSect)
Method CheckKeyConflicts Check whether the given key conflicts with anything in this WIDGET_HOTKEY_LI...
WIDGET_HOTKEY_CLIENT_DATA(const EDA_HOTKEY &aHotkey, const wxString &aSectionTag)
void UpdateFromClientData()
Method UpdateFromClientData Refresh the visible text on the widget from the rows' client data objects...
static HOTKEY_SECTIONS GenSections(EDA_HOTKEY_CONFIG *aHotkeys)
Static method GenSections Generate a list of sections and names from an EDA_HOTKEY_CONFIG*.
WIDGET_HOTKEY_CLIENT_DATA * GetSelHKClientData()
Method GetSelHKClientData Return the WIDGET_HOTKEY_CLIENT_DATA for the item being edited...
void SetClampedMinWidth(int aClampedMinWidth)
Set the minimum width of the non-rubber-band column.
std::vector< HOTKEY_LIST > m_hotkeys
void InstallOnPanel(wxPanel *aPanel)
Method InstallOnPanel Install this WIDGET_HOTKEY_LIST onto an empty panel.
wxTreeListItem m_context_menu_item
Class WIDGET_HOTKEY_CLIENT_DATA Stores the hotkey and section tag associated with each row...
#define GR_KB_SHIFT
Definition: common.h:66
bool IsQuasiModal()
Definition: dialog_shim.h:93
void LoadSection(EDA_HOTKEY_CONFIG *aSection)
Method LoadSection Generates a HOTKEY_LIST from the given hotkey configuration array and pushes it to...
void SetRubberBandColumn(int aRubberBandColumn)
Set the column number that will "rubber-band" (expand with available space).
std::vector< HOTKEY_SECTION > HOTKEY_SECTIONS
void EndQuasiModal(int retCode)
WIDGET_HOTKEY_LIST(wxWindow *aParent, const HOTKEY_SECTIONS &aSections)
Constructor WIDGET_HOTKEY_LIST Create a WIDGET_HOTKEY_LIST.
wxString m_InfoMsg
Definition: hotkeys_basic.h:64
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
class EDA_HOTKEY is a class to handle hot key commands.
Definition: hotkeys_basic.h:57
void EndFlexible(int aRtnCode)
End the dialog whether modal or quasimodal.
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:92
std::vector< EDA_HOTKEY > HOTKEY_LIST
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.
const wxString & GetSectionTag() const
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.
wxString g_CommonSectionTag
void EditItem(wxTreeListItem aItem)
Method EditItem Prompt the user for a new hotkey given a list item.
#define GR_KB_CTRL
Definition: common.h:64
EDA_HOTKEY_CONFIG * m_section
struct HOTKEY_SECTION Associates a hotkey configuration with a name.
bool TransferDefaultsToControl()
Method TransferDefaultsToControl Set hotkeys in the control to default values.
Class HK_PROMPT_DIALOG Dialog to prompt the user to enter a key.
void OnContextMenu(wxTreeListEvent &aEvent)
Method OnContextMenu Handle right-click on a row.
bool TransferDataFromControl()
Method TransferDataFromControl Save the hotkey data from the control.