1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - 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 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-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 
26 namespace juce
27 {
28 
29 //==============================================================================
30 /**
31     A command target publishes a list of command IDs that it can perform.
32 
33     An ApplicationCommandManager despatches commands to targets, which must be
34     able to provide information about what commands they can handle.
35 
36     To create a target, you'll need to inherit from this class, implementing all of
37     its pure virtual methods.
38 
39     For info about how a target is chosen to receive a command, see
40     ApplicationCommandManager::getFirstCommandTarget().
41 
42     @see ApplicationCommandManager, ApplicationCommandInfo
43 
44     @tags{GUI}
45 */
46 class JUCE_API  ApplicationCommandTarget
47 {
48 public:
49     //==============================================================================
50     /** Creates a command target. */
51     ApplicationCommandTarget();
52 
53     /** Destructor. */
54     virtual ~ApplicationCommandTarget();
55 
56     //==============================================================================
57     /**
58         Contains contextual details about the invocation of a command.
59     */
60     struct JUCE_API  InvocationInfo
61     {
62         //==============================================================================
63         InvocationInfo (const CommandID commandID);
64 
65         //==============================================================================
66         /** The UID of the command that should be performed. */
67         CommandID commandID;
68 
69         /** The command's flags.
70             See ApplicationCommandInfo for a description of these flag values.
71         */
72         int commandFlags;
73 
74         //==============================================================================
75         /** The types of context in which the command might be called. */
76         enum InvocationMethod
77         {
78             direct = 0,     /**< The command is being invoked directly by a piece of code. */
79             fromKeyPress,   /**< The command is being invoked by a key-press. */
80             fromMenu,       /**< The command is being invoked by a menu selection. */
81             fromButton      /**< The command is being invoked by a button click. */
82         };
83 
84         /** The type of event that triggered this command. */
85         InvocationMethod invocationMethod;
86 
87         //==============================================================================
88         /** If triggered by a keypress or menu, this will be the component that had the
89             keyboard focus at the time.
90 
91             If triggered by a button, it may be set to that component, or it may be null.
92         */
93         Component* originatingComponent;
94 
95         //==============================================================================
96         /** The keypress that was used to invoke it.
97 
98             Note that this will be an invalid keypress if the command was invoked
99             by some other means than a keyboard shortcut.
100         */
101         KeyPress keyPress;
102 
103         /** True if the callback is being invoked when the key is pressed,
104             false if the key is being released.
105 
106             @see KeyPressMappingSet::addCommand()
107         */
108         bool isKeyDown;
109 
110         /** If the key is being released, this indicates how long it had been held
111             down for.
112 
113             (Only relevant if isKeyDown is false.)
114         */
115         int millisecsSinceKeyPressed;
116     };
117 
118     //==============================================================================
119     /** This must return the next target to try after this one.
120 
121         When a command is being sent, and the first target can't handle
122         that command, this method is used to determine the next target that should
123         be tried.
124 
125         It may return nullptr if it doesn't know of another target.
126 
127         If your target is a Component, you would usually use the findFirstTargetParentComponent()
128         method to return a parent component that might want to handle it.
129 
130         @see invoke
131     */
132     virtual ApplicationCommandTarget* getNextCommandTarget() = 0;
133 
134     /** This must return a complete list of commands that this target can handle.
135 
136         Your target should add all the command IDs that it handles to the array that is
137         passed-in.
138     */
139     virtual void getAllCommands (Array<CommandID>& commands) = 0;
140 
141     /** This must provide details about one of the commands that this target can perform.
142 
143         This will be called with one of the command IDs that the target provided in its
144         getAllCommands() methods.
145 
146         It should fill-in all appropriate fields of the ApplicationCommandInfo structure with
147         suitable information about the command. (The commandID field will already have been filled-in
148         by the caller).
149 
150         The easiest way to set the info is using the ApplicationCommandInfo::setInfo() method to
151         set all the fields at once.
152 
153         If the command is currently inactive for some reason, this method must use
154         ApplicationCommandInfo::setActive() to make that clear, (or it should set the isDisabled
155         bit of the ApplicationCommandInfo::flags field).
156 
157         Any default key-presses for the command should be appended to the
158         ApplicationCommandInfo::defaultKeypresses field.
159 
160         Note that if you change something that affects the status of the commands
161         that would be returned by this method (e.g. something that makes some commands
162         active or inactive), you should call ApplicationCommandManager::commandStatusChanged()
163         to cause the manager to refresh its status.
164     */
165     virtual void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result) = 0;
166 
167     /** This must actually perform the specified command.
168 
169         If this target is able to perform the command specified by the commandID field of the
170         InvocationInfo structure, then it should do so, and must return true.
171 
172         If it can't handle this command, it should return false, which tells the caller to pass
173         the command on to the next target in line.
174 
175         @see invoke, ApplicationCommandManager::invoke
176     */
177     virtual bool perform (const InvocationInfo& info) = 0;
178 
179     //==============================================================================
180     /** Makes this target invoke a command.
181 
182         Your code can call this method to invoke a command on this target, but normally
183         you'd call it indirectly via ApplicationCommandManager::invoke() or
184         ApplicationCommandManager::invokeDirectly().
185 
186         If this target can perform the given command, it will call its perform() method to
187         do so. If not, then getNextCommandTarget() will be used to determine the next target
188         to try, and the command will be passed along to it.
189 
190         @param invocationInfo       this must be correctly filled-in, describing the context for
191                                     the invocation.
192         @param asynchronously       if false, the command will be performed before this method returns.
193                                     If true, a message will be posted so that the command will be performed
194                                     later on the message thread, and this method will return immediately.
195         @see perform, ApplicationCommandManager::invoke
196     */
197     bool invoke (const InvocationInfo& invocationInfo,
198                  const bool asynchronously);
199 
200     /** Invokes a given command directly on this target.
201 
202         This is just an easy way to call invoke() without having to fill out the InvocationInfo
203         structure.
204     */
205     bool invokeDirectly (const CommandID commandID,
206                          const bool asynchronously);
207 
208     //==============================================================================
209     /** Searches this target and all subsequent ones for the first one that can handle
210         the specified command.
211 
212         This will use getNextCommandTarget() to determine the chain of targets to try
213         after this one.
214     */
215     ApplicationCommandTarget* getTargetForCommand (const CommandID commandID);
216 
217     /** Checks whether this command can currently be performed by this target.
218 
219         This will return true only if a call to getCommandInfo() doesn't set the
220         isDisabled flag to indicate that the command is inactive.
221     */
222     bool isCommandActive (const CommandID commandID);
223 
224     /** If this object is a Component, this method will search upwards in its current
225         UI hierarchy for the next parent component that implements the
226         ApplicationCommandTarget class.
227 
228         If your target is a Component, this is a very handy method to use in your
229         getNextCommandTarget() implementation.
230     */
231     ApplicationCommandTarget* findFirstTargetParentComponent();
232 
233 private:
234     //==============================================================================
235     class CommandMessage;
236     friend class CommandMessage;
237 
238     bool tryToInvoke (const InvocationInfo&, bool async);
239 
240     JUCE_DECLARE_WEAK_REFERENCEABLE (ApplicationCommandTarget)
241     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ApplicationCommandTarget)
242 };
243 
244 } // namespace juce
245