diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 12f823ed9b..048ddf01a6 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories( BEFORE ${INC_BEFORE} ) include_directories( ./dialogs + ./widgets ./dialog_about ${CAIRO_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} @@ -144,6 +145,9 @@ set( COMMON_ABOUT_DLG_SRCS dialog_about/AboutDialog_main.cpp dialog_about/dialog_about.cpp dialog_about/dialog_about_base.cpp + ) + +set( COMMON_DLG_SRCS dialogs/dialog_display_info_HTML_base.cpp dialogs/dialog_exit_base.cpp dialogs/dialog_image_editor.cpp @@ -160,6 +164,10 @@ set( COMMON_ABOUT_DLG_SRCS dialogs/wx_html_report_panel.cpp ) +set( COMMON_WIDGET_SRCS + widgets/widget_hotkey_list.cpp + ) + set( COMMON_PAGE_LAYOUT_SRCS page_layout/title_block_shapes.cpp page_layout/class_worksheet_dataitem.cpp @@ -173,6 +181,8 @@ set( COMMON_PAGE_LAYOUT_SRCS set( COMMON_SRCS ${LIB_KICAD_SRCS} ${COMMON_ABOUT_DLG_SRCS} + ${COMMON_DLG_SRCS} + ${COMMON_WIDGET_SRCS} ${COMMON_PAGE_LAYOUT_SRCS} base_struct.cpp basicframe.cpp diff --git a/common/dialogs/dialog_hotkeys_editor.cpp b/common/dialogs/dialog_hotkeys_editor.cpp index fac42548ed..df1ce23002 100644 --- a/common/dialogs/dialog_hotkeys_editor.cpp +++ b/common/dialogs/dialog_hotkeys_editor.cpp @@ -21,352 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include - -#include -#include -#include -#include -#include - #include - -class DIALOG_HOTKEY_CLIENT_DATA : public wxClientData -{ - EDA_HOTKEY m_hotkey; - wxString m_section_tag; - -public: - DIALOG_HOTKEY_CLIENT_DATA( const EDA_HOTKEY& aHotkey, const wxString& aSectionTag ) - : m_hotkey( aHotkey ), m_section_tag( aSectionTag ) {} - - EDA_HOTKEY& GetHotkey() { return m_hotkey; } - wxString GetSectionTag() const { return m_section_tag; } -}; - - -HOTKEY_LIST_CTRL::HOTKEY_LIST_CTRL( wxWindow *aParent, const HOTKEYS_SECTIONS& aSections ) : - wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ), - m_sections( aSections ) -{ - AppendColumn( _( "Command" ) ); - AppendColumn( _( "Hotkey" ) ); - - Bind( wxEVT_CHAR, &HOTKEY_LIST_CTRL::OnChar, this ); - Bind( wxEVT_SIZE, &HOTKEY_LIST_CTRL::OnSize, this ); -} - - -HOTKEYS_SECTIONS HOTKEY_LIST_CTRL::Sections( EDA_HOTKEY_CONFIG* aHotkeys ) -{ - HOTKEYS_SECTIONS sections; - for( EDA_HOTKEY_CONFIG* section = aHotkeys; section->m_HK_InfoList; ++section ) - { - HOTKEYS_SECTION sec( wxGetTranslation( *section->m_Title ), section ); - sections.push_back( sec ); - } - return sections; -} - - -void HOTKEY_LIST_CTRL::OnSize( wxSizeEvent& aEvent ) -{ - // Handle this manually - wxTreeListCtrl screws up the width of the first column - wxDataViewCtrl* view = GetDataView(); - - if( !view ) - return; - - const wxRect rect = GetClientRect(); - view->SetSize( rect ); - -#ifdef wxHAS_GENERIC_DATAVIEWCTRL - { - wxWindow* const view = GetView(); - view->Refresh(); - view->Update(); - } -#endif - - SetColumnWidth( 1, 100 ); - SetColumnWidth( 0, rect.width - 130 ); -} - - -void HOTKEY_LIST_CTRL::DeselectRow( int aRow ) -{ - wxASSERT( aRow >= 0 ); - wxASSERT( (size_t)( aRow ) < m_items.size() ); - Unselect( m_items[aRow] ); -} - - -void HOTKEY_LIST_CTRL::OnChar( wxKeyEvent& aEvent ) -{ - DIALOG_HOTKEY_CLIENT_DATA* data = GetSelHKClientData(); - - if( data ) - { - long key = aEvent.GetKeyCode(); - - switch( key ) - { - case WXK_ESCAPE: - UnselectAll(); - break; - - default: - if( key >= 'a' && key <= 'z' ) // convert to uppercase - key = key + ('A' - 'a'); - - // Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL) - // to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z' - if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z ) - key += 'A' - 1; - - /* Disallow shift for keys that have two keycodes on them (e.g. number and - * punctuation keys) leaving only the "letter keys" of A-Z. - * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout) - * and Ctrl-( and Ctrl-5 (FR layout). - * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout - */ - bool keyIsLetter = key >= 'A' && key <= 'Z'; - - if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) ) - key |= GR_KB_SHIFT; - - if( aEvent.ControlDown() ) - key |= GR_KB_CTRL; - - if( aEvent.AltDown() ) - key |= GR_KB_ALT; - - // See if this key code is handled in hotkeys names list - bool exists; - KeyNameFromKeyCode( key, &exists ); - - if( exists && data->GetHotkey().m_KeyCode != key ) - { - wxString tag = data->GetSectionTag(); - bool canUpdate = ResolveKeyConflicts( key, tag ); - - if( canUpdate ) - { - data->GetHotkey().m_KeyCode = key; - } - - // Remove selection - UnselectAll(); - } - } - } - UpdateFromClientData(); -} - - -DIALOG_HOTKEY_CLIENT_DATA* HOTKEY_LIST_CTRL::GetSelHKClientData() -{ - return GetHKClientData( GetSelection() ); -} - - -DIALOG_HOTKEY_CLIENT_DATA* HOTKEY_LIST_CTRL::GetHKClientData( wxTreeListItem aItem ) -{ - if( aItem.IsOk() ) - { - wxClientData* data = GetItemData( aItem ); - if( !data ) - return NULL; - - DIALOG_HOTKEY_CLIENT_DATA* hkdata = static_cast( data ); - return hkdata; - } - else - { - return NULL; - } -} - - -void HOTKEY_LIST_CTRL::LoadSection( struct EDA_HOTKEY_CONFIG* aSection ) -{ - HOTKEY_LIST list; - EDA_HOTKEY** info_ptr; - - for( info_ptr = aSection->m_HK_InfoList; *info_ptr; info_ptr++ ) - { - EDA_HOTKEY info = **info_ptr; - list.push_back( info ); - } - - m_hotkeys.push_back( list ); -} - - -void HOTKEY_LIST_CTRL::UpdateFromClientData() -{ - for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) ) - { - DIALOG_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( i ); - if( !hkdata ) - continue; - - EDA_HOTKEY& hk = hkdata->GetHotkey(); - - wxString name = wxGetTranslation( hk.m_InfoMsg ); - wxString key = KeyNameFromKeyCode( hk.m_KeyCode ); - - SetItemText( i, 0, name ); - SetItemText( i, 1, key ); - } -} - - -bool HOTKEY_LIST_CTRL::TransferDataToControl() -{ - Freeze(); - DeleteAllItems(); - m_items.clear(); - m_hotkeys.clear(); - - HOTKEYS_SECTIONS::iterator sec_it; - size_t sec_index = 0; - for( sec_it = m_sections.begin(); sec_it != m_sections.end(); ++sec_it, ++sec_index ) - { - LoadSection( sec_it->second ); - wxString section_tag = *( sec_it->second->m_SectionTag ); - - // Create parent item - wxTreeListItem parent = AppendItem( GetRootItem(), sec_it->first ); - - HOTKEY_LIST& each_list = m_hotkeys[sec_index]; - HOTKEY_LIST::iterator hk_it; - for( hk_it = each_list.begin(); hk_it != each_list.end(); ++hk_it ) - { - wxTreeListItem item = AppendItem( parent, wxEmptyString ); - SetItemData( item, new DIALOG_HOTKEY_CLIENT_DATA( &*hk_it, section_tag ) ); - m_items.push_back( item ); - } - - Expand( parent ); - } - - UpdateFromClientData(); - Thaw(); - - return true; -} - - -bool HOTKEY_LIST_CTRL::TransferDataFromControl() -{ - for( size_t i_sec = 0; i_sec < m_sections.size(); ++i_sec ) - { - struct EDA_HOTKEY_CONFIG* section = m_sections[i_sec].second; - for( EDA_HOTKEY** info_ptr = section->m_HK_InfoList; *info_ptr; ++info_ptr ) - { - EDA_HOTKEY* info = *info_ptr; - for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) ) - { - DIALOG_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item ); - if( !hkdata ) - continue; - - EDA_HOTKEY& hk = hkdata->GetHotkey(); - if( hk.m_Idcommand == info->m_Idcommand ) - { - info->m_KeyCode = hk.m_KeyCode; - break; - } - } - } - } - return true; -} - - -bool HOTKEY_LIST_CTRL::ResolveKeyConflicts( long aKey, const wxString& aSectionTag ) -{ - EDA_HOTKEY* conflictingKey = NULL; - EDA_HOTKEY_CONFIG* conflictingSection = NULL; - - CheckKeyConflicts( aKey, aSectionTag, &conflictingKey, &conflictingSection ); - - if( conflictingKey != NULL ) - { - wxString info = wxGetTranslation( conflictingKey->m_InfoMsg ); - wxString msg = wxString::Format( - _( "<%s> is already assigned to \"%s\" in section \"%s\". Are you sure you want " - "to change its assignment?" ), - KeyNameFromKeyCode( aKey ), GetChars( info ), - *(conflictingSection->m_Title) ); - - wxMessageDialog dlg( GetParent(), msg, _( "Confirm change" ), wxYES_NO | wxNO_DEFAULT ); - - if( dlg.ShowModal() == wxID_YES ) - { - conflictingKey->m_KeyCode = 0; - UpdateFromClientData(); - return true; - } - else - { - return false; - } - } - - return true; -} - - -bool HOTKEY_LIST_CTRL::CheckKeyConflicts( long aKey, const wxString& aSectionTag, - EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect ) -{ - EDA_HOTKEY* conflictingKey = NULL; - struct EDA_HOTKEY_CONFIG* conflictingSection = NULL; - - for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) ) - { - DIALOG_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item ); - if( !hkdata ) - continue; - - EDA_HOTKEY& hk = hkdata->GetHotkey(); - wxString tag = hkdata->GetSectionTag(); - - if( aSectionTag != g_CommonSectionTag - && tag != g_CommonSectionTag - && tag != aSectionTag ) - continue; - - if( aKey == hk.m_KeyCode ) - { - conflictingKey = &hk; - - // Find the section - HOTKEYS_SECTIONS::iterator it; - for( it = m_sections.begin(); it != m_sections.end(); ++it ) - { - if( *it->second->m_SectionTag == tag ) - { - conflictingSection = it->second; - break; - } - } - } - } - - if( aConfKey ) - *aConfKey = conflictingKey; - - if( aConfSect ) - *aConfSect = conflictingSection; - - return conflictingKey == NULL; -} - - void InstallHotkeyFrame( EDA_BASE_FRAME* aParent, EDA_HOTKEY_CONFIG* aHotkeys ) { HOTKEYS_EDITOR_DIALOG dialog( aParent, aHotkeys ); @@ -385,7 +41,7 @@ HOTKEYS_EDITOR_DIALOG::HOTKEYS_EDITOR_DIALOG( EDA_BASE_FRAME* aParent, HOTKEYS_EDITOR_DIALOG_BASE( aParent ), m_hotkeys( aHotkeys ) { - m_hotkeyListCtrl = new HOTKEY_LIST_CTRL( this, HOTKEY_LIST_CTRL::Sections( aHotkeys ) ); + m_hotkeyListCtrl = new WIDGET_HOTKEY_LIST( this, WIDGET_HOTKEY_LIST::GenSections( aHotkeys ) ); m_mainSizer->Insert( 1, m_hotkeyListCtrl, wxSizerFlags( 1 ).Expand().Border( wxALL, 5 ) ); Layout(); diff --git a/common/widgets/widget_hotkey_list.cpp b/common/widgets/widget_hotkey_list.cpp new file mode 100644 index 0000000000..e995a01f7d --- /dev/null +++ b/common/widgets/widget_hotkey_list.cpp @@ -0,0 +1,371 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 Chris Pavlina + * Copyright (C) 2016 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include + +#include + + +/** + * Class WIDGET_HOTKEY_CLIENT_DATA + * Stores the hotkey and section tag associated with each row. To change a + * hotkey, edit it in the row's client data, then call WIDGET_HOTKEY_LIST::UpdateFromClientData(). + */ +class WIDGET_HOTKEY_CLIENT_DATA: public wxClientData +{ + EDA_HOTKEY m_hotkey; + wxString m_section_tag; + +public: + WIDGET_HOTKEY_CLIENT_DATA( const EDA_HOTKEY& aHotkey, const wxString& aSectionTag ) + : m_hotkey( aHotkey ), + m_section_tag( aSectionTag ) + { } + + EDA_HOTKEY& GetHotkey() { return m_hotkey; } + const wxString& GetSectionTag() const { return m_section_tag; } +}; + + +WIDGET_HOTKEY_CLIENT_DATA* WIDGET_HOTKEY_LIST::GetHKClientData( wxTreeListItem aItem ) +{ + if( aItem.IsOk() ) + { + wxClientData* data = GetItemData( aItem ); + if( !data ) + { + return NULL; + } + else + { + return static_cast( data ); + } + } + else + { + return NULL; + } +} + + +WIDGET_HOTKEY_CLIENT_DATA* WIDGET_HOTKEY_LIST::GetSelHKClientData() +{ + return GetHKClientData( GetSelection() ); +} + + +void WIDGET_HOTKEY_LIST::UpdateFromClientData() +{ + for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) ) + { + WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( i ); + + if( hkdata ) + { + EDA_HOTKEY& hk = hkdata->GetHotkey(); + + SetItemText( i, 0, wxGetTranslation( hk.m_InfoMsg ) ); + SetItemText( i, 1, KeyNameFromKeyCode( hk.m_KeyCode ) ); + } + } +} + + +void WIDGET_HOTKEY_LIST::LoadSection( EDA_HOTKEY_CONFIG* aSection ) +{ + HOTKEY_LIST list; + + for( EDA_HOTKEY** info_ptr = aSection->m_HK_InfoList; *info_ptr; ++info_ptr ) + { + list.push_back( **info_ptr ); + } + + m_hotkeys.push_back( list ); +} + + +void WIDGET_HOTKEY_LIST::OnChar( wxKeyEvent& aEvent ) +{ + WIDGET_HOTKEY_CLIENT_DATA* data = GetSelHKClientData(); + + if( data ) + { + long key = aEvent.GetKeyCode(); + + switch( key ) + { + case WXK_ESCAPE: + UnselectAll(); + break; + + default: + if( key >= 'a' && key <= 'z' ) // convert to uppercase + key = key + ('A' - 'a'); + + // Remap Ctrl A (=1+GR_KB_CTRL) to Ctrl Z(=26+GR_KB_CTRL) + // to GR_KB_CTRL+'A' .. GR_KB_CTRL+'Z' + if( aEvent.ControlDown() && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z ) + key += 'A' - 1; + + /* Disallow shift for keys that have two keycodes on them (e.g. number and + * punctuation keys) leaving only the "letter keys" of A-Z. + * Then, you can have, e.g. Ctrl-5 and Ctrl-% (GB layout) + * and Ctrl-( and Ctrl-5 (FR layout). + * Otherwise, you'd have to have to say Ctrl-Shift-5 on a FR layout + */ + bool keyIsLetter = key >= 'A' && key <= 'Z'; + + if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 ) ) + key |= GR_KB_SHIFT; + + if( aEvent.ControlDown() ) + key |= GR_KB_CTRL; + + if( aEvent.AltDown() ) + key |= GR_KB_ALT; + + // See if this key code is handled in hotkeys names list + bool exists; + KeyNameFromKeyCode( key, &exists ); + + if( exists && data->GetHotkey().m_KeyCode != key ) + { + wxString tag = data->GetSectionTag(); + bool canUpdate = ResolveKeyConflicts( key, tag ); + + if( canUpdate ) + { + data->GetHotkey().m_KeyCode = key; + } + + // Remove selection + UnselectAll(); + } + } + } + UpdateFromClientData(); +} + + +void WIDGET_HOTKEY_LIST::OnSize( wxSizeEvent& aEvent ) +{ + // Handle this manually - wxTreeListCtrl screws up the width of the first column + wxDataViewCtrl* view = GetDataView(); + + if( !view ) + return; + + wxRect rect = GetClientRect(); + view->SetSize( rect ); + +#ifdef wxHAS_GENERIC_DATAVIEWCTRL + { + wxWindow* view = GetView(); + view->Refresh(); + view->Update(); + } +#endif + + SetColumnWidth( 1, WIDGET_HOTKEY_LIST_HKCOLUMN_WIDTH ); + SetColumnWidth( 0, + rect.width - WIDGET_HOTKEY_LIST_HKCOLUMN_WIDTH - WIDGET_HOTKEY_LIST_HMARGIN ); +} + + +bool WIDGET_HOTKEY_LIST::CheckKeyConflicts( long aKey, const wxString& aSectionTag, + EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect ) +{ + EDA_HOTKEY* conflicting_key = NULL; + struct EDA_HOTKEY_CONFIG* conflicting_section = NULL; + + for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) ) + { + WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item ); + if( !hkdata ) + continue; + + EDA_HOTKEY& hk = hkdata->GetHotkey(); + wxString tag = hkdata->GetSectionTag(); + + if( aSectionTag != g_CommonSectionTag + && tag != g_CommonSectionTag + && tag != aSectionTag ) + { + // This key and its conflict candidate are in orthogonal sections, so skip. + continue; + } + + if( aKey == hk.m_KeyCode ) + { + conflicting_key = &hk; + + // Find the section + HOTKEY_SECTIONS::iterator it; + for( it = m_sections.begin(); it != m_sections.end(); ++it ) + { + if( *it->m_section->m_SectionTag == tag ) + { + conflicting_section = it->m_section; + break; + } + } + } + } + + // Write the outparams + if( aConfKey ) + *aConfKey = conflicting_key; + + if( aConfSect ) + *aConfSect = conflicting_section; + + return conflicting_key == NULL; +} + + +bool WIDGET_HOTKEY_LIST::ResolveKeyConflicts( long aKey, const wxString& aSectionTag ) +{ + EDA_HOTKEY* conflicting_key = NULL; + EDA_HOTKEY_CONFIG* conflicting_section = NULL; + + CheckKeyConflicts( aKey, aSectionTag, &conflicting_key, &conflicting_section ); + + if( conflicting_key != NULL ) + { + wxString info = wxGetTranslation( conflicting_key->m_InfoMsg ); + wxString msg = wxString::Format( + _( "<%s> is already assigned to \"%s\" in section \"%s\". Are you sure you want " + "to change its assignment?" ), + KeyNameFromKeyCode( aKey ), GetChars( info ), + *(conflicting_section->m_Title) ); + + wxMessageDialog dlg( GetParent(), msg, _( "Confirm change" ), wxYES_NO | wxNO_DEFAULT ); + + if( dlg.ShowModal() == wxID_YES ) + { + conflicting_key->m_KeyCode = 0; + UpdateFromClientData(); + return true; + } + else + { + return false; + } + } + else + { + return true; + } +} + + +WIDGET_HOTKEY_LIST::WIDGET_HOTKEY_LIST( wxWindow* aParent, const HOTKEY_SECTIONS& aSections ) + : wxTreeListCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTL_SINGLE ), + m_sections( aSections ) +{ + AppendColumn( _( "Command" ) ); + AppendColumn( _( "Hotkey" ) ); + + Bind( wxEVT_CHAR, &WIDGET_HOTKEY_LIST::OnChar, this ); + Bind( wxEVT_SIZE, &WIDGET_HOTKEY_LIST::OnSize, this ); +} + + +HOTKEY_SECTIONS WIDGET_HOTKEY_LIST::GenSections( EDA_HOTKEY_CONFIG* aHotkeys ) +{ + HOTKEY_SECTIONS sections; + for( EDA_HOTKEY_CONFIG* section = aHotkeys; section->m_HK_InfoList; ++section ) + { + HOTKEY_SECTION sec; + sec.m_name = wxGetTranslation( *section->m_Title ); + sec.m_section = section; + sections.push_back( sec ); + } + return sections; +} + + +bool WIDGET_HOTKEY_LIST::TransferDataToControl() +{ + Freeze(); + DeleteAllItems(); + m_hotkeys.clear(); + + for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index ) + { + // LoadSection pushes into m_hotkeys + LoadSection( m_sections[sec_index].m_section ); + wxASSERT( m_hotkeys.size() == sec_index + 1 ); + + wxString section_tag = *( m_sections[sec_index].m_section->m_SectionTag ); + + // Create parent tree item + wxTreeListItem parent = AppendItem( GetRootItem(), m_sections[sec_index].m_name ); + + HOTKEY_LIST& each_list = m_hotkeys[sec_index]; + HOTKEY_LIST::iterator hk_it; + for( hk_it = each_list.begin(); hk_it != each_list.end(); ++hk_it ) + { + wxTreeListItem item = AppendItem( parent, wxEmptyString ); + SetItemData( item, new WIDGET_HOTKEY_CLIENT_DATA( &*hk_it, section_tag ) ); + } + + Expand( parent ); + } + + UpdateFromClientData(); + Thaw(); + + return true; +} + + +bool WIDGET_HOTKEY_LIST::TransferDataFromControl() +{ + for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index ) + { + EDA_HOTKEY_CONFIG* section = m_sections[sec_index].m_section; + for( EDA_HOTKEY** info_ptr = section->m_HK_InfoList; *info_ptr; ++info_ptr ) + { + EDA_HOTKEY* info = *info_ptr; + for( wxTreeListItem item = GetFirstItem(); item.IsOk(); item = GetNextItem( item ) ) + { + WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( item ); + if( !hkdata ) + continue; + + EDA_HOTKEY& hk = hkdata->GetHotkey(); + if( hk.m_Idcommand == info->m_Idcommand ) + { + info->m_KeyCode = hk.m_KeyCode; + break; + } + } + } + } + + return true; +} diff --git a/eeschema/dialogs/dialog_eeschema_options.cpp b/eeschema/dialogs/dialog_eeschema_options.cpp index 2bd5b0547b..cf42ab9f42 100644 --- a/eeschema/dialogs/dialog_eeschema_options.cpp +++ b/eeschema/dialogs/dialog_eeschema_options.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include "../schframe.h" #include "hotkeys.h" @@ -65,8 +65,8 @@ DIALOG_EESCHEMA_OPTIONS::DIALOG_EESCHEMA_OPTIONS( SCH_EDIT_FRAME* parent ) : } // Embed the hotkeys list - HOTKEYS_SECTIONS sections = HOTKEY_LIST_CTRL::Sections( g_Eeschema_Hokeys_Descr ); - m_hotkeyListCtrl = new HOTKEY_LIST_CTRL( m_controlsPanel, sections ); + HOTKEY_SECTIONS sections = WIDGET_HOTKEY_LIST::GenSections( g_Eeschema_Hokeys_Descr ); + m_hotkeyListCtrl = new WIDGET_HOTKEY_LIST( m_controlsPanel, sections ); // Insert after the "Hotkeys:" label m_controlsSizer->Insert( 1, m_hotkeyListCtrl, wxSizerFlags( 1 ).Expand().Border( wxALL, 5 ) ); diff --git a/eeschema/dialogs/dialog_eeschema_options.h b/eeschema/dialogs/dialog_eeschema_options.h index 2afc07a198..146659bd4f 100644 --- a/eeschema/dialogs/dialog_eeschema_options.h +++ b/eeschema/dialogs/dialog_eeschema_options.h @@ -34,13 +34,13 @@ #include #include -class HOTKEY_LIST_CTRL; +class WIDGET_HOTKEY_LIST; class SCH_EDIT_FRAME; class DIALOG_EESCHEMA_OPTIONS : public DIALOG_EESCHEMA_OPTIONS_BASE { protected: - HOTKEY_LIST_CTRL* m_hotkeyListCtrl; + WIDGET_HOTKEY_LIST* m_hotkeyListCtrl; /** @brief The template fieldnames for this dialog */ TEMPLATE_FIELDNAMES templateFields; diff --git a/include/dialog_hotkeys_editor.h b/include/dialog_hotkeys_editor.h index ea7b3d3e02..801bea9aea 100644 --- a/include/dialog_hotkeys_editor.h +++ b/include/dialog_hotkeys_editor.h @@ -5,7 +5,7 @@ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 + * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -28,159 +28,9 @@ #ifndef __dialog_hotkeys_editor__ #define __dialog_hotkeys_editor__ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - #include -#include #include <../common/dialogs/dialog_hotkeys_editor_base.h> - -typedef std::pair HOTKEYS_SECTION; -typedef std::vector HOTKEYS_SECTIONS; - -typedef std::vector HOTKEY_LIST; - -class HOTKEYS_EDITOR_DIALOG; -class DIALOG_HOTKEY_CLIENT_DATA; - -/** - * Class HOTKEY_LIST_CTRL - * is a class to contain the contents of a hotkey editor tab page. - */ -class HOTKEY_LIST_CTRL : public wxTreeListCtrl -{ -public: - static HOTKEYS_SECTIONS Sections( EDA_HOTKEY_CONFIG* aHotkeys ); - - HOTKEY_LIST_CTRL( wxWindow* aParent, const HOTKEYS_SECTIONS& aSections ); - ~HOTKEY_LIST_CTRL() {}; - - /** - * Function DeselectRow - * Deselect the given row - * - * @param aRow is the row to deselect - */ - void DeselectRow( int aRow ); - - /** - * Function TransferDataToControl - * Load the hotkey data into the control. - * @return true iff the operation was successful - */ - bool TransferDataToControl(); - - /** - * Function TransferDataFromControl - * Save the hotkey data from the control. - * @return true iff the operation was successful - */ - bool TransferDataFromControl(); - - /** - * Function ResolveKeyConflicts - * Check if we can set a hotkey, this will prompt the user if there - * is a conflict between keys. The key code should have already been - * checked that it's not for the same entry as its currently in or else - * it'll prompt the change on itself. - * The function will do conflict detection depending on aSectionTag. - * g_CommonSectionTag means the key code must be checked with all sections. - * While other tags means the key code only must be checked with the aSectionTag - * section and g_CommonSectionTag section. - * - * @param aKey is the key code that wants to be set - * @param aSectionTag is the section tag that the key code came from - * - * @return True if the user accepted the overwrite or no conflict existed - */ - bool ResolveKeyConflicts( long aKey, const wxString& aSectionTag ); - - - /** - * Function CheckKeyConflicts - * Check whether the given key conflicts with anything in this HOTKEY_LIST_CTRL. - * - * @param aKey - key to check - * @param aSectionTag - section tag of the key - * @param aConfKey - if not NULL, outparam holding the key this one conflicts with - * @param aConfSect - if not NULL, outparam holding the section this one conflicts with - */ - bool CheckKeyConflicts( long aKey, const wxString& aSectionTag, - EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect ); - - /** - * Function UpdateFromClientData - * Update all visible items from the data stored in their client data objects. - */ - void UpdateFromClientData(); - -private: - HOTKEYS_SECTIONS m_sections; - std::vector< HOTKEY_LIST > m_hotkeys; - std::vector< wxTreeListItem > m_items; - - /** - * Function GetSelHKClientData - * Return the DIALOG_HOTKEY_CLIENT_DATA for the item being edited, or NULL if none is selected. - */ - DIALOG_HOTKEY_CLIENT_DATA* GetSelHKClientData(); - - /** - * Function GetHKClientData - * Return the DIALOG_HOTKEY_CLIENT_DATA for the given item, or NULL if invalid. - */ - DIALOG_HOTKEY_CLIENT_DATA* GetHKClientData( wxTreeListItem aItem ); - -protected: - /** - * Function LoadSection - * Generates a HOTKEY_LIST from the given hotkey configuration array and - * pushes it to m_hotkeys. - * - * @param aSection is a pointer to the hotkey configuration array - */ - void LoadSection( struct EDA_HOTKEY_CONFIG* aSection ); - - /** - * Function OnGetItemText - * Returns the requested row, column data to the list control. - * - * @param aRow is the row of the data which matches our hotkeys vector as a index - * @param aColumn is the column of the data which is either Command(0) or KeyCode(1) - * - * @return String containing the text for the specified row, column combination - */ - wxString OnGetItemText( long aRow, long aColumn ) const; - - /** - * Function OnChar - * Decoded key press handler which is used to set key codes in the list control - * - * @param aEvent is the key press event, the keycode is retrieved from it - */ - void OnChar( wxKeyEvent& aEvent ); - - /** - * Function OnSize - * Handle resizing of the control. Overrides the buggy wxTreeListCtrl::OnSize. - */ - void OnSize( wxSizeEvent& aEvent ); -}; - +#include /** * Class HOTKEYS_EDITOR_DIALOG @@ -192,7 +42,7 @@ class HOTKEYS_EDITOR_DIALOG : public HOTKEYS_EDITOR_DIALOG_BASE protected: struct EDA_HOTKEY_CONFIG* m_hotkeys; - HOTKEY_LIST_CTRL* m_hotkeyListCtrl; + WIDGET_HOTKEY_LIST* m_hotkeyListCtrl; bool TransferDataToWindow(); bool TransferDataFromWindow(); diff --git a/include/hotkeys_basic.h b/include/hotkeys_basic.h index a2dc77302d..089fcce479 100644 --- a/include/hotkeys_basic.h +++ b/include/hotkeys_basic.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2004-2016 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,6 +29,8 @@ #ifndef HOTKEYS_BASIC_H #define HOTKEYS_BASIC_H +#include + #define DEFAULT_HOTKEY_FILENAME_EXT wxT( "hotkeys" ) // A define to allow translation of Hot Key message Info in hotkey help menu diff --git a/include/widgets/widget_hotkey_list.h b/include/widgets/widget_hotkey_list.h new file mode 100644 index 0000000000..05573f2f85 --- /dev/null +++ b/include/widgets/widget_hotkey_list.h @@ -0,0 +1,170 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 Chris Pavlina + * Copyright (C) 2016 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file widget_hotkey_list + */ + +#ifndef __widget_hotkey_list__ +#define __widget_hotkey_list__ + +#include +#include + +#include + +#include + +/// Width of the hotkey list +const int WIDGET_HOTKEY_LIST_HKCOLUMN_WIDTH = 100; + +/// Extra margin to compensate for vertical scrollbar +const int WIDGET_HOTKEY_LIST_HMARGIN = 30; + +/** + * struct HOTKEY_SECTION + * Associates a hotkey configuration with a name. + */ +struct HOTKEY_SECTION +{ + wxString m_name; + EDA_HOTKEY_CONFIG* m_section; +}; + +typedef std::vector HOTKEY_SECTIONS; +typedef std::vector HOTKEY_LIST; + +class WIDGET_HOTKEY_CLIENT_DATA; + +class WIDGET_HOTKEY_LIST : public wxTreeListCtrl +{ + HOTKEY_SECTIONS m_sections; + std::vector m_hotkeys; + + /** + * Method GetHKClientData + * Return the WIDGET_HOTKEY_CLIENT_DATA for the given item, or NULL if the + * item is invalid. + */ + WIDGET_HOTKEY_CLIENT_DATA* GetHKClientData( wxTreeListItem aItem ); + + /** + * Method GetSelHKClientData + * Return the WIDGET_HOTKEY_CLIENT_DATA for the item being edited, or NULL if + * none is selected. + */ + WIDGET_HOTKEY_CLIENT_DATA* GetSelHKClientData(); + + /** + * Method UpdateFromClientData + * Refresh the visible text on the widget from the rows' client data objects. + */ + void UpdateFromClientData(); + +protected: + /** + * Method LoadSection + * Generates a HOTKEY_LIST from the given hotkey configuration array and pushes + * it to m_hotkeys. + */ + void LoadSection( EDA_HOTKEY_CONFIG* aSection ); + + /** + * Function OnChar + * Handle keypress. + * XXX REMOVE + */ + void OnChar( wxKeyEvent& aEvent ); + + /** + * Function OnSize + * Handle resizing of the control. Overrides the buggy wxTreeListCtrl::OnSize. + */ + void OnSize( wxSizeEvent& aEvent ); + + /** + * Method CheckKeyConflicts + * Check whether the given key conflicts with anything in this WIDGET_HOTKEY_LIST. + * + * @param aKey - key to check + * @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 aConfSect - if not NULL, outparam getting the section this one conflicts with + */ + bool CheckKeyConflicts( long aKey, const wxString& aSectionTag, + EDA_HOTKEY** aConfKey, EDA_HOTKEY_CONFIG** aConfSect ); + + /** + * Method ResolveKeyConflicts + * Check if we can set a hotkey, and prompt the user if there is a conflict between + * keys. The key code should already have been checked that it's not for the same + * entry as it's current in, or else this method will prompt for the self-change. + * + * The method will do conflict resolution depending on aSectionTag. + * g_CommonSectionTag means the key code must only be checkd with the aSectionTag + * section and g_CommonSectionTag section. + * + * @param aKey - key to check + * @param aSectionTag - section tag into which the key is proposed to be installed + * + * @return true iff the user accepted the overwrite or no conflict existed + */ + bool ResolveKeyConflicts( long aKey, const wxString& aSectionTag ); + +public: + /** + * Constructor WIDGET_HOTKEY_LIST + * Create a WIDGET_HOTKEY_LIST. + * + * @param aParent - parent widget + * @param aSections - list of the hotkey sections to display and their names. + * See WIDGET_HOTKEY_LIST::GenSections for a way to generate these easily + * from an EDA_HOTKEY_CONFIG*. + */ + WIDGET_HOTKEY_LIST( wxWindow* aParent, const HOTKEY_SECTIONS& aSections ); + + /** + * Static method GenSections + * Generate a list of sections and names from an EDA_HOTKEY_CONFIG*. Titles + * will be looked up from translations. + */ + static HOTKEY_SECTIONS GenSections( EDA_HOTKEY_CONFIG* aHotkeys ); + + /** + * Method TransferDataToControl + * Load the hotkey data into the control. It is safe to call this multiple times, + * for example to reset the control. + * @return true iff the operation was successful + */ + bool TransferDataToControl(); + + /** + * Method TransferDataFromControl + * Save the hotkey data from the control. + * @return true iff the operation was successful + */ + bool TransferDataFromControl(); +}; + +#endif // __widget_hotkey_list__