KiCad PCB EDA Suite
Loading...
Searching...
No Matches
hotkey_store.cpp
Go to the documentation of this file.
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
24#include <hotkey_store.h>
25#include <eda_base_frame.h>
26#include <tool/tool_manager.h>
27#include <tool/action_manager.h>
28#include <tool/tool_event.h>
29#include <tool/tool_action.h>
30#include <advanced_config.h>
31
33{
34public:
35 PSEUDO_ACTION( const wxString& aLabel, int aHotKey, int aHotKeyAlt = 0 )
36 {
37 m_friendlyName = aLabel;
38 m_hotKey = aHotKey;
39 m_hotKeyAlt = aHotKeyAlt;
40 }
41};
42
44 new PSEUDO_ACTION( _( "Accept Autocomplete" ), WXK_RETURN, WXK_NUMPAD_ENTER ),
45 new PSEUDO_ACTION( _( "Cancel Autocomplete" ), WXK_ESCAPE ),
46 new PSEUDO_ACTION( _( "Toggle Checkbox" ), WXK_SPACE ),
47 new PSEUDO_ACTION( _( "Pan Left/Right" ), MD_CTRL + PSEUDO_WXK_WHEEL ),
48 new PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
49 new PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
50 new PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
51 new PSEUDO_ACTION( _( "Highlight Net" ), MD_CTRL + PSEUDO_WXK_CLICK ),
52 new PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_CTRL + PSEUDO_WXK_CLICK ),
53 new PSEUDO_ACTION( _( "Ignore Grid Snaps" ), MD_CTRL ),
54 new PSEUDO_ACTION( _( "Ignore Other Snaps" ), MD_SHIFT ),
55};
56
58#ifndef __WINDOWS__
59 new PSEUDO_ACTION( _( "Close" ), MD_CTRL + 'W' ),
60#endif
61 new PSEUDO_ACTION( _( "Quit" ), MD_CTRL + 'Q' )
62};
63
64
66{
67 wxString name( aAction->GetName() );
68 return name.BeforeFirst( '.' );
69}
70
71
73{
74 std::map<wxString, wxString> s_AppNames = {
75 { wxT( "common" ), _( "Common" ) },
76 { wxT( "kicad" ), _( "Project Manager" ) },
77 { wxT( "eeschema" ), _( "Schematic Editor" ) },
78 { wxT( "pcbnew" ), _( "PCB Editor" ) },
79 { wxT( "plEditor" ), _( "Drawing Sheet Editor" ), },
80 { wxT( "3DViewer" ), _( "3D Viewer" ) },
81 { wxT( "gerbview" ), _( "Gerber Viewer" ) }
82 };
83
84 wxString appName = GetAppName( aAction );
85
86 if( s_AppNames.count( appName ) )
87 return s_AppNames[ appName ];
88 else
89 return appName;
90}
91
92
94{
95}
96
97
98void HOTKEY_STORE::Init( std::vector<TOOL_ACTION*> aActionsList, bool aIncludeReadOnlyCmds )
99{
100 std::map<std::string, HOTKEY> masterMap;
101
102 for( TOOL_ACTION* action : aActionsList )
103 {
104 // Internal actions probably shouldn't be allowed hotkeys
105 if( action->GetFriendlyName().IsEmpty() )
106 continue;
107
108 if( !ADVANCED_CFG::GetCfg().m_ExtraZoneDisplayModes )
109 {
110 if( action->GetName() == "pcbnew.Control.zoneDisplayOutlines"
111 || action->GetName() == "pcbnew.Control.zoneDisplayTesselation" )
112 {
113 continue;
114 }
115 }
116
117 HOTKEY& hotkey = masterMap[ action->GetName() ];
118 hotkey.m_Actions.push_back( action );
119
120 if( !hotkey.m_EditKeycode )
121 {
122 hotkey.m_EditKeycode = action->GetHotKey();
123 hotkey.m_EditKeycodeAlt = action->GetHotKeyAlt();
124 }
125 }
126
127 wxString currentApp;
128 HOTKEY_SECTION* currentSection = nullptr;
129
130 // If a previous list was built, ensure this previous list is cleared:
131 m_hk_sections.clear();
132
133 for( const std::pair<const std::string, HOTKEY>& entry : masterMap )
134 {
135 TOOL_ACTION* entryAction = entry.second.m_Actions[ 0 ];
136 wxString entryApp = GetAppName( entryAction );
137
138 if( !currentSection || entryApp != currentApp )
139 {
140 m_hk_sections.emplace_back( HOTKEY_SECTION() );
141 currentApp = entryApp;
142 currentSection = &m_hk_sections.back();
143 currentSection->m_SectionName = GetSectionName( entryAction );
144
145 if( aIncludeReadOnlyCmds && currentApp == "common" )
146 {
148 currentSection->m_HotKeys.emplace_back( HOTKEY( command ) );
149 }
150 }
151
152 currentSection->m_HotKeys.emplace_back( HOTKEY( entry.second ) );
153 }
154
155 if( aIncludeReadOnlyCmds )
156 {
157 m_hk_sections.emplace_back( HOTKEY_SECTION() );
158 currentSection = &m_hk_sections.back();
159 currentSection->m_SectionName = _( "Gestures" );
160
161 for( TOOL_ACTION* gesture : g_gesturePseudoActions )
162 currentSection->m_HotKeys.emplace_back( HOTKEY( gesture ) );
163 }
164}
165
166
167std::vector<HOTKEY_SECTION>& HOTKEY_STORE::GetSections()
168{
169 return m_hk_sections;
170}
171
172
174{
175 for( HOTKEY_SECTION& section : m_hk_sections )
176 {
177 for( HOTKEY& hotkey : section.m_HotKeys )
178 {
179 for( TOOL_ACTION* action : hotkey.m_Actions )
180 action->SetHotKey( hotkey.m_EditKeycode, hotkey.m_EditKeycodeAlt );
181 }
182 }
183}
184
185
187{
188 for( HOTKEY_SECTION& section : m_hk_sections )
189 {
190 for( HOTKEY& hotkey : section.m_HotKeys )
191 {
192 hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetDefaultHotKey();
193 hotkey.m_EditKeycodeAlt = hotkey.m_Actions[ 0 ]->GetDefaultHotKeyAlt();
194 }
195 }
196}
197
198
200{
201 for( HOTKEY_SECTION& section : m_hk_sections )
202 {
203 for( HOTKEY& hotkey : section.m_HotKeys )
204 {
205 hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetHotKey();
206 hotkey.m_EditKeycodeAlt = hotkey.m_Actions[ 0 ]->GetHotKeyAlt();
207 }
208 }
209}
210
211
212bool HOTKEY_STORE::CheckKeyConflicts( TOOL_ACTION* aAction, long aKey, HOTKEY** aConflict )
213{
214 wxString sectionName = GetSectionName( aAction );
215
216 // Create a fake "TOOL_ACTION" so we can get the section name for "Common" through the API.
217 // Simply declaring a wxString with the value "Common" works, but the goal is to futureproof
218 // the code here as much as possible.
219 TOOL_ACTION commonAction( TOOL_ACTION_ARGS().Name( "common.Control.Fake" ).Scope( AS_GLOBAL ) );
220 wxString commonName = GetSectionName( &commonAction );
221
222 for( HOTKEY_SECTION& section : m_hk_sections )
223 {
224 // We can have the same hotkey in multiple sections (i.e. Kicad programs), but if a hotkey
225 // is in "Common" it can't be in any other section and vice versa.
226
227 if( !( section.m_SectionName == sectionName || section.m_SectionName == commonName ) )
228 continue;
229
230 for( HOTKEY& hotkey : section.m_HotKeys )
231 {
232 if( hotkey.m_Actions[0] == aAction )
233 continue;
234
235 if( hotkey.m_EditKeycode == aKey || hotkey.m_EditKeycodeAlt == aKey )
236 {
237 // We can use the same key for a different action if both actions are contextual and
238 // for different tools.
239 if( hotkey.m_Actions[0]->GetScope() == AS_CONTEXT &&
240 aAction->GetScope() == AS_CONTEXT &&
241 hotkey.m_Actions[0]->GetToolName() != aAction->GetToolName() )
242 {
243 continue;
244 }
245
246 *aConflict = &hotkey;
247 return true;
248 }
249 }
250 }
251
252 return false;
253}
const char * name
Definition: DXF_plotter.cpp:57
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
bool CheckKeyConflicts(TOOL_ACTION *aAction, long aKey, HOTKEY **aConflict)
Check whether the given key conflicts with anything in this store.
void ResetAllHotkeysToOriginal()
Resets every hotkey to the original values.
void ResetAllHotkeysToDefault()
Reset every hotkey in the store to the default values.
HOTKEY_STORE()
Construct a HOTKEY_STORE from a list of hotkey sections.
void Init(std::vector< TOOL_ACTION * > aActionsList, bool aIncludeReadOnlyCmds)
std::vector< HOTKEY_SECTION > & GetSections()
Get the list of sections managed by this store.
std::vector< HOTKEY_SECTION > m_hk_sections
Definition: hotkey_store.h:114
void SaveAllHotkeys()
Persist all changes to hotkeys in the store to the underlying data structures.
static wxString GetSectionName(TOOL_ACTION *aAction)
static wxString GetAppName(TOOL_ACTION *aAction)
PSEUDO_ACTION(const wxString &aLabel, int aHotKey, int aHotKeyAlt=0)
Build up the properties of a TOOL_ACTION in an incremental manner that is static-construction safe.
Definition: tool_action.h:102
Represent a single user action.
Definition: tool_action.h:269
void SetHotKey(int aKeycode, int aKeycodeAlt=0)
TOOL_ACTION_SCOPE GetScope() const
Definition: tool_action.h:366
std::string GetToolName() const
Return name of the tool associated with the action.
wxString m_friendlyName
Definition: tool_action.h:447
const std::string & GetName() const
Return name of the action.
Definition: tool_action.h:302
#define _(s)
Base window classes and related definitions.
static PSEUDO_ACTION * g_gesturePseudoActions[]
static PSEUDO_ACTION * g_standardPlatformCommands[]
#define PSEUDO_WXK_WHEEL
Definition: hotkeys_basic.h:52
#define PSEUDO_WXK_DBLCLICK
Definition: hotkeys_basic.h:51
#define PSEUDO_WXK_CLICK
Definition: hotkeys_basic.h:50
std::vector< HOTKEY > m_HotKeys
Definition: hotkey_store.h:57
wxString m_SectionName
Definition: hotkey_store.h:56
int m_EditKeycodeAlt
Definition: hotkey_store.h:38
int m_EditKeycode
Definition: hotkey_store.h:37
std::vector< TOOL_ACTION * > m_Actions
Definition: hotkey_store.h:36
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition: tool_action.h:48
@ AS_CONTEXT
Action belongs to a particular tool (i.e. a part of a pop-up menu)
Definition: tool_action.h:46
@ MD_CTRL
Definition: tool_event.h:143
@ MD_SHIFT
Definition: tool_event.h:142