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