JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_ApplicationCommandManager.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
41//==============================================================================
43{
44 commands.clear();
45 keyMappings->clearAllKeyPresses();
47}
48
50{
51 // zero isn't a valid command ID!
52 jassert (newCommand.commandID != 0);
53
54 // the name isn't optional!
55 jassert (newCommand.shortName.isNotEmpty());
56
57 if (auto* command = getMutableCommandForID (newCommand.commandID))
58 {
59 // Trying to re-register the same command ID with different parameters can often indicate a typo.
60 // This assertion is here because I've found it useful catching some mistakes, but it may also cause
61 // false alarms if you're deliberately updating some flags for a command.
62 jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName
63 && newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName
64 && newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses
67
68 *command = newCommand;
69 }
70 else
71 {
73 newInfo->flags &= ~ApplicationCommandInfo::isTicked;
74 commands.add (newInfo);
75
76 keyMappings->resetToDefaultMapping (newCommand.commandID);
77
79 }
80}
81
83{
84 if (target != nullptr)
85 {
87 target->getAllCommands (commandIDs);
88
89 for (int i = 0; i < commandIDs.size(); ++i)
90 {
91 ApplicationCommandInfo info (commandIDs.getUnchecked (i));
92 target->getCommandInfo (info.commandID, info);
93
94 registerCommand (info);
95 }
96 }
97}
98
100{
101 for (int i = commands.size(); --i >= 0;)
102 {
103 if (commands.getUnchecked (i)->commandID == commandID)
104 {
105 commands.remove (i);
107
108 const Array<KeyPress> keys (keyMappings->getKeyPressesAssignedToCommand (commandID));
109
110 for (int j = keys.size(); --j >= 0;)
111 keyMappings->removeKeyPress (keys.getReference (j));
112 }
113 }
114}
115
120
121//==============================================================================
122ApplicationCommandInfo* ApplicationCommandManager::getMutableCommandForID (CommandID commandID) const noexcept
123{
124 for (int i = commands.size(); --i >= 0;)
125 if (commands.getUnchecked (i)->commandID == commandID)
126 return commands.getUnchecked (i);
127
128 return nullptr;
129}
130
132{
133 return getMutableCommandForID (commandID);
134}
135
137{
138 if (auto* ci = getCommandForID (commandID))
139 return ci->shortName;
140
141 return {};
142}
143
145{
146 if (auto* ci = getCommandForID (commandID))
147 return ci->description.isNotEmpty() ? ci->description
148 : ci->shortName;
149
150 return {};
151}
152
154{
155 StringArray s;
156
157 for (int i = 0; i < commands.size(); ++i)
158 s.addIfNotAlreadyThere (commands.getUnchecked (i)->categoryName, false);
159
160 return s;
161}
162
164{
165 Array<CommandID> results;
166
167 for (int i = 0; i < commands.size(); ++i)
168 if (commands.getUnchecked (i)->categoryName == categoryName)
169 results.add (commands.getUnchecked (i)->commandID);
170
171 return results;
172}
173
174//==============================================================================
182
184{
185 // This call isn't thread-safe for use from a non-UI thread without locking the message
186 // manager first..
188
189 bool ok = false;
191
192 if (auto* target = getTargetForCommand (inf.commandID, commandInfo))
193 {
195 info.commandFlags = commandInfo.flags;
196
197 sendListenerInvokeCallback (info);
198 ok = target->invoke (info, asynchronously);
200 }
201
202 return ok;
203}
204
205//==============================================================================
207{
208 return firstTarget != nullptr ? firstTarget
210}
211
216
219{
220 auto* target = getFirstCommandTarget (commandID);
221
222 if (target == nullptr)
224
225 if (target != nullptr)
226 target = target->getTargetForCommand (commandID);
227
228 if (target != nullptr)
229 {
230 upToDateInfo.commandID = commandID;
231 target->getCommandInfo (commandID, upToDateInfo);
232 }
233
234 return target;
235}
236
237//==============================================================================
239{
240 auto* target = dynamic_cast<ApplicationCommandTarget*> (c);
241
242 if (target == nullptr && c != nullptr)
244
245 return target;
246}
247
249{
251
252 if (c == nullptr)
253 {
255 {
256 if (auto* peer = activeWindow->getPeer())
257 {
258 c = peer->getLastFocusedSubcomponent();
259
260 if (c == nullptr)
261 c = activeWindow;
262 }
263 }
264 }
265
266 if (c == nullptr)
267 {
269
270 // getting a bit desperate now: try all desktop comps..
271 for (int i = desktop.getNumComponents(); --i >= 0;)
272 if (auto* component = desktop.getComponent (i))
273 if (detail::WindowingHelpers::isForegroundOrEmbeddedProcess (component))
274 if (auto* peer = component->getPeer())
275 if (auto* target = findTargetForComponent (peer->getLastFocusedSubcomponent()))
276 return target;
277 }
278
279 if (c != nullptr)
280 {
281 // if we're focused on a ResizableWindow, chances are that it's the content
282 // component that really should get the event. And if not, the event will
283 // still be passed up to the top level window anyway, so let's send it to the
284 // content comp.
285 if (auto* resizableWindow = dynamic_cast<ResizableWindow*> (c))
286 if (auto* content = resizableWindow->getContentComponent())
287 c = content;
288
289 if (auto* target = findTargetForComponent (c))
290 return target;
291 }
292
294}
295
296//==============================================================================
298{
299 listeners.add (listener);
300}
301
303{
304 listeners.remove (listener);
305}
306
307void ApplicationCommandManager::sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo& info)
308{
309 listeners.call ([&] (ApplicationCommandManagerListener& l) { l.applicationCommandInvoked (info); });
310}
311
312void ApplicationCommandManager::handleAsyncUpdate()
313{
314 listeners.call ([] (ApplicationCommandManagerListener& l) { l.applicationCommandListChanged(); });
315}
316
317void ApplicationCommandManager::globalFocusChanged (Component*)
318{
320}
321
322} // namespace juce
A listener that receives callbacks from an ApplicationCommandManager when commands are invoked or the...
void addListener(ApplicationCommandManagerListener *listener)
Registers a listener that will be called when various events occur.
ApplicationCommandTarget * getTargetForCommand(CommandID commandID, ApplicationCommandInfo &upToDateInfo)
Tries to find the best target to use to perform a given command.
static ApplicationCommandTarget * findTargetForComponent(Component *)
Examines this component and all its parents in turn, looking for the first one which is an Applicatio...
Array< CommandID > getCommandsInCategory(const String &categoryName) const
Returns a list of all the command UIDs in a particular category.
String getNameOfCommand(CommandID commandID) const noexcept
Returns the name field for a command.
static ApplicationCommandTarget * findDefaultComponentTarget()
Looks for a suitable command target based on which Components have the keyboard focus.
StringArray getCommandCategories() const
Returns the list of categories.
void setFirstCommandTarget(ApplicationCommandTarget *newTarget) noexcept
Sets a target to be returned by getFirstCommandTarget().
void registerCommand(const ApplicationCommandInfo &newCommand)
Adds a command to the list of registered commands.
ApplicationCommandManager()
Creates an ApplicationCommandManager.
bool invokeDirectly(CommandID commandID, bool asynchronously)
Invokes the given command directly, sending it to the default target.
void removeCommand(CommandID commandID)
Removes the command with a specified ID.
const ApplicationCommandInfo * getCommandForID(CommandID commandID) const noexcept
Returns the details about a given command ID.
bool invoke(const ApplicationCommandTarget::InvocationInfo &invocationInfo, bool asynchronously)
Sends a command to the default target.
void commandStatusChanged()
This should be called to tell the manager that one of its registered commands may have changed its ac...
void clearCommands()
Clears the current list of all commands.
virtual ApplicationCommandTarget * getFirstCommandTarget(CommandID commandID)
Chooses the ApplicationCommandTarget to which a command should be sent.
void removeListener(ApplicationCommandManagerListener *listener)
Deregisters a previously-added listener.
void registerAllCommandsForTarget(ApplicationCommandTarget *target)
Adds all the commands that this target publishes to the manager's list.
String getDescriptionOfCommand(CommandID commandID) const noexcept
Returns the description field for a command.
A command target publishes a list of command IDs that it can perform.
virtual void getCommandInfo(CommandID commandID, ApplicationCommandInfo &result)=0
This must provide details about one of the commands that this target can perform.
virtual void getAllCommands(Array< CommandID > &commands)=0
This must return a complete list of commands that this target can handle.
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:56
int size() const noexcept
Returns the current number of elements in the array.
Definition juce_Array.h:215
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition juce_Array.h:418
ElementType & getReference(int index) noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in.
Definition juce_Array.h:267
void triggerAsyncUpdate()
Causes the callback to be triggered at a later time.
The base class for all JUCE user-interface objects.
static Component *JUCE_CALLTYPE getCurrentlyFocusedComponent() noexcept
Returns the component that currently has the keyboard focus.
TargetClass * findParentComponentOfClass() const
Searches the parent components for a component of a specified class.
void removeFocusChangeListener(FocusChangeListener *listener)
Unregisters a FocusChangeListener that was added with addFocusChangeListener().
void addFocusChangeListener(FocusChangeListener *listener)
Registers a FocusChangeListener that will receive a callback whenever the focused component changes.
static Desktop &JUCE_CALLTYPE getInstance()
There's only one desktop object, and this method will return it.
static JUCEApplication *JUCE_CALLTYPE getInstance() noexcept
Returns the global instance of the application object being run.
Manages and edits a list of keypresses, which it uses to invoke the appropriate command in an Applica...
A base class for top-level windows that can be dragged around and resized.
A special array for holding a list of strings.
bool addIfNotAlreadyThere(const String &stringToAdd, bool ignoreCase=false)
Adds a string to the array as long as it's not already in there.
The JUCE String class!
Definition juce_String.h:53
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
static TopLevelWindow * getActiveTopLevelWindow() noexcept
Returns the currently-active top level window.
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
This macro is used to catch unsafe use of functions which expect to only be called on the message thr...
#define jassert(expression)
Platform-independent assertion macro.
JUCE Namespace.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
int CommandID
A type used to hold the unique ID for an application command.
Holds information describing an application command.
int flags
A bitwise-OR of the values specified in the CommandFlags enum.
Array< KeyPress > defaultKeypresses
A list of zero or more keypresses that should be used as the default keys for this command.
CommandID commandID
The command's unique ID number.
String categoryName
A named category that the command fits into.
@ wantsKeyUpDownCallbacks
If this flag is present, then when a KeyPressMappingSet invokes the command, it will call the command...
@ readOnlyInKeyEditor
If this flag is present, then a KeyMappingEditorComponent will display the command in its list,...
@ hiddenFromKeyEditor
If this flag is present, then a KeyMappingEditorComponent will not display the command in its list.
String shortName
A short name to describe the command.
Contains contextual details about the invocation of a command.
InvocationMethod invocationMethod
The type of event that triggered this command.
@ direct
The command is being invoked directly by a piece of code.