34#include <wx/dcclient.h>
37#include <wx/statline.h>
38#include <wx/stattext.h>
39#include <wx/treelist.h>
81 const wxString& aName,
const wxString& aCurrentKey ) :
82 DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
84 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
85 SetSizer( mainSizer );
97 wxStaticText* inst_label =
new wxStaticText(
this, wxID_ANY, wxEmptyString,
98 wxDefaultPosition, wxDefaultSize,
99 wxALIGN_CENTRE_HORIZONTAL );
101 inst_label->SetLabelText(
_(
"Press a new hotkey, or press Esc to cancel..." ) );
102 mainSizer->Add( inst_label, 0, wxALL, 10 );
104 mainSizer->Add(
new wxStaticLine(
this ), 0, wxALL | wxEXPAND, 2 );
106 wxPanel* panelDisplayCurrent =
new wxPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize );
107 mainSizer->Add( panelDisplayCurrent, 0, wxALL | wxEXPAND, 5 );
109 wxFlexGridSizer* fgsizer =
new wxFlexGridSizer( 2 );
110 panelDisplayCurrent->SetSizer( fgsizer );
112 wxStaticText* cmd_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
_(
"Command:" ) );
113 fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
115 wxStaticText* cmd_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
116 cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
117 cmd_label_1->SetLabel( aName );
118 fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
120 wxStaticText* key_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
_(
"Current key:" ) );
121 fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
123 wxStaticText* key_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
124 key_label_1->SetFont( key_label_1->GetFont().Bold() );
125 key_label_1->SetLabel( aCurrentKey );
126 fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
128 fgsizer->AddStretchSpacer();
130 wxButton* resetButton =
new wxButton(
this, wxID_ANY,
_(
"Clear assigned hotkey" ), wxDefaultPosition, wxDefaultSize, 0 );
132 mainSizer->Add( resetButton, 0, wxALL | wxALIGN_CENTRE_HORIZONTAL, 5 );
135 mainSizer->Fit(
this );
138 SetMinClientSize( GetClientSize() );
151 static std::optional<long>
PromptForKey( wxWindow* aParent,
const wxString& aName,
152 const wxString& aCurrentKey )
154 HK_PROMPT_DIALOG dialog( aParent, wxID_ANY,
_(
"Set Hotkey" ), aName, aCurrentKey );
156 if( dialog.ShowModal() == wxID_OK )
159 return std::make_optional( 0 );
165 return std::make_optional( key );
186 const enum wxKeyCode skipped_keys[] =
188 WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL, WXK_NUMLOCK, WXK_SCROLL,
192 int key = aEvent.GetKeyCode();
194 for( wxKeyCode skipped_key : skipped_keys )
196 if( key == skipped_key )
200 if( key <= 255 && isprint( key ) && !isspace( key ) )
203 aEvent.DoAllowNextEvent();
226 if(
m_event.GetEventType() != wxEVT_NULL )
229 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
236 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
268 const auto normedInfo = wxGetTranslation( aHotkey.
m_Actions[ 0 ]->GetFriendlyName() ).Upper();
291 wxClientData* data = GetItemData( aItem );
307 wxASSERT_MSG( hkdata !=
nullptr,
"No hotkey data found for list item" );
315 for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
322 wxString label = changed_hk.
m_Actions[ 0 ]->GetFriendlyName();
325 wxString description = changed_hk.
m_Actions[ 0 ]->GetDescription();
327 if( label.IsEmpty() )
328 label = changed_hk.
m_Actions[ 0 ]->GetName();
330 label.Replace( wxT(
"..." ), wxEmptyString );
331 label.Replace( wxT(
"…" ), wxEmptyString );
335 label += wxS(
" *" );
337 description.Replace( wxS(
"\n" ), wxS(
" " ) );
338 description.Replace( wxS(
"\r" ), wxS(
" " ) );
340 SetItemText( i, 0, label );
341 SetItemText( i, 1, key_text );
342 SetItemText( i, 2, alt_text );
343 SetItemText( i, 3, description );
375 wxString
name = GetItemText( aItem, 0 );
376 wxString current_key =
377 aEditId ==
ID_EDIT_HOTKEY ? GetItemText( aItem, 1 ) : GetItemText( aItem, 2 );
382 if( key.has_value() )
388 wxString msg = wxString::Format(
_(
"'%s' is a reserved hotkey in KiCad and cannot "
450 menu.Append(
ID_RESET,
_(
"Undo Changes" ) );
451 menu.Append(
ID_CLEAR,
_(
"Clear Assigned Hotkey" ) );
452 menu.Append(
ID_CLEAR_ALT,
_(
"Clear Assigned Alternate" ) );
453 menu.Append(
ID_DEFAULT,
_(
"Restore Defaults" ) );
454 menu.Append( wxID_SEPARATOR );
463 switch( aEvent.GetId() )
478 wxFAIL_MSG( wxT(
"Unknown ID in context menu event" ) );
485 HOTKEY* conflictingHotKey =
nullptr;
489 if( !conflictingHotKey )
493 wxString msg = wxString::Format(
_(
"'%s' is already assigned to '%s' in section '%s'. "
494 "Are you sure you want to change its assignment?" ),
499 wxMessageDialog dlg( GetParent(), msg,
_(
"Confirm change" ), wxYES_NO | wxNO_DEFAULT );
501 if( dlg.ShowModal() == wxID_YES )
515 wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
516 m_hk_store( aHotkeyStore ),
517 m_readOnly( aReadOnly )
519 wxString command_header =
_(
"Command" );
522 command_header << wxS(
" " ) <<
_(
"(double-click to edit)" );
524 AppendColumn( command_header, 450, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
525 AppendColumn(
_(
"Hotkey" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
526 AppendColumn(
_(
"Alternate" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
527 AppendColumn(
_(
"Description" ), 900, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
530#if defined( __WXGTK__ )
534 wxDataViewCtrl* dv = GetDataView();
536 wxString longKey = wxT(
"Ctrl+Alt+Shift+X" );
539 dv->GetColumn( 0 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 2 +
pad );
540 dv->GetColumn( 1 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
541 dv->GetColumn( 2 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
542 dv->GetColumn( 3 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 5 +
pad );
546 GetDataView()->Update();
550 std::vector<wxString> reserved_keys =
553 wxS(
"Ctrl+Shift+Tab" )
556 for(
const wxString& key : reserved_keys )
563 wxLogWarning( wxS(
"Unknown reserved keycode %s\n" ), key );
566 GetDataView()->SetIndent( 10 );
591 if( aResetToDefault )
614 wxDataViewColumn* col = GetDataView()->GetColumn( 0 );
615 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
616 col->SetWidth( col->GetWidth() );
618 col = GetDataView()->GetColumn( 1 );
619 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
620 col->SetWidth( col->GetWidth() );
622 col = GetDataView()->GetColumn( 2 );
623 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
624 col->SetWidth( col->GetWidth() );
626 col = GetDataView()->GetColumn( 3 );
627 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
628 col->SetWidth( col->GetWidth() );
642 wxTreeListItem parent = AppendItem( GetRootItem(), section.m_SectionName );
644 for(
HOTKEY& hotkey: section.m_HotKeys )
646 if(
filter.FilterMatches( hotkey ) )
648 wxTreeListItem item = AppendItem( parent, wxEmptyString );
670 long key = aEvent.GetKeyCode();
671 bool is_tab = aEvent.IsKeyInCategory( WXK_CATEGORY_TAB );
673 if( key == WXK_ESCAPE )
679 if( key >=
'a' && key <=
'z' )
680 key = key + (
'A' -
'a');
684 if( !is_tab && aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
693 bool keyIsLetter = key >=
'A' && key <=
'Z';
695 if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
698 if( aEvent.ControlDown() )
701 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