From bfe4f85b992097abc6099167684f8fa1540b4e93 Mon Sep 17 00:00:00 2001
From: jean-pierre charras <jp.charras@wanadoo.fr>
Date: Sun, 29 Aug 2010 18:36:52 +0200
Subject: [PATCH] Fixed some issues in hotkeys editor

---
 common/dialog_hotkeys_editor.cpp      | 87 +++++++++++++++++++++++----
 common/dialog_hotkeys_editor_base.cpp | 28 +++++----
 common/dialog_hotkeys_editor_base.fbp | 16 ++---
 common/dialog_hotkeys_editor_base.h   |  5 +-
 common/hotkeys_basic.cpp              | 16 +++--
 include/dialog_hotkeys_editor.h       |  5 +-
 include/hotkeys_basic.h               |  9 +++
 7 files changed, 124 insertions(+), 42 deletions(-)

diff --git a/common/dialog_hotkeys_editor.cpp b/common/dialog_hotkeys_editor.cpp
index 01346fb60e..7b2525db28 100644
--- a/common/dialog_hotkeys_editor.cpp
+++ b/common/dialog_hotkeys_editor.cpp
@@ -1,12 +1,34 @@
-#include <wx/tooltip.h>
+/*
+dialog_hotkeys_editor.cpp
+*/
+/*
+ * This program source code file is part of KICAD, a free EDA CAD application.
+ *
+ * Copyright (C) 1992-2010 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
+ * as published by the Free Software Foundation; either version 2
+ * 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 <algorithm>
 
 #include "fctsys.h"
 #include "appl_wxstruct.h"
-#include "gr_basic.h"
 #include "common.h"
-#include "class_drawpanel.h"
-#include "confirm.h"
 
 #include "dialog_hotkeys_editor.h"
 
@@ -30,6 +52,7 @@ HOTKEYS_EDITOR_DIALOG::HOTKEYS_EDITOR_DIALOG( WinEDA_DrawFrame*               pa
 {
     m_parent  = parent;
     m_hotkeys = hotkeys;
+    m_curEditingRow = -1;
 
     m_table = new HotkeyGridTable( hotkeys );
     m_hotkeyGrid->SetTable( m_table, true );
@@ -82,16 +105,18 @@ void HOTKEYS_EDITOR_DIALOG::OnOKClicked( wxCommandEvent& event )
     /* save the hotkeys */
     m_parent->WriteHotkeyConfig( m_hotkeys );
 
-    Close( TRUE );
+    EndModal( wxID_OK );
 }
 
 
 void HOTKEYS_EDITOR_DIALOG::CancelClicked( wxCommandEvent& event )
 {
-    Close( TRUE );
+    EndModal( wxID_CANCEL );
 }
 
 
+/* Reinit the hotkeys to the initial state (remove all pending changes
+ */
 void HOTKEYS_EDITOR_DIALOG::UndoClicked( wxCommandEvent& event )
 {
     m_table->RestoreFrom( m_hotkeys );
@@ -121,13 +146,13 @@ void HOTKEYS_EDITOR_DIALOG::SetHotkeyCellState( int aRow, bool aHightlight )
 }
 
 
-void HOTKEYS_EDITOR_DIALOG::StartEditing( wxGridEvent& event )
+void HOTKEYS_EDITOR_DIALOG::OnClickOnCell( wxGridEvent& event )
 {
     if( m_curEditingRow != -1 )
         SetHotkeyCellState( m_curEditingRow, false );
 
     int newRow = event.GetRow();
-    if( m_curEditingRow == newRow || m_table->isHeader( newRow ) )
+    if( ( event.GetCol() != 1 ) || ( m_table->isHeader( newRow ) ) )
     {
         m_curEditingRow = -1;
     }
@@ -140,8 +165,47 @@ void HOTKEYS_EDITOR_DIALOG::StartEditing( wxGridEvent& event )
     Update();
 }
 
