34#include <wx/dcclient.h>
39#include <wx/statline.h>
40#include <wx/stattext.h>
41#include <wx/treelist.h>
83 const wxString& aName,
const wxString& aCurrentKey ) :
84 DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
86 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
87 SetSizer( mainSizer );
99 wxStaticText* inst_label =
new wxStaticText(
this, wxID_ANY, wxEmptyString,
100 wxDefaultPosition, wxDefaultSize,
101 wxALIGN_CENTRE_HORIZONTAL );
103 inst_label->SetLabelText(
_(
"Press a new hotkey, or press Esc to cancel..." ) );
104 mainSizer->Add( inst_label, 0, wxALL, 10 );
106 mainSizer->Add(
new wxStaticLine(
this ), 0, wxALL | wxEXPAND, 2 );
108 wxPanel* panelDisplayCurrent =
new wxPanel(
this, wxID_ANY, wxDefaultPosition,
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,
117 fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
119 wxStaticText* cmd_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
120 cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
121 cmd_label_1->SetLabel( aName );
122 fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
124 wxStaticText* key_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
125 _(
"Current key:" ) );
126 fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
128 wxStaticText* key_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
129 key_label_1->SetFont( key_label_1->GetFont().Bold() );
130 key_label_1->SetLabel( aCurrentKey );
131 fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
133 fgsizer->AddStretchSpacer();
135 wxButton* resetButton =
new wxButton(
this, wxID_ANY,
_(
"Clear assigned hotkey" ),
136 wxDefaultPosition, wxDefaultSize, 0 );
138 mainSizer->Add( resetButton, 0, wxALL | wxALIGN_CENTRE_HORIZONTAL, 5 );
141 mainSizer->Fit(
this );
144 SetMinClientSize( GetClientSize() );
157 static std::optional<long>
PromptForKey( wxWindow* aParent,
const wxString& aName,
158 const wxString& aCurrentKey )
160 HK_PROMPT_DIALOG dialog( aParent, wxID_ANY,
_(
"Set Hotkey" ), aName, aCurrentKey );
166 return std::make_optional( 0 );
173 return std::make_optional( key );
194 const enum wxKeyCode skipped_keys[] =
196 WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL, WXK_NUMLOCK, WXK_SCROLL,
200 int key = aEvent.GetKeyCode();
202 for( wxKeyCode skipped_key : skipped_keys )
204 if( key == skipped_key )
208 if( key <= 255 && isprint( key ) && !isspace( key ) )
211 aEvent.DoAllowNextEvent();
236 if(
m_event.GetEventType() != wxEVT_NULL )
239 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
246 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
278 const auto normedInfo = wxGetTranslation( aHotkey.
m_Actions[0]->GetFriendlyName() ).Upper();
301 wxClientData* data = GetItemData( aItem );
313 for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
320 wxString label = changed_hk.
m_Actions[ 0 ]->GetFriendlyName();
323 wxString description = changed_hk.
m_Actions[ 0 ]->GetDescription();
325 if( label.IsEmpty() )
326 label = changed_hk.
m_Actions[ 0 ]->GetName();
328 label.Replace( wxT(
"..." ), wxEmptyString );
329 label.Replace( wxT(
"…" ), wxEmptyString );
333 label += wxS(
" *" );
335 description.Replace( wxS(
"\n" ), wxS(
" " ) );
336 description.Replace( wxS(
"\r" ), wxS(
" " ) );
338 SetItemText( i, 0, label );
339 SetItemText( i, 1, key_text );
340 SetItemText( i, 2, alt_text );
341 SetItemText( i, 3, description );
373 wxString
name = GetItemText( aItem, 0 );
374 wxString current_key = aEditId ==
ID_EDIT_HOTKEY ? GetItemText( aItem, 1 )
375 : GetItemText( aItem, 2 );
380 if( key.has_value() )
386 wxString msg = wxString::Format(
_(
"'%s' is a reserved hotkey in KiCad and cannot "
452 menu.Append(
ID_RESET,
_(
"Undo Changes" ) );
453 menu.Append(
ID_CLEAR,
_(
"Clear Assigned Hotkey" ) );
454 menu.Append(
ID_CLEAR_ALT,
_(
"Clear Assigned Alternate" ) );
455 menu.Append(
ID_DEFAULT,
_(
"Restore Defaults" ) );
456 menu.Append( wxID_SEPARATOR );
465 switch( aEvent.GetId() )
480 wxFAIL_MSG( wxT(
"Unknown ID in context menu event" ) );
487 HOTKEY* conflictingHotKey =
nullptr;
491 if( !conflictingHotKey )
495 wxString msg = wxString::Format(
_(
"'%s' is already assigned to '%s' in section '%s'. "
496 "Are you sure you want to change its assignment?" ),
501 wxMessageDialog dlg( GetParent(), msg,
_(
"Confirm change" ), wxYES_NO | wxNO_DEFAULT );
503 if( dlg.ShowModal() == wxID_YES )
517 wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
518 m_hk_store( aHotkeyStore ),
519 m_readOnly( aReadOnly )
521 wxString command_header =
_(
"Command" );
524 command_header << wxS(
" " ) <<
_(
"(double-click to edit)" );
526 AppendColumn( command_header, 450, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
527 AppendColumn(
_(
"Hotkey" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
528 AppendColumn(
_(
"Alternate" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
529 AppendColumn(
_(
"Description" ), 900, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
532#if defined( __WXGTK__ )
536 wxDataViewCtrl* dv = GetDataView();
538 wxString longKey = wxT(
"Ctrl+Alt+Shift+X" );
541 dv->GetColumn( 0 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 2 +
pad );
542 dv->GetColumn( 1 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
543 dv->GetColumn( 2 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
544 dv->GetColumn( 3 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 5 +
pad );
548 GetDataView()->Update();
552 std::vector<wxString> reserved_keys =
555 wxS(
"Ctrl+Shift+Tab" )
558 for(
const wxString& key : reserved_keys )
565 wxLogWarning( wxS(
"Unknown reserved keycode %s\n" ), key );
568 GetDataView()->SetIndent( 10 );
593 if( aResetToDefault )
616 wxDataViewColumn* col = GetDataView()->GetColumn( 0 );
617 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
618 col->SetWidth( col->GetWidth() );
620 col = GetDataView()->GetColumn( 1 );
621 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
622 col->SetWidth( col->GetWidth() );
624 col = GetDataView()->GetColumn( 2 );
625 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
626 col->SetWidth( col->GetWidth() );
628 col = GetDataView()->GetColumn( 3 );
629 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
630 col->SetWidth( col->GetWidth() );
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 );
672 long key = aEvent.GetKeyCode();
673 bool is_tab = aEvent.IsKeyInCategory( WXK_CATEGORY_TAB );
675 if( key == WXK_ESCAPE )
681 if( key >=
'a' && key <=
'z' )
682 key = key + (
'A' -
'a');
686 if( !is_tab && aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
695 bool keyIsLetter = key >=
'A' && key <=
'Z';
697 if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
700 if( aEvent.ControlDown() )
703 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