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 )
36 {
37 m_friendlyName = aLabel;
38 m_hotKey = aHotKey;
39 }
40};
41
43 new PSEUDO_ACTION( _( "Pan Left/Right" ), MD_CTRL + PSEUDO_WXK_WHEEL ),
44 new PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
45 new PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
46 new PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
47 new PSEUDO_ACTION( _( "Highlight Net" ), MD_CTRL + PSEUDO_WXK_CLICK ),
48 new PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_CTRL + PSEUDO_WXK_CLICK ),
49 new PSEUDO_ACTION( _( "Ignore Grid Snaps" ), MD_CTRL ),
50 new PSEUDO_ACTION( _( "Ignore Other Snaps" ), MD_SHIFT ),
51};
52
54#ifndef __WINDOWS__
55 new PSEUDO_ACTION( _( "Close" ), MD_CTRL + 'W' ),
56#endif
57 new PSEUDO_ACTION( _( "Quit" ), MD_CTRL + 'Q' )
58};
59
60
62{
63 wxString name( aAction->GetName() );
64 return name.BeforeFirst( '.' );
65}
66
67
69{
70 std::map<wxString, wxString> s_AppNames = {
71 { wxT( "common" ), _( "Common" ) },
72 { wxT( "kicad" ), _( "Project Manager" ) },
73 { wxT( "eeschema" ), _( "Schematic Editor" ) },
74 { wxT( "pcbnew" ), _( "PCB Editor" ) },
75 { wxT( "plEditor" ), _( "Drawing Sheet Editor" ), },
76 { wxT( "3DViewer" ), _( "3D Viewer" ) },
77 { wxT( "gerbview" ), _( "Gerber Viewer" ) }
78 };
79
80 wxString appName = GetAppName( aAction );
81
82 if( s_AppNames.count( appName ) )
83 return s_AppNames[ appName ];
84 else
85 return appName;
86}
87
88
90{
91}
92
93
94void HOTKEY_STORE::Init( std::vector<TOOL_ACTION*> aActionsList, bool aIncludeReadOnlyCmds )
95{
96 std::map<std::string, HOTKEY> masterMap;
97
98 for( TOOL_ACTION* action : aActionsList )
99 {
100 // Internal actions probably shouldn't be allowed hotkeys
101 if( action->GetFriendlyName().IsEmpty() )
102 continue;
103
104 if( !ADVANCED_CFG::GetCfg().m_ExtraZoneDisplayModes )
105 {
106 if( action->GetName() == "pcbnew.Control.zoneDisplayOutlines"
107 || action->GetName() == "pcbnew.Control.zoneDisplayTesselation" )
108 {
109 continue;
110 }
111 }
112
113 HOTKEY& hotkey = masterMap[ action->GetName() ];
114 hotkey.m_Actions.push_back( action );
115
116 if( !hotkey.m_EditKeycode )
117 {
118 hotkey.m_EditKeycode = action->GetHotKey();
119 hotkey.m_EditKeycodeAlt = action->GetHotKeyAlt();
120 }
121 }
122
123 wxString currentApp;
124 HOTKEY_SECTION* currentSection = nullptr;
125
126 // If a previous list was built, ensure this previous list is cleared:
127 m_hk_sections.clear();
128
129 for( const std::pair<const std::string, HOTKEY>& entry : masterMap )
130 {
131 TOOL_ACTION* entryAction = entry.second.m_Actions[ 0 ];
132 wxString entryApp = GetAppName( entryAction );
133
134 if( !currentSection || entryApp != currentApp )
135 {
136 m_hk_sections.emplace_back( HOTKEY_SECTION() );
137 currentApp = entryApp;
138 currentSection = &m_hk_sections.back();
139 currentSection->m_SectionName = GetSectionName( entryAction );
140
141 if( aIncludeReadOnlyCmds && currentApp == "common" )
142 {
144 currentSection->m_HotKeys.emplace_back( HOTKEY( command ) );
145 }
146 }
147
148 currentSection->m_HotKeys.emplace_back( HOTKEY( entry.second ) );
149 }
150
151 if( aIncludeReadOnlyCmds )
152 {
153 m_hk_sections.emplace_back( HOTKEY_SECTION() );
154 currentSection = &m_hk_sections.back();
155 currentSection->m_SectionName = _( "Gestures" );
156
157 for( TOOL_ACTION* gesture : g_gesturePseudoActions )
158 currentSection->m_HotKeys.emplace_back( HOTKEY( gesture ) );
159 }
160}
161
162
163std::vector<HOTKEY_SECTION>& HOTKEY_STORE::GetSections()
164{
165 return m_hk_sections;
166}
167
168
170{
171 for( HOTKEY_SECTION& section : m_hk_sections )
172 {
173 for( HOTKEY& hotkey : section.m_HotKeys )
174 {
175 for( TOOL_ACTION* action : hotkey.m_Actions )
176 action->SetHotKey( hotkey.m_EditKeycode, hotkey.m_EditKeycodeAlt );
177 }
178 }
179}
180
181
183{
184 for( HOTKEY_SECTION& section : m_hk_sections )
185 {
186 for( HOTKEY& hotkey : section.m_HotKeys )
187 {
188 hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetDefaultHotKey();
189 hotkey.m_EditKeycodeAlt = hotkey.m_Actions[ 0 ]->GetDefaultHotKeyAlt();
190 }
191 }
192}
193
194
196{
197 for( HOTKEY_SECTION& section : m_hk_sections )
198 {
199 for( HOTKEY& hotkey : section.m_HotKeys )
200 {
201 hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetHotKey();
202 hotkey.m_EditKeycodeAlt = hotkey.m_Actions[ 0 ]->GetHotKeyAlt();
203 }
204 }
205}
206
207
208bool HOTKEY_STORE::CheckKeyConflicts( TOOL_ACTION* aAction, long aKey, HOTKEY** aConflict )
209{
210 wxString sectionName = GetSectionName( aAction );
211
212 // Create a fake "TOOL_ACTION" so we can get the section name for "Common" through the API.
213 // Simply declaring a wxString with the value "Common" works, but the goal is to futureproof
214 // the code here as much as possible.
215 TOOL_ACTION commonAction( TOOL_ACTION_ARGS().Name( "common.Control.Fake" ).Scope( AS_GLOBAL ) );
216 wxString commonName = GetSectionName( &commonAction );
217
218 for( HOTKEY_SECTION& section : m_hk_sections )
219 {
220 // We can have the same hotkey in multiple sections (i.e. Kicad programs), but if a hotkey
221 // is in "Common" it can't be in any other section and vice versa.
222
223 if( !( section.m_SectionName == sectionName || section.m_SectionName == commonName ) )
224 continue;
225
226 for( HOTKEY& hotkey : section.m_HotKeys )
227 {
228 if( hotkey.m_Actions[0] == aAction )
229 continue;
230
231 if( hotkey.m_EditKeycode == aKey || hotkey.m_EditKeycodeAlt == aKey )
232 {
233 // We can use the same key for a different action if both actions are contextual and
234 // for different tools.
235 if( hotkey.m_Actions[0]->GetScope() == AS_CONTEXT &&
236 aAction->GetScope() == AS_CONTEXT &&
237 hotkey.m_Actions[0]->GetToolName() != aAction->GetToolName() )
238 {
239 continue;
240 }
241
242 *aConflict = &hotkey;
243 return true;
244 }
245 }
246 }
247
248 return false;
249}
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)
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