LMMS
Loading...
Searching...
No Matches
juce_KeyPressMappingSet.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
34
40
42{
43 Desktop::getInstance().removeFocusChangeListener (this);
44}
45
46//==============================================================================
48{
49 for (int i = 0; i < mappings.size(); ++i)
50 if (mappings.getUnchecked(i)->commandID == commandID)
51 return mappings.getUnchecked (i)->keypresses;
52
53 return {};
54}
55
56void KeyPressMappingSet::addKeyPress (const CommandID commandID, const KeyPress& newKeyPress, int insertIndex)
57{
58 // If you specify an upper-case letter but no shift key, how is the user supposed to press it!?
59 // Stick to lower-case letters when defining a keypress, to avoid ambiguity.
61 && ! newKeyPress.getModifiers().isShiftDown()));
62
63 if (findCommandForKeyPress (newKeyPress) != commandID)
64 {
65 if (newKeyPress.isValid())
66 {
67 for (int i = mappings.size(); --i >= 0;)
68 {
69 if (mappings.getUnchecked(i)->commandID == commandID)
70 {
71 mappings.getUnchecked(i)->keypresses.insert (insertIndex, newKeyPress);
72
74 return;
75 }
76 }
77
78 if (const ApplicationCommandInfo* const ci = commandManager.getCommandForID (commandID))
79 {
80 CommandMapping* const cm = new CommandMapping();
81 cm->commandID = commandID;
82 cm->keypresses.add (newKeyPress);
84
85 mappings.add (cm);
87 }
88 else
89 {
90 // If you hit this, you're trying to attach a keypress to a command ID that
91 // doesn't exist, so the key is not being attached.
93 }
94 }
95 }
96}
97
98static void addKeyPresses (KeyPressMappingSet& set, const ApplicationCommandInfo* const ci)
99{
100 for (int j = 0; j < ci->defaultKeypresses.size(); ++j)
101 set.addKeyPress (ci->commandID, ci->defaultKeypresses.getReference (j));
102}
103
105{
106 mappings.clear();
107
108 for (int i = 0; i < commandManager.getNumCommands(); ++i)
109 addKeyPresses (*this, commandManager.getCommandForIndex (i));
110
112}
113
115{
116 clearAllKeyPresses (commandID);
117
118 if (const ApplicationCommandInfo* const ci = commandManager.getCommandForID (commandID))
119 addKeyPresses (*this, ci);
120}
121
123{
124 if (mappings.size() > 0)
125 {
127 mappings.clear();
128 }
129}
130
132{
133 for (int i = mappings.size(); --i >= 0;)
134 {
135 if (mappings.getUnchecked(i)->commandID == commandID)
136 {
137 mappings.remove (i);
139 }
140 }
141}
142
144{
145 if (keypress.isValid())
146 {
147 for (int i = mappings.size(); --i >= 0;)
148 {
149 CommandMapping& cm = *mappings.getUnchecked(i);
150
151 for (int j = cm.keypresses.size(); --j >= 0;)
152 {
153 if (keypress == cm.keypresses [j])
154 {
155 cm.keypresses.remove (j);
157 }
158 }
159 }
160 }
161}
162
163void KeyPressMappingSet::removeKeyPress (const CommandID commandID, const int keyPressIndex)
164{
165 for (int i = mappings.size(); --i >= 0;)
166 {
167 if (mappings.getUnchecked(i)->commandID == commandID)
168 {
169 mappings.getUnchecked(i)->keypresses.remove (keyPressIndex);
171 break;
172 }
173 }
174}
175
176//==============================================================================
178{
179 for (int i = 0; i < mappings.size(); ++i)
180 if (mappings.getUnchecked(i)->keypresses.contains (keyPress))
181 return mappings.getUnchecked(i)->commandID;
182
183 return 0;
184}
185
186bool KeyPressMappingSet::containsMapping (const CommandID commandID, const KeyPress& keyPress) const noexcept
187{
188 for (int i = mappings.size(); --i >= 0;)
189 if (mappings.getUnchecked(i)->commandID == commandID)
190 return mappings.getUnchecked(i)->keypresses.contains (keyPress);
191
192 return false;
193}
194
196 const KeyPress& key,
197 const bool isKeyDown,
198 const int millisecsSinceKeyPressed,
199 Component* const originatingComponent) const
200{
202
204 info.isKeyDown = isKeyDown;
205 info.keyPress = key;
206 info.millisecsSinceKeyPressed = millisecsSinceKeyPressed;
207 info.originatingComponent = originatingComponent;
208
209 commandManager.invoke (info, false);
210}
211
212//==============================================================================
214{
215 if (xmlVersion.hasTagName ("KEYMAPPINGS"))
216 {
217 if (xmlVersion.getBoolAttribute ("basedOnDefaults", true))
218 {
219 // if the XML was created as a set of differences from the default mappings,
220 // (i.e. by calling createXml (true)), then we need to first restore the defaults.
222 }
223 else
224 {
225 // if the XML was created calling createXml (false), then we need to clear all
226 // the keys and treat the xml as describing the entire set of mappings.
228 }
229
230 for (auto* map : xmlVersion.getChildIterator())
231 {
232 const CommandID commandId = map->getStringAttribute ("commandId").getHexValue32();
233
234 if (commandId != 0)
235 {
236 auto key = KeyPress::createFromDescription (map->getStringAttribute ("key"));
237
238 if (map->hasTagName ("MAPPING"))
239 {
240 addKeyPress (commandId, key);
241 }
242 else if (map->hasTagName ("UNMAPPING"))
243 {
244 for (auto& m : mappings)
245 if (m->commandID == commandId)
246 m->keypresses.removeAllInstancesOf (key);
247 }
248 }
249 }
250
251 return true;
252 }
253
254 return false;
255}
256
257std::unique_ptr<XmlElement> KeyPressMappingSet::createXml (const bool saveDifferencesFromDefaultSet) const
258{
259 std::unique_ptr<KeyPressMappingSet> defaultSet;
260
261 if (saveDifferencesFromDefaultSet)
262 {
263 defaultSet = std::make_unique<KeyPressMappingSet> (commandManager);
264 defaultSet->resetToDefaultMappings();
265 }
266
267 auto doc = std::make_unique<XmlElement> ("KEYMAPPINGS");
268
269 doc->setAttribute ("basedOnDefaults", saveDifferencesFromDefaultSet);
270
271 for (int i = 0; i < mappings.size(); ++i)
272 {
273 auto& cm = *mappings.getUnchecked(i);
274
275 for (int j = 0; j < cm.keypresses.size(); ++j)
276 {
277 if (defaultSet == nullptr
278 || ! defaultSet->containsMapping (cm.commandID, cm.keypresses.getReference (j)))
279 {
280 auto map = doc->createNewChildElement ("MAPPING");
281
282 map->setAttribute ("commandId", String::toHexString ((int) cm.commandID));
283 map->setAttribute ("description", commandManager.getDescriptionOfCommand (cm.commandID));
284 map->setAttribute ("key", cm.keypresses.getReference (j).getTextDescription());
285 }
286 }
287 }
288
289 if (defaultSet != nullptr)
290 {
291 for (int i = 0; i < defaultSet->mappings.size(); ++i)
292 {
293 auto& cm = *defaultSet->mappings.getUnchecked(i);
294
295 for (int j = 0; j < cm.keypresses.size(); ++j)
296 {
297 if (! containsMapping (cm.commandID, cm.keypresses.getReference (j)))
298 {
299 auto map = doc->createNewChildElement ("UNMAPPING");
300
301 map->setAttribute ("commandId", String::toHexString ((int) cm.commandID));
302 map->setAttribute ("description", commandManager.getDescriptionOfCommand (cm.commandID));
303 map->setAttribute ("key", cm.keypresses.getReference (j).getTextDescription());
304 }
305 }
306 }
307 }
308
309 return doc;
310}
311
312//==============================================================================
313bool KeyPressMappingSet::keyPressed (const KeyPress& key, Component* const originatingComponent)
314{
315 bool commandWasDisabled = false;
316
317 for (int i = 0; i < mappings.size(); ++i)
318 {
319 CommandMapping& cm = *mappings.getUnchecked(i);
320
321 if (cm.keypresses.contains (key))
322 {
323 if (const ApplicationCommandInfo* const ci = commandManager.getCommandForID (cm.commandID))
324 {
326 {
328
329 if (commandManager.getTargetForCommand (cm.commandID, info) != nullptr)
330 {
331 if ((info.flags & ApplicationCommandInfo::isDisabled) == 0)
332 {
333 invokeCommand (cm.commandID, key, true, 0, originatingComponent);
334 return true;
335 }
336
337 commandWasDisabled = true;
338 }
339 }
340 }
341 }
342 }
343
344 if (originatingComponent != nullptr && commandWasDisabled)
345 originatingComponent->getLookAndFeel().playAlertSound();
346
347 return false;
348}
349
350bool KeyPressMappingSet::keyStateChanged (const bool /*isKeyDown*/, Component* originatingComponent)
351{
352 bool used = false;
354
355 for (int i = mappings.size(); --i >= 0;)
356 {
357 CommandMapping& cm = *mappings.getUnchecked(i);
358
360 {
361 for (int j = cm.keypresses.size(); --j >= 0;)
362 {
363 const KeyPress key (cm.keypresses.getReference (j));
364 const bool isDown = key.isCurrentlyDown();
365
366 int keyPressEntryIndex = 0;
367 bool wasDown = false;
368
369 for (int k = keysDown.size(); --k >= 0;)
370 {
371 if (key == keysDown.getUnchecked(k)->key)
372 {
373 keyPressEntryIndex = k;
374 wasDown = true;
375 used = true;
376 break;
377 }
378 }
379
380 if (isDown != wasDown)
381 {
382 int millisecs = 0;
383
384 if (isDown)
385 {
386 KeyPressTime* const k = new KeyPressTime();
387 k->key = key;
388 k->timeWhenPressed = now;
389
390 keysDown.add (k);
391 }
392 else
393 {
394 const uint32 pressTime = keysDown.getUnchecked (keyPressEntryIndex)->timeWhenPressed;
395
396 if (now > pressTime)
397 millisecs = (int) (now - pressTime);
398
399 keysDown.remove (keyPressEntryIndex);
400 }
401
402 invokeCommand (cm.commandID, key, isDown, millisecs, originatingComponent);
403 used = true;
404 }
405 }
406 }
407 }
408
409 return used;
410}
411
413{
414 if (focusedComponent != nullptr)
415 focusedComponent->keyStateChanged (false);
416}
417
418} // namespace juce
Definition juce_ApplicationCommandManager.h:88
Definition juce_Array.h:56
void sendChangeMessage()
Definition juce_ChangeBroadcaster.cpp:65
ChangeBroadcaster() noexcept
Definition juce_ChangeBroadcaster.cpp:26
static bool isUpperCase(juce_wchar character) noexcept
Definition juce_CharacterFunctions.cpp:38
Definition juce_Component.h:36
virtual bool keyStateChanged(bool isKeyDown)
Definition juce_Component.cpp:3231
LookAndFeel & getLookAndFeel() const noexcept
Definition juce_Component.cpp:2173
static Desktop &JUCE_CALLTYPE getInstance()
Definition juce_Desktop.cpp:50
Definition juce_Desktop.h:39
Definition juce_KeyListener.h:41
Definition juce_KeyPress.h:40
juce_wchar getTextCharacter() const noexcept
Definition juce_KeyPress.h:122
bool isValid() const noexcept
Definition juce_KeyPress.h:102
ModifierKeys getModifiers() const noexcept
Definition juce_KeyPress.h:115
static KeyPress createFromDescription(const String &textVersion)
Definition juce_KeyPress.cpp:174
Definition juce_KeyPressMappingSet.h:89
ApplicationCommandManager & commandManager
Definition juce_KeyPressMappingSet.h:218
void addKeyPress(CommandID commandID, const KeyPress &newKeyPress, int insertIndex=-1)
Definition juce_KeyPressMappingSet.cpp:56
void resetToDefaultMapping(CommandID commandID)
Definition juce_KeyPressMappingSet.cpp:114
Array< KeyPress > getKeyPressesAssignedToCommand(CommandID commandID) const
Definition juce_KeyPressMappingSet.cpp:47
bool containsMapping(CommandID commandID, const KeyPress &keyPress) const noexcept
Definition juce_KeyPressMappingSet.cpp:186
void removeKeyPress(CommandID commandID, int keyPressIndex)
Definition juce_KeyPressMappingSet.cpp:163
~KeyPressMappingSet() override
Definition juce_KeyPressMappingSet.cpp:41
void globalFocusChanged(Component *) override
Definition juce_KeyPressMappingSet.cpp:412
void clearAllKeyPresses()
Definition juce_KeyPressMappingSet.cpp:122
void resetToDefaultMappings()
Definition juce_KeyPressMappingSet.cpp:104
OwnedArray< KeyPressTime > keysDown
Definition juce_KeyPressMappingSet.h:235
CommandID findCommandForKeyPress(const KeyPress &keyPress) const noexcept
Definition juce_KeyPressMappingSet.cpp:177
bool keyPressed(const KeyPress &, Component *) override
Definition juce_KeyPressMappingSet.cpp:313
KeyPressMappingSet(ApplicationCommandManager &)
Definition juce_KeyPressMappingSet.cpp:29
void invokeCommand(const CommandID, const KeyPress &, const bool isKeyDown, const int millisecsSinceKeyPressed, Component *originator) const
Definition juce_KeyPressMappingSet.cpp:195
bool keyStateChanged(bool isKeyDown, Component *) override
Definition juce_KeyPressMappingSet.cpp:350
bool restoreFromXml(const XmlElement &xmlVersion)
Definition juce_KeyPressMappingSet.cpp:213
std::unique_ptr< XmlElement > createXml(bool saveDifferencesFromDefaultSet) const
Definition juce_KeyPressMappingSet.cpp:257
OwnedArray< CommandMapping > mappings
Definition juce_KeyPressMappingSet.h:227
virtual void playAlertSound()
Definition juce_linux_Windowing.cpp:809
bool isShiftDown() const noexcept
Definition juce_ModifierKeys.h:99
static String toHexString(IntegerType number)
Definition juce_String.h:1097
static uint32 getMillisecondCounter() noexcept
Definition juce_Time.cpp:241
Definition juce_XmlElement.h:83
bool getBoolAttribute(StringRef attributeName, bool defaultReturnValue=false) const
Definition juce_XmlElement.cpp:587
bool hasTagName(StringRef possibleTagName) const noexcept
Definition juce_XmlElement.cpp:470
Iterator< GetNextElement > getChildIterator() const
Definition juce_XmlElement.h:715
unsigned * m
Definition inflate.c:1559
register unsigned k
Definition inflate.c:946
register unsigned j
Definition inflate.c:1576
register unsigned i
Definition inflate.c:1575
struct backing_store_struct * info
Definition jmemsys.h:183
#define jassert(expression)
#define jassertfalse
Definition carla_juce.cpp:31
static void addKeyPresses(KeyPressMappingSet &set, const ApplicationCommandInfo *const ci)
Definition juce_KeyPressMappingSet.cpp:98
unsigned int uint32
Definition juce_MathsFunctions.h:45
int CommandID
Definition juce_ApplicationCommandID.h:37
Definition juce_ApplicationCommandInfo.h:45
Array< KeyPress > defaultKeypresses
Definition juce_ApplicationCommandInfo.h:127
CommandID commandID
Definition juce_ApplicationCommandInfo.h:87
@ wantsKeyUpDownCallbacks
Definition juce_ApplicationCommandInfo.h:163
@ isDisabled
Definition juce_ApplicationCommandInfo.h:146
Definition juce_ApplicationCommandTarget.h:61
@ fromKeyPress
Definition juce_ApplicationCommandTarget.h:79
Definition juce_KeyPressMappingSet.h:221
bool wantsKeyUpDownCallbacks
Definition juce_KeyPressMappingSet.h:224
CommandID commandID
Definition juce_KeyPressMappingSet.h:222
Array< KeyPress > keypresses
Definition juce_KeyPressMappingSet.h:223
Definition juce_KeyPressMappingSet.h:230
ZCONST char * key
Definition crypt.c:587
typedef int(UZ_EXP MsgFn)()