+/** OnRightClickOnCell
+ * If a cell is selected, display a list of keys for selection
+ * The list is restricted to keys that cannot be entered:
+ * tab, home ... because these keys have special functions in dialogs
+ */
+void HOTKEYS_EDITOR_DIALOG::OnRightClickOnCell( wxGridEvent& event )
+{
+    // Select the new cell if needed
+    OnClickOnCell(event);
 
-void HOTKEYS_EDITOR_DIALOG::KeyPressed( wxKeyEvent& event )
+    if( m_curEditingRow == -1 )
+        return;
+
+    // Do not translate these key names. They are internally used.
+    //ee hotkeys_basic.cpp
+    #define C_COUNT 8
+    wxString choices[C_COUNT] =
+    {
+        wxT("End")
+        wxT("Tab"),
+        wxT("Ctrl+Tab"),
+        wxT("Alt+Tab"),
+        wxT("Home"),
+        wxT("Space"),
+        wxT("Ctrl+Space"),
+        wxT("Alt+Space"),
+    };
+
+    wxString keyname = wxGetSingleChoice(
+        _("Special keys only. For others keys, use keyboard"),
+        _("Select a key"), C_COUNT, choices, this);
+    int key = ReturnKeyCodeFromKeyName( keyname );
+
+    if( key == 0 )
+        return;
+    m_table->SetKeyCode( m_curEditingRow, key );
+    m_hotkeyGrid->Refresh();
+    Update();
+}
+
+void HOTKEYS_EDITOR_DIALOG::OnKeyPressed( wxKeyEvent& event )
 {
     if( m_curEditingRow != -1 )
     {
@@ -155,7 +219,6 @@ void HOTKEYS_EDITOR_DIALOG::KeyPressed( wxKeyEvent& event )
             break;
 
         default:
-
             if( event.ControlDown() )
                 key |= GR_KB_CTRL;
             if( event.AltDown() )
@@ -168,7 +231,7 @@ void HOTKEYS_EDITOR_DIALOG::KeyPressed( wxKeyEvent& event )
             if( (key > GR_KB_CTRL) && (key <= GR_KB_CTRL+26) )
                 key += ('A' - 1);
 
-            if( key >= 'a' && key <= 'z' ) //upcase key
+            if( key >= 'a' && key <= 'z' ) // convert to uppercase
                 key = key + ('A' - 'a');
 
 #if 0       // For debug only
@@ -176,7 +239,7 @@ void HOTKEYS_EDITOR_DIALOG::KeyPressed( wxKeyEvent& event )
             msg.Printf(wxT("key %X, keycode %X"),event.GetKeyCode(), key);
             wxMessageBox(msg);
 #endif
-            // See if this key code is handled in hotkeys list
+            // See if this key code is handled in hotkeys names list
             bool exists;
             ReturnKeyNameFromKeyCode( key, &exists );
             if( !exists )   // not handled, see hotkeys_basic.cpp
diff --git a/common/dialog_hotkeys_editor_base.cpp b/common/dialog_hotkeys_editor_base.cpp
index 09e18c1aca..f040a01870 100644
--- a/common/dialog_hotkeys_editor_base.cpp
+++ b/common/dialog_hotkeys_editor_base.cpp
@@ -16,11 +16,11 @@ HOTKEYS_EDITOR_DIALOG_BASE::HOTKEYS_EDITOR_DIALOG_BASE( wxWindow* parent, wxWind
 	wxBoxSizer* bMainSizer;
 	bMainSizer = new wxBoxSizer( wxHORIZONTAL );
 	
-	m_hotkeyGrid = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+	m_hotkeyGrid = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER|wxTAB_TRAVERSAL|wxWANTS_CHARS );
 	
 	// Grid
-	m_hotkeyGrid->CreateGrid( 5, 2 );
-	m_hotkeyGrid->EnableEditing( true );
+	m_hotkeyGrid->CreateGrid( 1, 2 );
+	m_hotkeyGrid->EnableEditing( false );
 	m_hotkeyGrid->EnableGridLines( true );
 	m_hotkeyGrid->EnableDragGridSize( false );
 	m_hotkeyGrid->SetMargins( 0, 0 );
@@ -43,26 +43,27 @@ HOTKEYS_EDITOR_DIALOG_BASE::HOTKEYS_EDITOR_DIALOG_BASE( wxWindow* parent, wxWind
 	m_hotkeyGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
 	bMainSizer->Add( m_hotkeyGrid, 1, wxALL|wxEXPAND, 5 );
 	
-	wxBoxSizer* bSizer2;
-	bSizer2 = new wxBoxSizer( wxVERTICAL );
+	wxBoxSizer* b_buttonsSizer;
+	b_buttonsSizer = new wxBoxSizer( wxVERTICAL );
 	
 	m_OKButton = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
-	bSizer2->Add( m_OKButton, 0, wxALL|wxEXPAND, 5 );
+	b_buttonsSizer->Add( m_OKButton, 0, wxALL|wxEXPAND, 5 );
 	
 	 m_cancelButton = new wxButton( this, wxID_ANY, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
-	bSizer2->Add(  m_cancelButton, 0, wxALL|wxEXPAND, 5 );
+	b_buttonsSizer->Add(  m_cancelButton, 0, wxALL|wxEXPAND, 5 );
 	
 	m_undoButton = new wxButton( this, wxID_CANCEL, _("Undo"), wxDefaultPosition, wxDefaultSize, 0 );
-	bSizer2->Add( m_undoButton, 0, wxALL|wxEXPAND, 5 );
+	b_buttonsSizer->Add( m_undoButton, 0, wxALL|wxEXPAND, 5 );
 	
-	bMainSizer->Add( bSizer2, 0, wxALIGN_CENTER_VERTICAL, 5 );
+	bMainSizer->Add( b_buttonsSizer, 0, wxALIGN_CENTER_VERTICAL, 5 );
 	
 	this->SetSizer( bMainSizer );
 	this->Layout();
 	
 	// Connect Events
-	m_hotkeyGrid->Connect( wxEVT_CHAR, wxKeyEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::KeyPressed ), NULL, this );
-	m_hotkeyGrid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::StartEditing ), NULL, this );
+	m_hotkeyGrid->Connect( wxEVT_CHAR, wxKeyEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnKeyPressed ), NULL, this );
+	m_hotkeyGrid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnRightClickOnCell ), NULL, this );
+	m_hotkeyGrid->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnClickOnCell ), NULL, this );
 	m_OKButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnOKClicked ), NULL, this );
 	 m_cancelButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::CancelClicked ), NULL, this );
 	m_undoButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::UndoClicked ), NULL, this );
