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, wxDefaultSize );
109 mainSizer->Add( panelDisplayCurrent, 0, wxALL | wxEXPAND, 5 );
111 wxFlexGridSizer* fgsizer =
new wxFlexGridSizer( 2 );
112 panelDisplayCurrent->SetSizer( fgsizer );
114 wxStaticText* cmd_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
_(
"Command:" ) );
115 fgsizer->Add( cmd_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
117 wxStaticText* cmd_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
118 cmd_label_1->SetFont( cmd_label_1->GetFont().Bold() );
119 cmd_label_1->SetLabel( aName );
120 fgsizer->Add( cmd_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
122 wxStaticText* key_label_0 =
new wxStaticText( panelDisplayCurrent, wxID_ANY,
_(
"Current key:" ) );
123 fgsizer->Add( key_label_0, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
125 wxStaticText* key_label_1 =
new wxStaticText( panelDisplayCurrent, wxID_ANY, wxEmptyString );
126 key_label_1->SetFont( key_label_1->GetFont().Bold() );
127 key_label_1->SetLabel( aCurrentKey );
128 fgsizer->Add( key_label_1, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5 );
130 fgsizer->AddStretchSpacer();
132 wxButton* resetButton =
new wxButton(
this, wxID_ANY,
_(
"Clear assigned hotkey" ), wxDefaultPosition, wxDefaultSize, 0 );
134 mainSizer->Add( resetButton, 0, wxALL | wxALIGN_CENTRE_HORIZONTAL, 5 );
137 mainSizer->Fit(
this );
140 SetMinClientSize( GetClientSize() );
153 static std::optional<long>
PromptForKey( wxWindow* aParent,
const wxString& aName,
154 const wxString& aCurrentKey )
156 HK_PROMPT_DIALOG dialog( aParent, wxID_ANY,
_(
"Set Hotkey" ), aName, aCurrentKey );
161 return std::make_optional( 0 );
167 return std::make_optional( key );
188 const enum wxKeyCode skipped_keys[] =
190 WXK_NONE, WXK_SHIFT, WXK_ALT, WXK_CONTROL, WXK_CAPITAL, WXK_NUMLOCK, WXK_SCROLL,
194 int key = aEvent.GetKeyCode();
196 for( wxKeyCode skipped_key : skipped_keys )
198 if( key == skipped_key )
202 if( key <= 255 && isprint( key ) && !isspace( key ) )
205 aEvent.DoAllowNextEvent();
230 if(
m_event.GetEventType() != wxEVT_NULL )
233 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
240 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
272 const auto normedInfo = wxGetTranslation( aHotkey.
m_Actions[ 0 ]->GetFriendlyName() ).Upper();
295 wxClientData* data = GetItemData( aItem );
311 wxASSERT_MSG( hkdata !=
nullptr,
"No hotkey data found for list item" );
319 for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
326 wxString label = changed_hk.
m_Actions[ 0 ]->GetFriendlyName();
329 wxString description = changed_hk.
m_Actions[ 0 ]->GetDescription();
331 if( label.IsEmpty() )
332 label = changed_hk.
m_Actions[ 0 ]->GetName();
334 label.Replace( wxT(
"..." ), wxEmptyString );
335 label.Replace( wxT(
"…" ), wxEmptyString );
339 label += wxS(
" *" );
341 description.Replace( wxS(
"\n" ), wxS(
" " ) );
342 description.Replace( wxS(
"\r" ), wxS(
" " ) );
344 SetItemText( i, 0, label );
345 SetItemText( i, 1, key_text );
346 SetItemText( i, 2, alt_text );
347 SetItemText( i, 3, description );
379 wxString
name = GetItemText( aItem, 0 );
380 wxString current_key =
381 aEditId ==
ID_EDIT_HOTKEY ? GetItemText( aItem, 1 ) : GetItemText( aItem, 2 );
386 if( key.has_value() )
392 wxString msg = wxString::Format(
_(
"'%s' is a reserved hotkey in KiCad and cannot "
454 menu.Append(
ID_RESET,
_(
"Undo Changes" ) );
455 menu.Append(
ID_CLEAR,
_(
"Clear Assigned Hotkey" ) );
456 menu.Append(
ID_CLEAR_ALT,
_(
"Clear Assigned Alternate" ) );
457 menu.Append(
ID_DEFAULT,
_(
"Restore Defaults" ) );
458 menu.Append( wxID_SEPARATOR );
467 switch( aEvent.GetId() )
482 wxFAIL_MSG( wxT(
"Unknown ID in context menu event" ) );
489 HOTKEY* conflictingHotKey =
nullptr;
493 if( !conflictingHotKey )
497 wxString msg = wxString::Format(
_(
"'%s' is already assigned to '%s' in section '%s'. "
498 "Are you sure you want to change its assignment?" ),
503 wxMessageDialog dlg( GetParent(), msg,
_(
"Confirm change" ), wxYES_NO | wxNO_DEFAULT );
505 if( dlg.ShowModal() == wxID_YES )
519 wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
520 m_hk_store( aHotkeyStore ),
521 m_readOnly( aReadOnly )
523 wxString command_header =
_(
"Command" );
526 command_header << wxS(
" " ) <<
_(
"(double-click to edit)" );
528 AppendColumn( command_header, 450, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
529 AppendColumn(
_(
"Hotkey" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
530 AppendColumn(
_(
"Alternate" ), 120, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
531 AppendColumn(
_(
"Description" ), 900, wxALIGN_LEFT, wxCOL_RESIZABLE | wxCOL_SORTABLE );
534#if defined( __WXGTK__ )
538 wxDataViewCtrl* dv = GetDataView();
540 wxString longKey = wxT(
"Ctrl+Alt+Shift+X" );
543 dv->GetColumn( 0 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 2 +
pad );
544 dv->GetColumn( 1 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
545 dv->GetColumn( 2 )->SetMinWidth( aParent->GetTextExtent( longKey ).x +
pad );
546 dv->GetColumn( 3 )->SetMinWidth( aParent->GetTextExtent( command_header ).x * 5 +
pad );
550 GetDataView()->Update();
554 std::vector<wxString> reserved_keys =
557 wxS(
"Ctrl+Shift+Tab" )
560 for(
const wxString& key : reserved_keys )
567 wxLogWarning( wxS(
"Unknown reserved keycode %s\n" ), key );
570 GetDataView()->SetIndent( 10 );
595 if( aResetToDefault )
618 wxDataViewColumn* col = GetDataView()->GetColumn( 0 );
619 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
620 col->SetWidth( col->GetWidth() );
622 col = GetDataView()->GetColumn( 1 );
623 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
624 col->SetWidth( col->GetWidth() );
626 col = GetDataView()->GetColumn( 2 );
627 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
628 col->SetWidth( col->GetWidth() );
630 col = GetDataView()->GetColumn( 3 );
631 col->SetWidth( wxCOL_WIDTH_AUTOSIZE );
632 col->SetWidth( col->GetWidth() );
646 wxTreeListItem parent = AppendItem( GetRootItem(), section.m_SectionName );
648 for(
HOTKEY& hotkey: section.m_HotKeys )
650 if(
filter.FilterMatches( hotkey ) )
652 wxTreeListItem item = AppendItem( parent, wxEmptyString );
674 long key = aEvent.GetKeyCode();
675 bool is_tab = aEvent.IsKeyInCategory( WXK_CATEGORY_TAB );
677 if( key == WXK_ESCAPE )
683 if( key >=
'a' && key <=
'z' )
684 key = key + (
'A' -
'a');
688 if( !is_tab && aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
697 bool keyIsLetter = key >=
'A' && key <=
'Z';
699 if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
702 if( aEvent.ControlDown() )
705 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