You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
6.2 KiB

  1. /*
  2. * This program source code file is part of KICAD, a free EDA CAD application.
  3. *
  4. * Copyright (C) 1992-2019 Kicad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <hotkey_store.h>
  24. #include <eda_base_frame.h>
  25. #include <tool/tool_manager.h>
  26. #include <tool/action_manager.h>
  27. #include <tool/tool_event.h>
  28. #include <tool/tool_action.h>
  29. class GESTURE_PSEUDO_ACTION : public TOOL_ACTION
  30. {
  31. public:
  32. GESTURE_PSEUDO_ACTION( const wxString& aLabel, int aHotKey )
  33. {
  34. m_label = aLabel;
  35. m_hotKey = aHotKey;
  36. }
  37. };
  38. static GESTURE_PSEUDO_ACTION* g_gesturePseudoActions[] = {
  39. new GESTURE_PSEUDO_ACTION( _( "Pan Left/Right" ), MD_CTRL + PSEUDO_WXK_WHEEL ),
  40. new GESTURE_PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
  41. new GESTURE_PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
  42. new GESTURE_PSEUDO_ACTION( _( "Show Clarify Selection Menu" ), MD_ALT + PSEUDO_WXK_CLICK ),
  43. new GESTURE_PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
  44. new GESTURE_PSEUDO_ACTION( _( "Toggle Selection State" ), MD_CTRL + PSEUDO_WXK_CLICK ),
  45. new GESTURE_PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_CTRL + PSEUDO_WXK_CLICK ),
  46. new GESTURE_PSEUDO_ACTION( _( "Ignore Grid Snaps" ), MD_ALT ),
  47. new GESTURE_PSEUDO_ACTION( _( "Ignore Other Snaps" ), MD_SHIFT ),
  48. };
  49. wxString HOTKEY_STORE::GetAppName( TOOL_ACTION* aAction )
  50. {
  51. wxString name( aAction->GetName() );
  52. return name.BeforeFirst( '.' );
  53. }
  54. wxString HOTKEY_STORE::GetSectionName( TOOL_ACTION* aAction )
  55. {
  56. std::map<wxString, wxString> s_AppNames = {
  57. { wxT( "common" ), _( "Common" ) },
  58. { wxT( "kicad" ), _( "Project Manager" ) },
  59. { wxT( "eeschema" ), _( "Eeschema" ) },
  60. { wxT( "pcbnew" ), _( "Pcbnew" ) },
  61. { wxT( "plEditor" ), _( "Page Layout Editor" ), },
  62. { wxT( "3DViewer" ), _( "3D Viewer" ) }
  63. };
  64. wxString appName = GetAppName( aAction );
  65. if( s_AppNames.count( appName ) )
  66. return s_AppNames[ appName ];
  67. else
  68. return appName;
  69. }
  70. HOTKEY_STORE::HOTKEY_STORE()
  71. {
  72. }
  73. void HOTKEY_STORE::Init( std::vector<TOOL_MANAGER*> aToolManagerList, bool aIncludeGestures )
  74. {
  75. m_toolManagers = std::move( aToolManagerList );
  76. // Collect all action maps into a single master map. This will re-group everything
  77. // and collect duplicates together
  78. std::map<std::string, HOTKEY> masterMap;
  79. for( TOOL_MANAGER* toolMgr : m_toolManagers )
  80. {
  81. for( const auto& entry : toolMgr->GetActions() )
  82. {
  83. // Internal actions probably shouldn't be allowed hotkeys
  84. if( entry.second->GetLabel().IsEmpty() )
  85. continue;
  86. HOTKEY& hotkey = masterMap[ entry.first ];
  87. hotkey.m_Actions.push_back( entry.second );
  88. hotkey.m_EditKeycode = entry.second->GetHotKey();
  89. }
  90. }
  91. wxString currentApp;
  92. HOTKEY_SECTION* currentSection = nullptr;
  93. // If a previous list was built, ensure this previous list is cleared:
  94. m_hk_sections.clear();
  95. for( const auto& entry : masterMap )
  96. {
  97. TOOL_ACTION* entryAction = entry.second.m_Actions[ 0 ];
  98. wxString entryApp = GetAppName( entryAction );
  99. if( !currentSection || entryApp != currentApp )
  100. {
  101. m_hk_sections.emplace_back( HOTKEY_SECTION() );
  102. currentApp = entryApp;
  103. currentSection = &m_hk_sections.back();
  104. currentSection->m_SectionName = GetSectionName( entryAction );
  105. }
  106. currentSection->m_HotKeys.emplace_back( HOTKEY( entry.second ) );
  107. }
  108. if( aIncludeGestures )
  109. {
  110. m_hk_sections.emplace_back( HOTKEY_SECTION() );
  111. currentSection = &m_hk_sections.back();
  112. currentSection->m_SectionName = _( "Gestures" );
  113. for( TOOL_ACTION* gesture : g_gesturePseudoActions )
  114. currentSection->m_HotKeys.emplace_back( HOTKEY( gesture ) );
  115. }
  116. }
  117. std::vector<HOTKEY_SECTION>& HOTKEY_STORE::GetSections()
  118. {
  119. return m_hk_sections;
  120. }
  121. void HOTKEY_STORE::SaveAllHotkeys()
  122. {
  123. for( HOTKEY_SECTION& section : m_hk_sections )
  124. {
  125. for( HOTKEY& hotkey : section.m_HotKeys )
  126. {
  127. for( TOOL_ACTION* action : hotkey.m_Actions )
  128. action->SetHotKey( hotkey.m_EditKeycode );
  129. }
  130. }
  131. }
  132. void HOTKEY_STORE::ResetAllHotkeysToDefault()
  133. {
  134. for( HOTKEY_SECTION& section : m_hk_sections )
  135. {
  136. for( HOTKEY& hotkey : section.m_HotKeys )
  137. hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetDefaultHotKey();
  138. }
  139. }
  140. void HOTKEY_STORE::ResetAllHotkeysToOriginal()
  141. {
  142. for( HOTKEY_SECTION& section : m_hk_sections )
  143. {
  144. for( HOTKEY& hotkey : section.m_HotKeys )
  145. hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetHotKey();
  146. }
  147. }
  148. bool HOTKEY_STORE::CheckKeyConflicts( TOOL_ACTION* aAction, long aKey, HOTKEY** aConflict )
  149. {
  150. wxString sectionName = GetSectionName( aAction );
  151. for( HOTKEY_SECTION& section: m_hk_sections )
  152. {
  153. if( section.m_SectionName != sectionName )
  154. continue;
  155. for( HOTKEY& hotkey: section.m_HotKeys )
  156. {
  157. if( hotkey.m_Actions[ 0 ] == aAction )
  158. continue;
  159. if( hotkey.m_EditKeycode == aKey )
  160. {
  161. *aConflict = &hotkey;
  162. return true;
  163. }
  164. }
  165. }
  166. return false;
  167. }