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();
228 if(
m_event.GetEventType() != wxEVT_NULL )
231 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
238 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
270 const auto normedInfo = wxGetTranslation( aHotkey.
m_Actions[ 0 ]->GetFriendlyName() ).Upper();
293 wxClientData* data = GetItemData( aItem );
309 wxASSERT_MSG( hkdata !=
nullptr,
"No hotkey data found for list item" );
317 for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
324 wxString label = changed_hk.
m_Actions[ 0 ]->GetFriendlyName();
327 wxString description = changed_hk.
m_Actions[ 0 ]->GetDescription();
329 if( label.IsEmpty() )
330 label = changed_hk.
m_Actions[ 0 ]->GetName();
332 label.Replace( wxT(
"..." ), wxEmptyString );
333 label.Replace( wxT(
"…" ), wxEmptyString );
337 label += wxS(
" *" );
339 description.Replace( wxS(
"\n" ), wxS(
" " ) );
340 description.Replace( wxS(
"\r" ), wxS(
" " ) );
342 SetItemText( i, 0, label );
343 SetItemText( i, 1, key_text );
344 SetItemText( i, 2, alt_text );
345 SetItemText( i, 3, description );
377 wxString
name = GetItemText( aItem, 0 );
378 wxString current_key =
379 aEditId ==
ID_EDIT_HOTKEY ? GetItemText( aItem, 1 ) : GetItemText( aItem, 2 );
384 if( key.has_value() )
390 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