@@ -71,8 +72,9 @@ HOTKEYS_EDITOR_DIALOG_BASE::HOTKEYS_EDITOR_DIALOG_BASE( wxWindow* parent, wxWind
 HOTKEYS_EDITOR_DIALOG_BASE::~HOTKEYS_EDITOR_DIALOG_BASE()
 {
 	// Disconnect Events
-	m_hotkeyGrid->Disconnect( wxEVT_CHAR, wxKeyEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::KeyPressed ), NULL, this );
-	m_hotkeyGrid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::StartEditing ), NULL, this );
+	m_hotkeyGrid->Disconnect( wxEVT_CHAR, wxKeyEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnKeyPressed ), NULL, this );
+	m_hotkeyGrid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnRightClickOnCell ), NULL, this );
+	m_hotkeyGrid->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnClickOnCell ), NULL, this );
 	m_OKButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::OnOKClicked ), NULL, this );
 	 m_cancelButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::CancelClicked ), NULL, this );
 	m_undoButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HOTKEYS_EDITOR_DIALOG_BASE::UndoClicked ), NULL, this );
diff --git a/common/dialog_hotkeys_editor_base.fbp b/common/dialog_hotkeys_editor_base.fbp
index 774211ca6b..91b99b4c72 100644
--- a/common/dialog_hotkeys_editor_base.fbp
+++ b/common/dialog_hotkeys_editor_base.fbp
@@ -99,7 +99,7 @@
                         <property name="drag_col_size">1</property>
                         <property name="drag_grid_size">0</property>
                         <property name="drag_row_size">1</property>
-                        <property name="editing">1</property>
+                        <property name="editing">0</property>
                         <property name="enabled">1</property>
                         <property name="fg"></property>
                         <property name="font"></property>
@@ -122,20 +122,20 @@
                         <property name="row_label_values"></property>
                         <property name="row_label_vert_alignment">wxALIGN_CENTRE</property>
                         <property name="row_sizes"></property>
-                        <property name="rows">5</property>
+                        <property name="rows">1</property>
                         <property name="size"></property>
                         <property name="subclass"></property>
                         <property name="tooltip"></property>
                         <property name="window_extra_style"></property>
                         <property name="window_name"></property>
