34#include <wx/dcclient.h>
39#include <wx/statline.h>
40#include <wx/stattext.h>
41#include <wx/treelist.h>
42#include <wx/wupdlock.h>
84 const wxString& aName,
const wxString& aCurrentKey ) :
85 DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
87 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
88 SetSizer( mainSizer );
100 wxStaticText* inst_label =
new wxStaticText(
this, wxID_ANY, wxEmptyString,
101 wxDefaultPosition, wxDefaultSize,
102 wxALIGN_CENTRE_HORIZONTAL );
104 inst_label->SetLabelText(
_(
"Press a new hotkey, or press Esc to cancel..." ) );
105 mainSizer->Add( inst_label, 0, wxALL, 10 );
107 mainSizer->Add(
new wxStaticLine(
this ), 0, wxALL | wxEXPAND, 2 );
109 wxPanel* panelDisplayCurrent =
new wxPanel(
this, wxID_ANY, wxDefaultPosition,
111 mainSizer->Add( panelDisplayCurrent, 0, wxALL | wxEXPAND, 5 );
113 wxFlexGridSizer* fgsizer =
new wxFlexGridSizer( 2 );
114 panelDisplayCurrent->SetSizer( fgsizer );
116 wxStaticText* cmd_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
118 fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
120 wxStaticText* cmd_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
121 cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
122 cmd_label_1->SetLabel( aName );
123 fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
125 wxStaticText* key_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
126 _(
"Current key:" ) );
127 fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
129 wxStaticText* key_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
130 key_label_1->SetFont( key_label_1->GetFont().Bold() );
131 key_label_1->SetLabel( aCurrentKey );
132 fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
134 fgsizer->AddStretchSpacer();
136 wxButton* resetButton =
new wxButton(
this, wxID_ANY,
_(
"Clear assigned hotkey" ),
137 wxDefaultPosition, wxDefaultSize, 0 );
139 mainSizer->Add( resetButton, 0, wxALL | wxALIGN_CENTRE_HORIZONTAL, 5 );
142 mainSizer->Fit(
this );
145 SetMinClientSize( GetClientSize() );
158 static std::optional<long>
PromptForKey( wxWindow* aParent,
const wxString& aName,
159 const wxString& aCurrentKey )
161 HK_PROMPT_DIALOG dialog( aParent, wxID_ANY,
_(
"Set Hotkey" ), aName, aCurrentKey );
167 return std::make_optional( 0 );
174 return std::make_optional( key );
195 const enum wxKeyCode skipped_keys[] =
197 WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL, WXK_NUMLOCK, WXK_SCROLL,
201 int key = aEvent.GetKeyCode();
203 for( wxKeyCode skipped_key : skipped_keys )
205 if( key == skipped_key )
209 if( key <= 255 && isprint( key ) && !isspace( key ) )
212 aEvent.DoAllowNextEvent();
237 if(
m_event.GetEventType() != wxEVT_NULL )
240 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
247 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
279 const auto normedInfo = wxGetTranslation( aHotkey.
m_Actions[0]->GetFriendlyName() ).Upper();
302 wxClientData* data = GetItemData( aItem );
314 for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
321 wxString label = changed_hk.
m_Actions[ 0 ]->GetFriendlyName();
324 wxString description = changed_hk.
m_Actions[ 0 ]->GetDescription();
326 if( label.IsEmpty() )
327 label = changed_hk.
m_Actions[ 0 ]->GetName();
329 label.Replace( wxT(
"..." ), wxEmptyString );
330 label.Replace( wxT(
"…" ), wxEmptyString );
334 label += wxS(
" *" );
336 description.Replace( wxS(
"\n" ), wxS(
" " ) );
337 description.Replace( wxS(
"\r" ), wxS(
" " ) );
339 SetItemText( i, 0, label );
340 SetItemText( i, 1, key_text );
341 SetItemText( i, 2, alt_text );
342 SetItemText( i, 3, description );
374 wxString
name = GetItemText( aItem, 0 );
375 wxString current_key = aEditId ==
ID_EDIT_HOTKEY ? GetItemText( aItem, 1 )
376 : GetItemText( aItem, 2 );
381 if( key.has_value() )
387 wxString msg = wxString::Format(
_(
"'%s' is a reserved hotkey in KiCad and cannot "
453 menu.Append(
ID_RESET,
_(
"Undo Changes" ) );
454 menu.Append(
ID_CLEAR,
_(
"Clear Assigned Hotkey" ) );
455 menu.Append(
ID_CLEAR_ALT,
_(
"Clear Assigned Alternate" ) );
456 menu.Append(
ID_DEFAULT,
_(
"Restore Defaults" ) );
457 menu.Append( wxID_SEPARATOR );
466 switch( aEvent.GetId() )
481 wxFAIL_MSG( wxT(
"Unknown ID in context menu event" ) );
488 HOTKEY* conflictingHotKey =
nullptr;
492 if( !conflictingHotKey )
496 wxString msg = wxString::Format(
_(
"'%s' is already assigned to '%s' in section '%s'. "
497 "Are you sure you want to change its assignment?" ),
502 wxMessageDialog dlg( GetParent(), msg,
_(
"Confirm change" ), wxYES_NO | wxNO_DEFAULT );
504 if( dlg.ShowModal() == wxID_YES )
518 wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
519 m_hk_store( aHotkeyStore ),
520 m_readOnly( aReadOnly )
522 wxString command_header =
_(
"Command" );
525 command_header << wxS(
" " ) <<
_(
"(double-click to edit)" );
527 AppendColumn( command_header, 450, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
528 AppendColumn(
_(
"Hotkey" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
529 AppendColumn(
_(
"Alternate" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
530 AppendColumn(
_(
"Description" ), 900, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
533#if defined( __WXGTK__ )
537 wxDataViewCtrl* dv = GetDataView();
539 wxString longKey = wxT(
"Ctrl+Alt+Shift+X" );
542 dv->GetColumn( 0 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 2 +
pad );
543 dv->GetColumn( 1 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
544 dv->GetColumn( 2 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
545 dv->GetColumn( 3 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 5 +
pad );
549 GetDataView()->Update();
553 std::vector<wxString> reserved_keys =
556 wxS(
"Ctrl+Shift+Tab" )
559 for(
const wxString& key : reserved_keys )
566 wxLogWarning( wxS(
"Unknown reserved keycode %s\n" ), key );
569 GetDataView()->SetIndent( 10 );
589 wxWindowUpdateLocker updateLock(
this );
594 if( aResetToDefault )
615 wxDataViewColumn* col = GetDataView()->GetColumn( 0 );
616 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
617 col->SetWidth( col->GetWidth() );
619 col = GetDataView()->GetColumn( 1 );
620 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
621 col->SetWidth( col->GetWidth() );
623 col = GetDataView()->GetColumn( 2 );
624 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
625 col->SetWidth( col->GetWidth() );
627 col = GetDataView()->GetColumn( 3 );
628 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
629 col->SetWidth( col->GetWidth() );
635 wxWindowUpdateLocker updateLock(
this );
644 wxTreeListItem parent = AppendItem( GetRootItem(), section.m_SectionName );
646 for(
HOTKEY& hotkey: section.m_HotKeys )
648 if(
filter.FilterMatches( hotkey ) )
650 wxTreeListItem item = AppendItem( parent, wxEmptyString );
671 long key = aEvent.GetKeyCode();
672 bool is_tab = aEvent.IsKeyInCategory( WXK_CATEGORY_TAB );
674 if( key == WXK_ESCAPE )
680 if( key >=
'a' && key <=
'z' )
681 key = key + (
'A' -
'a');
685 if( !is_tab && aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
694 bool keyIsLetter = key >=
'A' && key <=
'Z';
696 if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
699 if( aEvent.ControlDown() )
702 if( aEvent.AltDown() )
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Dialog to prompt the user to enter a key.
static std::optional< long > PromptForKey(wxWindow *aParent, const wxString &aName, const wxString &aCurrentKey)
void OnCharHook(wxKeyEvent &aEvent) override
HK_PROMPT_DIALOG(wxWindow *aParent, wxWindowID aId, const wxString &aTitle, const wxString &aName, const wxString &aCurrentKey)
void OnKeyUp(wxKeyEvent &aEvent)
void onResetButton(wxCommandEvent &aEvent)
void OnChar(wxKeyEvent &aEvent)
Manage logic for filtering hotkeys based on user input.
wxString m_normalised_filter_str
bool FilterMatches(const HOTKEY &aHotkey) const
Check if the filter matches the given hotkey.
HOTKEY_FILTER(const wxString &aFilterStr)
A class that contains a set of hotkeys, arranged into "sections" and provides some book-keeping funct...
bool CheckKeyConflicts(TOOL_ACTION *aAction, long aKey, HOTKEY **aConflict)
Check whether the given key conflicts with anything in this store.
void ResetAllHotkeysToOriginal()
Resets every hotkey to the original values.
void ResetAllHotkeysToDefault()
Reset every hotkey in the store to the default values.
std::vector< HOTKEY_SECTION > & GetSections()
Get the list of sections managed by this store.
void SaveAllHotkeys()
Persist all changes to hotkeys in the store to the underlying data structures.
static wxString GetSectionName(TOOL_ACTION *aAction)
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
int KeyCodeFromKeyName(const wxString &keyname)
Return the key code from its user-friendly key name (ie: "Ctrl+M").
std::vector< TOOL_ACTION * > m_Actions