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, wxDefaultSize );
110 mainSizer->Add( panelDisplayCurrent, 0, wxALL | wxEXPAND, 5 );
112 wxFlexGridSizer* fgsizer =
new wxFlexGridSizer( 2 );
113 panelDisplayCurrent->SetSizer( fgsizer );
115 wxStaticText* cmd_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
_(
"Command:" ) );
116 fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
118 wxStaticText* cmd_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
119 cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
120 cmd_label_1->SetLabel( aName );
121 fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
123 wxStaticText* key_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
_(
"Current key:" ) );
124 fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
126 wxStaticText* key_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
127 key_label_1->SetFont( key_label_1->GetFont().Bold() );
128 key_label_1->SetLabel( aCurrentKey );
129 fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
131 fgsizer->AddStretchSpacer();
133 wxButton* resetButton =
new wxButton(
this, wxID_ANY,
_(
"Clear assigned hotkey" ) );
135 mainSizer->Add( resetButton, 0, wxALL | wxALIGN_CENTRE_HORIZONTAL, 5 );
138 mainSizer->Fit(
this );
141 SetMinClientSize( GetClientSize() );
154 static std::optional<long>
PromptForKey( wxWindow* aParent,
const wxString& aName,
155 const wxString& aCurrentKey )
157 HK_PROMPT_DIALOG dialog( aParent, wxID_ANY,
_(
"Set Hotkey" ), aName, aCurrentKey );
163 return std::make_optional( 0 );
170 return std::make_optional( key );
191 const enum wxKeyCode skipped_keys[] =
193 WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL, WXK_NUMLOCK, WXK_SCROLL,
197 int key = aEvent.GetKeyCode();
199 for( wxKeyCode skipped_key : skipped_keys )
201 if( key == skipped_key )
205 if( key <= 255 && isprint( key ) && !isspace( key ) )
208 aEvent.DoAllowNextEvent();
233 if(
m_event.GetEventType() != wxEVT_NULL )
236 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
243 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
275 const auto normedInfo = wxGetTranslation( aHotkey.
m_Actions[0]->GetFriendlyName() ).Upper();
298 wxClientData* data = GetItemData( aItem );
310 for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
317 wxString label = changed_hk.
m_Actions[ 0 ]->GetFriendlyName();
320 wxString description = changed_hk.
m_Actions[ 0 ]->GetDescription();
322 if( label.IsEmpty() )
323 label = changed_hk.
m_Actions[ 0 ]->GetName();
325 label.Replace( wxT(
"..." ), wxEmptyString );
326 label.Replace( wxT(
"…" ), wxEmptyString );
330 label += wxS(
" *" );
332 description.Replace( wxS(
"\n" ), wxS(
" " ) );
333 description.Replace( wxS(
"\r" ), wxS(
" " ) );
335 SetItemText( i, 0, label );
336 SetItemText( i, 1, key_text );
337 SetItemText( i, 2, alt_text );
338 SetItemText( i, 3, description );
370 wxString
name = GetItemText( aItem, 0 );
371 wxString current_key = aEditId ==
ID_EDIT_HOTKEY ? GetItemText( aItem, 1 )
372 : GetItemText( aItem, 2 );
377 if( key.has_value() )
383 wxString msg = wxString::Format(
_(
"'%s' is a reserved hotkey in KiCad and cannot "
449 menu.Append(
ID_RESET,
_(
"Undo Changes" ) );
450 menu.Append(
ID_CLEAR,
_(
"Clear Assigned Hotkey" ) );
451 menu.Append(
ID_CLEAR_ALT,
_(
"Clear Assigned Alternate" ) );
452 menu.Append(
ID_DEFAULT,
_(
"Restore Defaults" ) );
453 menu.Append( wxID_SEPARATOR );
462 switch( aEvent.GetId() )
477 wxFAIL_MSG( wxT(
"Unknown ID in context menu event" ) );
484 HOTKEY* conflictingHotKey =
nullptr;
486 m_hk_store.CheckKeyConflicts( aAction, aKey, &conflictingHotKey );
488 if( !conflictingHotKey )
492 wxString msg = wxString::Format(
_(
"'%s' is already assigned to '%s' in section '%s'. "
493 "Are you sure you want to change its assignment?" ),
498 wxMessageDialog dlg( GetParent(), msg,
_(
"Confirm change" ), wxYES_NO | wxNO_DEFAULT );
500 if( dlg.ShowModal() == wxID_YES )
513 wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
516 wxString command_header =
_(
"Command (double-click to edit)" );
518 AppendColumn( command_header, 450, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
519 AppendColumn(
_(
"Hotkey" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
520 AppendColumn(
_(
"Alternate" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
521 AppendColumn(
_(
"Description" ), 900, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
524#if defined( __WXGTK__ )
528 wxDataViewCtrl* dv = GetDataView();
530 wxString longKey = wxT(
"Ctrl+Alt+Shift+X" );
533 dv->GetColumn( 0 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 2 +
pad );
534 dv->GetColumn( 1 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
535 dv->GetColumn( 2 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
536 dv->GetColumn( 3 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 5 +
pad );
540 GetDataView()->Update();
544 std::vector<wxString> reserved_keys =
547 wxS(
"Ctrl+Shift+Tab" )
550 for(
const wxString& key : reserved_keys )
557 wxLogWarning( wxS(
"Unknown reserved keycode %s\n" ), key );
560 GetDataView()->SetIndent( 10 );
577 wxWindowUpdateLocker updateLock(
this );
582 if( aResetToDefault )
603 wxDataViewColumn* col = GetDataView()->GetColumn( 0 );
604 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
605 col->SetWidth( col->GetWidth() );
607 col = GetDataView()->GetColumn( 1 );
608 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
609 col->SetWidth( col->GetWidth() );
611 col = GetDataView()->GetColumn( 2 );
612 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
613 col->SetWidth( col->GetWidth() );
615 col = GetDataView()->GetColumn( 3 );
616 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
617 col->SetWidth( col->GetWidth() );
623 wxWindowUpdateLocker updateLock(
this );
632 wxTreeListItem parent = AppendItem( GetRootItem(), section.m_SectionName );
634 for(
HOTKEY& hotkey: section.m_HotKeys )
636 if(
filter.FilterMatches( hotkey ) )
638 wxTreeListItem item = AppendItem( parent, wxEmptyString );
659 long key = aEvent.GetKeyCode();
660 bool is_tab = aEvent.IsKeyInCategory( WXK_CATEGORY_TAB );
662 if( key == WXK_ESCAPE )
668 if( key >=
'a' && key <=
'z' )
669 key = key + (
'A' -
'a');
673 if( !is_tab && aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
682 bool keyIsLetter = key >=
'A' && key <=
'Z';
684 int mods = aEvent.GetModifiers();
686 if( ( mods & wxMOD_SHIFT ) && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
691 #if CAN_USE_ALTGR_KEY
692 if( wxmods & wxMOD_ALTGR )
697 if( mods & wxMOD_CONTROL )
700 if( mods & wxMOD_ALT )
705 if( mods & wxMOD_META )
710 if( mods & wxMOD_WIN )
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
DIALOG_SHIM(wxWindow *aParent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER, const wxString &name=wxDialogNameStr)
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...
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