-                        <property name="window_style"></property>
-                        <event name="OnChar">KeyPressed</event>
+                        <property name="window_style">wxDOUBLE_BORDER|wxTAB_TRAVERSAL|wxWANTS_CHARS</property>
+                        <event name="OnChar">OnKeyPressed</event>
                         <event name="OnEnterWindow"></event>
                         <event name="OnEraseBackground"></event>
                         <event name="OnGridCellChange"></event>
-                        <event name="OnGridCellLeftClick">StartEditing</event>
+                        <event name="OnGridCellLeftClick"></event>
                         <event name="OnGridCellLeftDClick"></event>
-                        <event name="OnGridCellRightClick"></event>
+                        <event name="OnGridCellRightClick">OnRightClickOnCell</event>
                         <event name="OnGridCellRightDClick"></event>
                         <event name="OnGridCmdCellChange"></event>
                         <event name="OnGridCmdCellLeftClick"></event>
@@ -163,7 +163,7 @@
                         <event name="OnGridLabelRightDClick"></event>
                         <event name="OnGridRangeSelect"></event>
                         <event name="OnGridRowSize"></event>
-                        <event name="OnGridSelectCell"></event>
+                        <event name="OnGridSelectCell">OnClickOnCell</event>
                         <event name="OnKeyDown"></event>
                         <event name="OnKeyUp"></event>
                         <event name="OnKillFocus"></event>
@@ -192,7 +192,7 @@
                     <property name="proportion">0</property>
                     <object class="wxBoxSizer" expanded="1">
                         <property name="minimum_size"></property>
-                        <property name="name">bSizer2</property>
+                        <property name="name">b_buttonsSizer</property>
                         <property name="orient">wxVERTICAL</property>
                         <property name="permission">none</property>
                         <object class="sizeritem" expanded="1">
diff --git a/common/dialog_hotkeys_editor_base.h b/common/dialog_hotkeys_editor_base.h
index 18962111c7..2ac21ee391 100644
--- a/common/dialog_hotkeys_editor_base.h
+++ b/common/dialog_hotkeys_editor_base.h
@@ -37,8 +37,9 @@ class HOTKEYS_EDITOR_DIALOG_BASE : public wxDialog
 		wxButton* m_undoButton;
 		
 		// Virtual event handlers, overide them in your derived class
-		virtual void KeyPressed( wxKeyEvent& event ){ event.Skip(); }
-		virtual void StartEditing( wxGridEvent& event ){ event.Skip(); }
+		virtual void OnKeyPressed( wxKeyEvent& event ){ event.Skip(); }
+		virtual void OnRightClickOnCell( wxGridEvent& event ){ event.Skip(); }
+		virtual void OnClickOnCell( wxGridEvent& event ){ event.Skip(); }
 		virtual void OnOKClicked( wxCommandEvent& event ){ event.Skip(); }
 		virtual void CancelClicked( wxCommandEvent& event ){ event.Skip(); }
 		virtual void UndoClicked( wxCommandEvent& event ){ event.Skip(); }
diff --git a/common/hotkeys_basic.cpp b/common/hotkeys_basic.cpp
index 56667c3895..7517e0b49b 100644
--- a/common/hotkeys_basic.cpp
+++ b/common/hotkeys_basic.cpp
@@ -70,6 +70,9 @@ struct hotkey_name_descr
  * Note : when modifiers (ATL, SHIFT, CTRL) do not modify
  * the code of the key, do need to enter the modified key code
  * For instance wxT( "F1" ), WXK_F1 handle F1, AltF1, CtrlF1 ...
+ * Key names are:
+ *        "Space","Ctrl+Space","Alt+Space" or
+ *      "Alt+A","Ctrl+F1", ...
  */
 static struct hotkey_name_descr s_Hotkey_Name_List[] =
 {
@@ -88,7 +91,7 @@ static struct hotkey_name_descr s_Hotkey_Name_List[] =
 
     { wxT( "Esc" ),          WXK_ESCAPE                                               },
     { wxT( "Del" ),          WXK_DELETE                                               },
-    { wxT( "Tab" ),          '\t'                                                     },
+    { wxT( "Tab" ),          WXK_TAB                                                  },
     { wxT( "BkSp" ),         WXK_BACK                                                 },
     { wxT( "Ins" ),          WXK_INSERT                                               },
 
@@ -102,6 +105,8 @@ static struct hotkey_name_descr s_Hotkey_Name_List[] =
     { wxT( "Left" ),         WXK_LEFT                                                 },
     { wxT( "Right" ),        WXK_RIGHT                                                },
 
+    { wxT( "Space" ),        WXK_SPACE                                                },
+
     // Do not change this line: end of list
     { wxT( "" ),             0                                                        }
 };
