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;
490 m_hk_store.CheckKeyConflicts( aAction, aKey, &conflictingHotKey );
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 ),
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 );
673printf(
"key %lX mod %X\n", key, aEvent.GetModifiers());
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 int mods = aEvent.GetModifiers();
698 if( ( mods & wxMOD_SHIFT ) && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
703 #if CAN_USE_ALTGR_KEY
704 if( wxmods & wxMOD_ALTGR )
709 if( mods & wxMOD_CONTROL )
712 if( mods & wxMOD_ALT )
717 if( mods & wxMOD_META )
722 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