Added hotkey validity checking to the preferences menu
This commit is contained in:
parent
cfa187f477
commit
2aa8e444ee
|
@ -21,13 +21,16 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <panel_hotkeys_editor.h>
|
#include <bitmaps.h>
|
||||||
|
#include <confirm.h>
|
||||||
#include <eda_base_frame.h>
|
#include <eda_base_frame.h>
|
||||||
|
#include <panel_hotkeys_editor.h>
|
||||||
|
|
||||||
#include <wx/srchctrl.h>
|
|
||||||
#include <wx/panel.h>
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
|
#include <wx/panel.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/srchctrl.h>
|
||||||
|
#include <wx/statline.h>
|
||||||
|
|
||||||
#include <widgets/button_row_panel.h>
|
#include <widgets/button_row_panel.h>
|
||||||
#include <widgets/ui_common.h>
|
#include <widgets/ui_common.h>
|
||||||
|
@ -70,7 +73,33 @@ PANEL_HOTKEYS_EDITOR::PANEL_HOTKEYS_EDITOR( EDA_BASE_FRAME* aFrame, wxWindow* aW
|
||||||
m_hotkeyStore( aShowHotkeys )
|
m_hotkeyStore( aShowHotkeys )
|
||||||
{
|
{
|
||||||
const auto margin = KIUI::GetStdMargin();
|
const auto margin = KIUI::GetStdMargin();
|
||||||
auto mainSizer = new wxBoxSizer( wxVERTICAL );
|
|
||||||
|
m_mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
m_errorMessageSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
// Setup the sub-sizer to contain the bitmap and header text
|
||||||
|
wxBoxSizer* errImgHeadSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
wxStaticBitmap* valid_img = new wxStaticBitmap(
|
||||||
|
this, wxID_ANY, KiBitmap( cancel_xpm ), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
wxStaticText* err_head = new wxStaticText( this, wxID_ANY, _( "Hotkey errors detected" ),
|
||||||
|
wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
|
||||||
|
errImgHeadSizer->Add( valid_img, 0, wxALL, 5 );
|
||||||
|
errImgHeadSizer->Add( err_head, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
|
||||||
|
m_errorMessageSizer->Add( errImgHeadSizer, 0, wxTOP | wxLEFT | wxRIGHT, margin );
|
||||||
|
|
||||||
|
// Setup the error message to give the user information about any problems with the hotkeys,
|
||||||
|
// but only do this if they can actually change them
|
||||||
|
if( !m_readOnly )
|
||||||
|
{
|
||||||
|
m_errorMessage = new wxStaticText(
|
||||||
|
this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
|
||||||
|
m_errorMessageSizer->Add( m_errorMessage, 0, wxALL, 5 );
|
||||||
|
}
|
||||||
|
m_errorMessageSizer->Add( new wxStaticLine( this ), 0, wxALL | wxEXPAND, 2 );
|
||||||
|
|
||||||
|
// Add the validity text to the main sizer and hide the entire sizer
|
||||||
|
m_mainSizer->Add( m_errorMessageSizer, 0, wxTOP | wxLEFT | wxRIGHT | wxEXPAND, margin );
|
||||||
|
|
||||||
// Sub-sizer for setting a wider side margin
|
// Sub-sizer for setting a wider side margin
|
||||||
// TODO: Can this be set by the parent widget- doesn't seem to be
|
// TODO: Can this be set by the parent widget- doesn't seem to be
|
||||||
|
@ -87,9 +116,9 @@ PANEL_HOTKEYS_EDITOR::PANEL_HOTKEYS_EDITOR( EDA_BASE_FRAME* aFrame, wxWindow* aW
|
||||||
if( !m_readOnly )
|
if( !m_readOnly )
|
||||||
installButtons( bMargins );
|
installButtons( bMargins );
|
||||||
|
|
||||||
mainSizer->Add( bMargins, 1, wxEXPAND | wxRIGHT | wxLEFT, side_margins );
|
m_mainSizer->Add( bMargins, 1, wxEXPAND | wxRIGHT | wxLEFT, side_margins );
|
||||||
|
|
||||||
this->SetSizer( mainSizer );
|
this->SetSizer( m_mainSizer );
|
||||||
this->Layout();
|
this->Layout();
|
||||||
|
|
||||||
// Connect Events
|
// Connect Events
|
||||||
|
@ -125,7 +154,7 @@ void PANEL_HOTKEYS_EDITOR::installButtons( wxSizer* aSizer )
|
||||||
_( "Import..." ),
|
_( "Import..." ),
|
||||||
_( "Import hotkey definitions from an external file, replacing the current values" ),
|
_( "Import hotkey definitions from an external file, replacing the current values" ),
|
||||||
[this]( wxCommandEvent& ){
|
[this]( wxCommandEvent& ){
|
||||||
m_frame->ImportHotkeyConfigFromFile( m_hotkeys, m_nickname );
|
onImportHotkeyConfigFromFile();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -144,6 +173,22 @@ void PANEL_HOTKEYS_EDITOR::installButtons( wxSizer* aSizer )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_HOTKEYS_EDITOR::onImportHotkeyConfigFromFile()
|
||||||
|
{
|
||||||
|
m_frame->ImportHotkeyConfigFromFile( m_hotkeys, m_nickname );
|
||||||
|
|
||||||
|
if( !m_hotkeyStore.TestStoreValidity() )
|
||||||
|
{
|
||||||
|
wxString msg = _( "The imported file contains invalid hotkeys. "
|
||||||
|
"Please correct the errors before continuing." );
|
||||||
|
|
||||||
|
wxString errKeys;
|
||||||
|
m_hotkeyStore.GetStoreValidityMessage( errKeys );
|
||||||
|
DisplayErrorMessage( this, msg, errKeys );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PANEL_HOTKEYS_EDITOR::TransferDataToWindow()
|
bool PANEL_HOTKEYS_EDITOR::TransferDataToWindow()
|
||||||
{
|
{
|
||||||
return m_hotkeyListCtrl->TransferDataToControl();
|
return m_hotkeyListCtrl->TransferDataToControl();
|
||||||
|
@ -167,3 +212,34 @@ void PANEL_HOTKEYS_EDITOR::OnFilterSearch( wxCommandEvent& aEvent )
|
||||||
const auto searchStr = aEvent.GetString();
|
const auto searchStr = aEvent.GetString();
|
||||||
m_hotkeyListCtrl->ApplyFilterString( searchStr );
|
m_hotkeyListCtrl->ApplyFilterString( searchStr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_HOTKEYS_EDITOR::UpdateErrorMessage()
|
||||||
|
{
|
||||||
|
wxString validMessage;
|
||||||
|
bool isValid = m_hotkeyStore.GetStoreValidityMessage( validMessage );
|
||||||
|
|
||||||
|
if( isValid )
|
||||||
|
{
|
||||||
|
// Hide the error message sizer if all the hotkeys are valid
|
||||||
|
if( !m_readOnly )
|
||||||
|
{
|
||||||
|
m_errorMessage->SetLabelText( wxEmptyString );
|
||||||
|
m_errorMessage->Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mainSizer->Hide( m_errorMessageSizer );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Update the message text and ensure it is showing if there are errors
|
||||||
|
if( !m_readOnly )
|
||||||
|
{
|
||||||
|
m_errorMessage->SetLabelText( validMessage );
|
||||||
|
m_errorMessage->Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mainSizer->Show( m_errorMessageSizer );
|
||||||
|
}
|
||||||
|
m_mainSizer->Layout();
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
HOTKEY_STORE::HOTKEY_STORE( EDA_HOTKEY_CONFIG* aHotkeys )
|
HOTKEY_STORE::HOTKEY_STORE( EDA_HOTKEY_CONFIG* aHotkeys )
|
||||||
{
|
{
|
||||||
|
m_isValid = false;
|
||||||
|
m_invalidityCauses = _( "Hotkeys not checked" );
|
||||||
|
|
||||||
for( EDA_HOTKEY_CONFIG* section = aHotkeys; section->m_HK_InfoList; ++section )
|
for( EDA_HOTKEY_CONFIG* section = aHotkeys; section->m_HK_InfoList; ++section )
|
||||||
{
|
{
|
||||||
m_hk_sections.push_back( genSection( *section ) );
|
m_hk_sections.push_back( genSection( *section ) );
|
||||||
|
@ -113,13 +116,13 @@ void HOTKEY_STORE::ResetAllHotkeysToOriginal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool HOTKEY_STORE::CheckKeyConflicts( long aKey, const wxString& aSectionTag,
|
bool HOTKEY_STORE::CheckKeyConflicts( long aKey, const wxString& aSectionTag, EDA_HOTKEY** aConfKey,
|
||||||
EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect )
|
EDA_HOTKEY_CONFIG** aConfSect, const int aIdCommand )
|
||||||
{
|
{
|
||||||
EDA_HOTKEY* conflicting_key = nullptr;
|
EDA_HOTKEY* conflicting_key = nullptr;
|
||||||
EDA_HOTKEY_CONFIG* conflicting_section = nullptr;
|
EDA_HOTKEY_CONFIG* conflicting_section = nullptr;
|
||||||
|
|
||||||
for( auto& section: m_hk_sections )
|
for( auto& section : m_hk_sections )
|
||||||
{
|
{
|
||||||
const auto& sectionTag = *section.m_section.m_SectionTag;
|
const auto& sectionTag = *section.m_section.m_SectionTag;
|
||||||
|
|
||||||
|
@ -135,7 +138,7 @@ bool HOTKEY_STORE::CheckKeyConflicts( long aKey, const wxString& aSectionTag,
|
||||||
for( auto& hotkey: section.m_hotkeys )
|
for( auto& hotkey: section.m_hotkeys )
|
||||||
{
|
{
|
||||||
auto& curr_hk = hotkey.GetCurrentValue();
|
auto& curr_hk = hotkey.GetCurrentValue();
|
||||||
if( aKey == curr_hk.m_KeyCode )
|
if( ( aKey == curr_hk.m_KeyCode ) && ( aIdCommand != curr_hk.m_Idcommand ) )
|
||||||
{
|
{
|
||||||
conflicting_key = &curr_hk;
|
conflicting_key = &curr_hk;
|
||||||
conflicting_section = §ion.m_section;
|
conflicting_section = §ion.m_section;
|
||||||
|
@ -151,4 +154,99 @@ bool HOTKEY_STORE::CheckKeyConflicts( long aKey, const wxString& aSectionTag,
|
||||||
*aConfSect = conflicting_section;
|
*aConfSect = conflicting_section;
|
||||||
|
|
||||||
return conflicting_key == nullptr;
|
return conflicting_key == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool HOTKEY_STORE::CheckKeyValidity( long aKey, wxString& aMessage )
|
||||||
|
{
|
||||||
|
// Extract the modifiers and the keycode
|
||||||
|
int modifiers = aKey & ( GR_KB_SHIFT | GR_KB_CTRL | GR_KB_ALT );
|
||||||
|
int keycode = aKey & 0x00FFFFFF;
|
||||||
|
|
||||||
|
// Hotkeys may not contain the shift+SYMBOL sequence.
|
||||||
|
// This sequence gets mapped to (UPPER SYMBOL) in the hotkey logic
|
||||||
|
if( modifiers & GR_KB_SHIFT )
|
||||||
|
{
|
||||||
|
// These catch the ASCII codes for the special characters
|
||||||
|
if( ( keycode <= 64 && keycode >= 32 ) ||
|
||||||
|
( keycode <= 96 && keycode >= 91 ) ||
|
||||||
|
( keycode <= 126 && keycode >= 123 ) )
|
||||||
|
{
|
||||||
|
aMessage = _( "A hotkey cannot contain the shift key and a symbol key." );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This code block can be used to test the key validity checks
|
||||||
|
#if 0
|
||||||
|
if( modifiers & GR_KB_CTRL )
|
||||||
|
{
|
||||||
|
if( keycode == 'K' )
|
||||||
|
{
|
||||||
|
aMessage = "A hotkey cannot be ctrl+K";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool HOTKEY_STORE::TestStoreValidity()
|
||||||
|
{
|
||||||
|
m_isValid = true;
|
||||||
|
m_invalidityCauses.Clear();
|
||||||
|
|
||||||
|
// Iterate over every key to test it
|
||||||
|
for( HOTKEY_SECTION& section : m_hk_sections )
|
||||||
|
{
|
||||||
|
for( CHANGED_HOTKEY& hotkey : section.m_hotkeys )
|
||||||
|
{
|
||||||
|
EDA_HOTKEY& curr_hk = hotkey.GetCurrentValue();
|
||||||
|
wxString validMessage;
|
||||||
|
|
||||||
|
bool isValid = CheckKeyValidity( curr_hk.m_KeyCode, validMessage );
|
||||||
|
|
||||||
|
// If the key isn't valid, set it and continue
|
||||||
|
if( !isValid )
|
||||||
|
{
|
||||||
|
hotkey.SetValidity( false, validMessage );
|
||||||
|
|
||||||
|
m_invalidityCauses << wxGetTranslation( curr_hk.m_InfoMsg );
|
||||||
|
m_invalidityCauses << ": " << validMessage << "\n";
|
||||||
|
m_isValid = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for duplication
|
||||||
|
const wxString& sectionTag = *section.m_section.m_SectionTag;
|
||||||
|
EDA_HOTKEY* conflicting_key = nullptr;
|
||||||
|
EDA_HOTKEY_CONFIG* conflicting_section = nullptr;
|
||||||
|
|
||||||
|
CheckKeyConflicts( curr_hk.m_KeyCode, sectionTag, &conflicting_key,
|
||||||
|
&conflicting_section, curr_hk.m_Idcommand );
|
||||||
|
|
||||||
|
// Not valid if a conflicting key was found
|
||||||
|
if( conflicting_key != nullptr )
|
||||||
|
{
|
||||||
|
wxString keyInfoMsg = wxGetTranslation( conflicting_key->m_InfoMsg );
|
||||||
|
validMessage =
|
||||||
|
wxString::Format( _( "Duplicate of hotkey for \"%s\"" ), keyInfoMsg );
|
||||||
|
|
||||||
|
hotkey.SetValidity( false, validMessage );
|
||||||
|
|
||||||
|
m_invalidityCauses << wxGetTranslation( curr_hk.m_InfoMsg );
|
||||||
|
m_invalidityCauses << ": " << validMessage << "\n";
|
||||||
|
m_isValid = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it made it this far, it is a valid hotkey
|
||||||
|
validMessage = _( "Hotkey is valid" );
|
||||||
|
hotkey.SetValidity( true, validMessage );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_isValid;
|
||||||
|
}
|
||||||
|
|
|
@ -28,8 +28,12 @@
|
||||||
|
|
||||||
#include <wx/statline.h>
|
#include <wx/statline.h>
|
||||||
|
|
||||||
#include <draw_frame.h>
|
#include <bitmaps.h>
|
||||||
|
#include <confirm.h>
|
||||||
#include <dialog_shim.h>
|
#include <dialog_shim.h>
|
||||||
|
#include <draw_frame.h>
|
||||||
|
|
||||||
|
#include <panel_hotkeys_editor.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,13 +84,17 @@ class HK_PROMPT_DIALOG : public DIALOG_SHIM
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HK_PROMPT_DIALOG( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
|
HK_PROMPT_DIALOG( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
|
||||||
const wxString& aName, const wxString& aCurrentKey )
|
const wxString& aName, const wxString& aCurrentKey, const bool aValidKey,
|
||||||
: DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
|
const wxString& aValidMessage )
|
||||||
|
: DIALOG_SHIM( aParent, aId, aTitle, wxDefaultPosition, wxDefaultSize )
|
||||||
{
|
{
|
||||||
wxPanel* panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize );
|
wxPanel* panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize );
|
||||||
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
|
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
/* Dialog layout:
|
/* Dialog layout:
|
||||||
|
*
|
||||||
|
* valid_img valid_label...........
|
||||||
|
* ----------------------------------
|
||||||
*
|
*
|
||||||
* inst_label........................
|
* inst_label........................
|
||||||
* ----------------------------------
|
* ----------------------------------
|
||||||
|
@ -96,6 +104,25 @@ public:
|
||||||
* key_label_0 key_label_1 /
|
* key_label_0 key_label_1 /
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// If there is a validity error, display the error message to the user
|
||||||
|
wxBoxSizer* valid_sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
if( !aValidKey )
|
||||||
|
{
|
||||||
|
wxStaticBitmap* valid_img = new wxStaticBitmap(
|
||||||
|
panel, wxID_ANY, KiBitmap( cancel_xpm ), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
valid_sizer->Add( valid_img, 0, wxALL, 5 );
|
||||||
|
|
||||||
|
wxStaticText* valid_label = new wxStaticText( panel, wxID_ANY, wxEmptyString,
|
||||||
|
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL );
|
||||||
|
|
||||||
|
valid_label->SetLabelText( aValidMessage );
|
||||||
|
valid_sizer->Add( valid_label, 0, wxALL, 5 );
|
||||||
|
|
||||||
|
// Add the validity text to the main sizer
|
||||||
|
sizer->Add( valid_sizer, 0, wxALL, 5 );
|
||||||
|
sizer->Add( new wxStaticLine( panel ), 0, wxALL | wxEXPAND, 2 );
|
||||||
|
}
|
||||||
|
|
||||||
wxStaticText* inst_label = new wxStaticText( panel, wxID_ANY, wxEmptyString,
|
wxStaticText* inst_label = new wxStaticText( panel, wxID_ANY, wxEmptyString,
|
||||||
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL );
|
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL );
|
||||||
|
|
||||||
|
@ -188,8 +215,21 @@ public:
|
||||||
|
|
||||||
void OnChar( wxKeyEvent& aEvent )
|
void OnChar( wxKeyEvent& aEvent )
|
||||||
{
|
{
|
||||||
m_event = aEvent;
|
int keyCode = WIDGET_HOTKEY_LIST::MapKeypressToKeycode( aEvent );
|
||||||
EndFlexible( wxID_OK );
|
|
||||||
|
// Test for if the key is valid
|
||||||
|
wxString validMsg;
|
||||||
|
if( HOTKEY_STORE::CheckKeyValidity( keyCode, validMsg ) )
|
||||||
|
{
|
||||||
|
// Valid key, close the window and return
|
||||||
|
m_event = aEvent;
|
||||||
|
EndFlexible( wxID_OK );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid key, tell the user
|
||||||
|
DisplayErrorMessage( this, validMsg, wxEmptyString );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,9 +246,10 @@ public:
|
||||||
|
|
||||||
|
|
||||||
static wxKeyEvent PromptForKey( wxWindow* aParent, const wxString& aName,
|
static wxKeyEvent PromptForKey( wxWindow* aParent, const wxString& aName,
|
||||||
const wxString& aCurrentKey )
|
const wxString& aCurrentKey, const wxString& aValidMessage, const bool aValidKey )
|
||||||
{
|
{
|
||||||
HK_PROMPT_DIALOG dialog( aParent, wxID_ANY, _( "Set Hotkey" ), aName, aCurrentKey );
|
HK_PROMPT_DIALOG dialog( aParent, wxID_ANY, _( "Set Hotkey" ), aName, aCurrentKey,
|
||||||
|
aValidKey, aValidMessage );
|
||||||
|
|
||||||
if( dialog.ShowModal() == wxID_OK )
|
if( dialog.ShowModal() == wxID_OK )
|
||||||
{
|
{
|
||||||
|
@ -311,6 +352,9 @@ WIDGET_HOTKEY_CLIENT_DATA* WIDGET_HOTKEY_LIST::getExpectedHkClientData( wxTreeLi
|
||||||
|
|
||||||
void WIDGET_HOTKEY_LIST::UpdateFromClientData()
|
void WIDGET_HOTKEY_LIST::UpdateFromClientData()
|
||||||
{
|
{
|
||||||
|
// Run a validity check on the hotkey store before updating
|
||||||
|
m_hk_store.TestStoreValidity();
|
||||||
|
|
||||||
for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
|
for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
|
||||||
{
|
{
|
||||||
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( i );
|
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( i );
|
||||||
|
@ -328,12 +372,22 @@ void WIDGET_HOTKEY_LIST::UpdateFromClientData()
|
||||||
|
|
||||||
SetItemText( i, 0, wxGetTranslation( hk.m_InfoMsg ) );
|
SetItemText( i, 0, wxGetTranslation( hk.m_InfoMsg ) );
|
||||||
SetItemText( i, 1, key_text);
|
SetItemText( i, 1, key_text);
|
||||||
|
|
||||||
|
// Add the image to the column if the item is invalid
|
||||||
|
if( changed_hk.IsValid() )
|
||||||
|
SetItemImage( i, NO_IMAGE, NO_IMAGE );
|
||||||
|
else
|
||||||
|
SetItemImage( i, 0, NO_IMAGE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger a resize in case column widths have changed
|
// Trigger a resize in case column widths have changed
|
||||||
wxSizeEvent dummy_evt;
|
wxSizeEvent dummy_evt;
|
||||||
TWO_COLUMN_TREE_LIST::OnSize( dummy_evt );
|
TWO_COLUMN_TREE_LIST::OnSize( dummy_evt );
|
||||||
|
|
||||||
|
// Update the panel's error message if it exists
|
||||||
|
if( m_parentPanel )
|
||||||
|
m_parentPanel->UpdateErrorMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,8 +421,11 @@ void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
|
||||||
|
|
||||||
wxString name = GetItemText( aItem, 0 );
|
wxString name = GetItemText( aItem, 0 );
|
||||||
wxString current_key = GetItemText( aItem, 1 );
|
wxString current_key = GetItemText( aItem, 1 );
|
||||||
|
wxString valid_msg;
|
||||||
|
|
||||||
wxKeyEvent key_event = HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key );
|
bool valid_key = hkdata->GetChangedHotkey().IsValid( valid_msg );
|
||||||
|
wxKeyEvent key_event =
|
||||||
|
HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key, valid_msg, valid_key );
|
||||||
long key = MapKeypressToKeycode( key_event );
|
long key = MapKeypressToKeycode( key_event );
|
||||||
|
|
||||||
if( key )
|
if( key )
|
||||||
|
@ -506,11 +563,29 @@ bool WIDGET_HOTKEY_LIST::ResolveKeyConflicts( long aKey, const wxString& aSectio
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST( wxWindow* aParent, HOTKEY_STORE& aHotkeyStore,
|
WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST(
|
||||||
bool aReadOnly )
|
PANEL_HOTKEYS_EDITOR* aParent, HOTKEY_STORE& aHotkeyStore, bool aReadOnly )
|
||||||
: TWO_COLUMN_TREE_LIST( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
|
: TWO_COLUMN_TREE_LIST( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
|
||||||
m_hk_store( aHotkeyStore ),
|
m_hk_store( aHotkeyStore ),
|
||||||
m_readOnly( aReadOnly )
|
m_readOnly( aReadOnly ),
|
||||||
|
m_parentPanel( aParent )
|
||||||
|
{
|
||||||
|
initializeElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST(
|
||||||
|
wxWindow* aParent, HOTKEY_STORE& aHotkeyStore, bool aReadOnly )
|
||||||
|
: TWO_COLUMN_TREE_LIST( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ),
|
||||||
|
m_hk_store( aHotkeyStore ),
|
||||||
|
m_readOnly( aReadOnly ),
|
||||||
|
m_parentPanel( nullptr )
|
||||||
|
{
|
||||||
|
initializeElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WIDGET_HOTKEY_LIST::initializeElements()
|
||||||
{
|
{
|
||||||
wxString command_header = _( "Command" );
|
wxString command_header = _( "Command" );
|
||||||
|
|
||||||
|
@ -522,6 +597,11 @@ WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST( wxWindow* aParent, HOTKEY_STORE& aHotkey
|
||||||
SetRubberBandColumn( 0 );
|
SetRubberBandColumn( 0 );
|
||||||
SetClampedMinWidth( HOTKEY_MIN_WIDTH );
|
SetClampedMinWidth( HOTKEY_MIN_WIDTH );
|
||||||
|
|
||||||
|
// Add the image for invalid hotkey
|
||||||
|
m_imgList = new wxImageList();
|
||||||
|
m_imgList->Add( KiBitmap( cancel_xpm ) );
|
||||||
|
AssignImageList( m_imgList );
|
||||||
|
|
||||||
if( !m_readOnly )
|
if( !m_readOnly )
|
||||||
{
|
{
|
||||||
// The event only apply if the widget is in editable mode
|
// The event only apply if the widget is in editable mode
|
||||||
|
@ -531,7 +611,6 @@ WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST( wxWindow* aParent, HOTKEY_STORE& aHotkey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WIDGET_HOTKEY_LIST::ApplyFilterString( const wxString& aFilterStr )
|
void WIDGET_HOTKEY_LIST::ApplyFilterString( const wxString& aFilterStr )
|
||||||
{
|
{
|
||||||
updateShownItems( aFilterStr );
|
updateShownItems( aFilterStr );
|
||||||
|
@ -556,6 +635,12 @@ void WIDGET_HOTKEY_LIST::ResetAllHotkeys( bool aResetToDefault )
|
||||||
|
|
||||||
UpdateFromClientData();
|
UpdateFromClientData();
|
||||||
Thaw();
|
Thaw();
|
||||||
|
|
||||||
|
// Update the panel's error message if it exists
|
||||||
|
// Call here again since the freeze/thaw seems to disrupt the update
|
||||||
|
// inside UpdateFromClientData
|
||||||
|
if( m_parentPanel )
|
||||||
|
m_parentPanel->UpdateErrorMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -592,6 +677,12 @@ void WIDGET_HOTKEY_LIST::updateShownItems( const wxString& aFilterStr )
|
||||||
|
|
||||||
UpdateFromClientData();
|
UpdateFromClientData();
|
||||||
Thaw();
|
Thaw();
|
||||||
|
|
||||||
|
// Update the panel's error message if it exists
|
||||||
|
// Call here again since the freeze/thaw seems to disrupt the update
|
||||||
|
// inside UpdateFromClientData
|
||||||
|
if( m_parentPanel )
|
||||||
|
m_parentPanel->UpdateErrorMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,10 @@ public:
|
||||||
m_orig( aHotkey ),
|
m_orig( aHotkey ),
|
||||||
m_changed( aHotkey ),
|
m_changed( aHotkey ),
|
||||||
m_tag( aTag )
|
m_tag( aTag )
|
||||||
{}
|
{
|
||||||
|
m_isValid = false;
|
||||||
|
m_validMessage = _( "Hotkey never verified" );
|
||||||
|
}
|
||||||
|
|
||||||
EDA_HOTKEY& GetCurrentValue()
|
EDA_HOTKEY& GetCurrentValue()
|
||||||
{
|
{
|
||||||
|
@ -88,6 +91,40 @@ public:
|
||||||
return m_tag;
|
return m_tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this hotkey has been flagged as invalid
|
||||||
|
*
|
||||||
|
* @param aMessage - If invalid, contains a string giving the reason for being invalid
|
||||||
|
* @return - true if valid, false otherwise
|
||||||
|
*/
|
||||||
|
bool IsValid( wxString& aMessage ) const
|
||||||
|
{
|
||||||
|
aMessage = m_validMessage;
|
||||||
|
return m_isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this hotkey has been flagged as invalid
|
||||||
|
*
|
||||||
|
* @return - true if valid, false otherwise
|
||||||
|
*/
|
||||||
|
bool IsValid() const
|
||||||
|
{
|
||||||
|
return m_isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if this hotkey is valid
|
||||||
|
*
|
||||||
|
* @param aValid - Flag giving true if valid, false otherwise
|
||||||
|
* @param amessage - Reason for being invalid (empty if hotkey is valid)
|
||||||
|
*/
|
||||||
|
void SetValidity( bool aValid, wxString& aMessage )
|
||||||
|
{
|
||||||
|
m_isValid = aValid;
|
||||||
|
m_validMessage = aMessage;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Reference to an "original" hotkey config
|
// Reference to an "original" hotkey config
|
||||||
EDA_HOTKEY& m_orig;
|
EDA_HOTKEY& m_orig;
|
||||||
|
@ -98,6 +135,11 @@ private:
|
||||||
// The hotkey section tag, used to spot conflicts
|
// The hotkey section tag, used to spot conflicts
|
||||||
const wxString& m_tag;
|
const wxString& m_tag;
|
||||||
|
|
||||||
|
// True if the key is a valid hotkey (has no invalid combinations)
|
||||||
|
bool m_isValid;
|
||||||
|
|
||||||
|
// Reason for being invalid
|
||||||
|
wxString m_validMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -162,15 +204,48 @@ public:
|
||||||
void ResetAllHotkeysToOriginal();
|
void ResetAllHotkeysToOriginal();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given key conflicts with anything in this store.
|
* Check whether the given key conflicts with anything in this store. If a command ID is
|
||||||
|
* specified, then the conflict will only trigger if the conflicting hotkey is for
|
||||||
|
* a different command ID.
|
||||||
*
|
*
|
||||||
* @param aKey - key to check
|
* @param aKey - key to check
|
||||||
* @param aSectionTag - section tag into which the key is proposed to be installed
|
* @param aSectionTag - section tag into which the key is proposed to be installed
|
||||||
* @param aConfKey - if not NULL, outparam getting the key this one conflicts with
|
* @param aConfKey - if not NULL, outparam getting the key this one conflicts with
|
||||||
* @param aConfSect - if not NULL, outparam getting the section this one conflicts with
|
* @param aConfSect - if not NULL, outparam getting the section this one conflicts with
|
||||||
|
* @param aIdCommand - Optional command ID for the key being tested
|
||||||
*/
|
*/
|
||||||
bool CheckKeyConflicts( long aKey, const wxString& aSectionTag,
|
bool CheckKeyConflicts( long aKey, const wxString& aSectionTag, EDA_HOTKEY** aConfKey,
|
||||||
EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect );
|
EDA_HOTKEY_CONFIG** aConfSect, const int aIdCommand = -1 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given key contains only valid key combinations
|
||||||
|
*
|
||||||
|
* @param aKey - The key to check
|
||||||
|
* @param aMessage - If invalid, the outparam containing the message explaining the invalidity
|
||||||
|
* @return - true if valid, false if invalid
|
||||||
|
*/
|
||||||
|
static bool CheckKeyValidity( long aKey, wxString& aMessage );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test all hotkeys in the hotkey store for validity and conflicts with other keys
|
||||||
|
*/
|
||||||
|
bool TestStoreValidity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string containing all the errors detected during the validity test
|
||||||
|
* It is formatted as:
|
||||||
|
* Action name 1: Reason key is invalid
|
||||||
|
* Action name 2: Reason key is invalid
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* @param aMessage - outparam to store the message in
|
||||||
|
* @return true if no errors detected
|
||||||
|
*/
|
||||||
|
bool GetStoreValidityMessage( wxString& aMessage )
|
||||||
|
{
|
||||||
|
aMessage = m_invalidityCauses;
|
||||||
|
return m_isValid;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -182,6 +257,12 @@ private:
|
||||||
|
|
||||||
// Internal data for every hotkey passed in
|
// Internal data for every hotkey passed in
|
||||||
SECTION_LIST m_hk_sections;
|
SECTION_LIST m_hk_sections;
|
||||||
|
|
||||||
|
// String containing information on the causes of invalidity for the entire store
|
||||||
|
wxString m_invalidityCauses;
|
||||||
|
|
||||||
|
// Is the store valid
|
||||||
|
bool m_isValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HOTKEY_STORE__H
|
#endif // HOTKEY_STORE__H
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
class wxPanel;
|
class wxPanel;
|
||||||
class wxSizer;
|
class wxSizer;
|
||||||
|
class WIDGET_HOTKEY_LIST;
|
||||||
|
|
||||||
|
|
||||||
class PANEL_HOTKEYS_EDITOR : public wxPanel
|
class PANEL_HOTKEYS_EDITOR : public wxPanel
|
||||||
|
@ -47,6 +48,10 @@ protected:
|
||||||
HOTKEY_STORE m_hotkeyStore;
|
HOTKEY_STORE m_hotkeyStore;
|
||||||
WIDGET_HOTKEY_LIST* m_hotkeyListCtrl;
|
WIDGET_HOTKEY_LIST* m_hotkeyListCtrl;
|
||||||
|
|
||||||
|
wxBoxSizer* m_mainSizer;
|
||||||
|
wxBoxSizer* m_errorMessageSizer;
|
||||||
|
wxStaticText* m_errorMessage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PANEL_HOTKEYS_EDITOR( EDA_BASE_FRAME* aFrame, wxWindow* aWindow, bool aReadOnly,
|
PANEL_HOTKEYS_EDITOR( EDA_BASE_FRAME* aFrame, wxWindow* aWindow, bool aReadOnly,
|
||||||
EDA_HOTKEY_CONFIG* aHotkeys, EDA_HOTKEY_CONFIG* aShowHotkeys,
|
EDA_HOTKEY_CONFIG* aHotkeys, EDA_HOTKEY_CONFIG* aShowHotkeys,
|
||||||
|
@ -55,7 +60,22 @@ public:
|
||||||
bool TransferDataToWindow() override;
|
bool TransferDataToWindow() override;
|
||||||
bool TransferDataFromWindow() override;
|
bool TransferDataFromWindow() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the error message display on the panel with the new messages.
|
||||||
|
*/
|
||||||
|
void UpdateErrorMessage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Initialize the elements of the panel.
|
||||||
|
*/
|
||||||
|
void initializeElements();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import hotkey configuration data from a file and verify the validity of the
|
||||||
|
* imported keys. Then prompt the user with the results.
|
||||||
|
*/
|
||||||
|
void onImportHotkeyConfigFromFile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install the button panel (global reset/default, import/export)
|
* Install the button panel (global reset/default, import/export)
|
||||||
|
|
|
@ -35,11 +35,13 @@
|
||||||
#include <wx/treelist.h>
|
#include <wx/treelist.h>
|
||||||
#include <widgets/two_column_tree_list.h>
|
#include <widgets/two_column_tree_list.h>
|
||||||
|
|
||||||
#include <hotkeys_basic.h>
|
|
||||||
#include <hotkey_store.h>
|
#include <hotkey_store.h>
|
||||||
|
#include <hotkeys_basic.h>
|
||||||
|
#include <panel_hotkeys_editor.h>
|
||||||
|
|
||||||
|
|
||||||
class WIDGET_HOTKEY_CLIENT_DATA;
|
class WIDGET_HOTKEY_CLIENT_DATA;
|
||||||
|
class PANEL_HOTKEYS_EDITOR;
|
||||||
|
|
||||||
class WIDGET_HOTKEY_LIST : public TWO_COLUMN_TREE_LIST
|
class WIDGET_HOTKEY_LIST : public TWO_COLUMN_TREE_LIST
|
||||||
{
|
{
|
||||||
|
@ -47,6 +49,8 @@ class WIDGET_HOTKEY_LIST : public TWO_COLUMN_TREE_LIST
|
||||||
bool m_readOnly;
|
bool m_readOnly;
|
||||||
|
|
||||||
wxTreeListItem m_context_menu_item;
|
wxTreeListItem m_context_menu_item;
|
||||||
|
wxImageList* m_imgList;
|
||||||
|
PANEL_HOTKEYS_EDITOR* m_parentPanel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method GetHKClientData
|
* Method GetHKClientData
|
||||||
|
@ -164,9 +168,22 @@ public:
|
||||||
* @param aParent - parent widget
|
* @param aParent - parent widget
|
||||||
* @param aHotkeys - EDA_HOTKEY_CONFIG data - a hotkey store is constructed
|
* @param aHotkeys - EDA_HOTKEY_CONFIG data - a hotkey store is constructed
|
||||||
* from this.
|
* from this.
|
||||||
|
* @param aReadOnly - true disallows edits of the hotkeys
|
||||||
*/
|
*/
|
||||||
WIDGET_HOTKEY_LIST( wxWindow* aParent, HOTKEY_STORE& aHotkeyStore, bool aReadOnly );
|
WIDGET_HOTKEY_LIST( wxWindow* aParent, HOTKEY_STORE& aHotkeyStore, bool aReadOnly );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor WIDGET_HOTKEY_LIST
|
||||||
|
* Create a WIDGET_HOTKEY_LIST that will update the panel's error message when
|
||||||
|
* new validity messages are available.
|
||||||
|
*
|
||||||
|
* @param aParent - parent hotkey panel
|
||||||
|
* @param aHotkeys - EDA_HOTKEY_CONFIG data - a hotkey store is constructed
|
||||||
|
* from this.
|
||||||
|
* @param aReadOnly - true disallows edits of the hotkeys
|
||||||
|
*/
|
||||||
|
WIDGET_HOTKEY_LIST( PANEL_HOTKEYS_EDITOR* aParent, HOTKEY_STORE& aHotkeyStore, bool aReadOnly );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method ApplyFilterString
|
* Method ApplyFilterString
|
||||||
* Apply a filter string to the hotkey list, selecting which hotkeys
|
* Apply a filter string to the hotkey list, selecting which hotkeys
|
||||||
|
@ -202,6 +219,12 @@ public:
|
||||||
* Map a keypress event to the correct key code for use as a hotkey.
|
* Map a keypress event to the correct key code for use as a hotkey.
|
||||||
*/
|
*/
|
||||||
static long MapKeypressToKeycode( const wxKeyEvent& aEvent );
|
static long MapKeypressToKeycode( const wxKeyEvent& aEvent );
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Initialize the elements of the widget
|
||||||
|
*/
|
||||||
|
void initializeElements();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __widget_hotkey_list__
|
#endif // __widget_hotkey_list__
|
||||||
|
|
Loading…
Reference in New Issue