@@ -134,7 +139,7 @@ wxString ReturnKeyNameFromKeyCode( int aKeycode, bool* aIsFound )
 
     aKeycode &= ~( GR_KB_CTRL | GR_KB_ALT | GR_KB_SHIFT );
 
-    if( (aKeycode >= ' ') && (aKeycode < 0x7F ) )
+    if( (aKeycode > ' ') && (aKeycode < 0x7F ) )
     {
         found   = true;
         keyname.Append((wxChar)aKeycode);
@@ -263,7 +268,7 @@ wxString ReturnKeyNameFromCommandId( Ki_HotkeyInfo** aList, int aCommandId )
  *   like F2 or space or an usual (ascii) char.
  * @return the key code
  */
-static int ReturnKeyCodeFromKeyName( const wxString& keyname )
+int ReturnKeyCodeFromKeyName( const wxString& keyname )
 {
     int ii, keycode = 0;
 
@@ -292,10 +297,11 @@ static int ReturnKeyCodeFromKeyName( const wxString& keyname )
             break;
     }
 
-    if( (key[0] >= ' ') && (key[0] < 0x7F) )
+    if( (key.length() == 1) && (key[0] > ' ') && (key[0] < 0x7F) )
     {
         keycode = key[0];
         keycode += modifier;
+        return keycode;
     }
 
     for( ii = 0; ; ii++ )
@@ -303,7 +309,7 @@ static int ReturnKeyCodeFromKeyName( const wxString& keyname )
         if( s_Hotkey_Name_List[ii].m_KeyCode == 0 )  // End of list reached
             break;
 
-        if( keyname.CmpNoCase( s_Hotkey_Name_List[ii].m_Name ) == 0 )
+        if( key.CmpNoCase( s_Hotkey_Name_List[ii].m_Name ) == 0 )
         {
             keycode = s_Hotkey_Name_List[ii].m_KeyCode + modifier;
             break;
diff --git a/include/dialog_hotkeys_editor.h b/include/dialog_hotkeys_editor.h
index 24113651f6..58f484162d 100644
--- a/include/dialog_hotkeys_editor.h
+++ b/include/dialog_hotkeys_editor.h
@@ -40,8 +40,9 @@ private:
     void OnOKClicked( wxCommandEvent& event );
     void CancelClicked( wxCommandEvent& event );
     void UndoClicked( wxCommandEvent& event );
-    void StartEditing( wxGridEvent& event );
-    void KeyPressed( wxKeyEvent& event );
+    void OnClickOnCell( wxGridEvent& event );
+    void OnRightClickOnCell( wxGridEvent& event );
+    void OnKeyPressed( wxKeyEvent& event );
     void SetHotkeyCellState( int aRow, bool aHightlight );
 };
 
diff --git a/include/hotkeys_basic.h b/include/hotkeys_basic.h
index bdb6abb7f8..01fcbbfc96 100644
--- a/include/hotkeys_basic.h
+++ b/include/hotkeys_basic.h
@@ -78,6 +78,15 @@ wxString        ReturnKeyNameFromKeyCode( int aKeycode, bool * aIsFound = NULL )
  */
 wxString        ReturnKeyNameFromCommandId( Ki_HotkeyInfo** aList, int aCommandId );
 
+/** function ReturnKeyCodeFromKeyName
+ * return the key code from its key name
+ * Only some wxWidgets key values are handled for function key
+ * @param keyname = wxString key name to find in s_Hotkey_Name_List[],
+ *   like F2 or space or an usual (ascii) char.
+ * @return the key code
+ */
+int ReturnKeyCodeFromKeyName( const wxString& keyname );
+
 /** function AddHotkeyName
  * Add the key name from the Command id value ( m_Idcommand member value)
  * @param aText = a wxString. returns aText + key name