The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
6.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. BEGIN_JUCE_NAMESPACE
  19. //==============================================================================
  20. class ApplicationCommandTarget::MessageTarget : public MessageListener
  21. {
  22. public:
  23. MessageTarget (ApplicationCommandTarget& owner_)
  24. : owner (owner_)
  25. {
  26. }
  27. void handleMessage (const Message& message)
  28. {
  29. jassert (dynamic_cast <const InvokedMessage*> (&message) != nullptr);
  30. owner.tryToInvoke (dynamic_cast <const InvokedMessage&> (message).info, false);
  31. }
  32. struct InvokedMessage : public Message
  33. {
  34. InvokedMessage (const InvocationInfo& info_)
  35. : info (info_)
  36. {}
  37. const InvocationInfo info;
  38. private:
  39. JUCE_DECLARE_NON_COPYABLE (InvokedMessage);
  40. };
  41. private:
  42. ApplicationCommandTarget& owner;
  43. JUCE_DECLARE_NON_COPYABLE (MessageTarget);
  44. };
  45. //==============================================================================
  46. ApplicationCommandTarget::ApplicationCommandTarget()
  47. {
  48. }
  49. ApplicationCommandTarget::~ApplicationCommandTarget()
  50. {
  51. messageInvoker = nullptr;
  52. }
  53. //==============================================================================
  54. bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bool async)
  55. {
  56. if (isCommandActive (info.commandID))
  57. {
  58. if (async)
  59. {
  60. if (messageInvoker == nullptr)
  61. messageInvoker = new MessageTarget (*this);
  62. messageInvoker->postMessage (new MessageTarget::InvokedMessage (info));
  63. return true;
  64. }
  65. else
  66. {
  67. const bool success = perform (info);
  68. jassert (success); // hmm - your target should have been able to perform this command. If it can't
  69. // do it at the moment for some reason, it should clear the 'isActive' flag when it
  70. // returns the command's info.
  71. return success;
  72. }
  73. }
  74. return false;
  75. }
  76. ApplicationCommandTarget* ApplicationCommandTarget::findFirstTargetParentComponent()
  77. {
  78. Component* c = dynamic_cast <Component*> (this);
  79. if (c != nullptr)
  80. // (unable to use the syntax findParentComponentOfClass <ApplicationCommandTarget> () because of a VC6 compiler bug)
  81. return c->findParentComponentOfClass ((ApplicationCommandTarget*) nullptr);
  82. return nullptr;
  83. }
  84. ApplicationCommandTarget* ApplicationCommandTarget::getTargetForCommand (const CommandID commandID)
  85. {
  86. ApplicationCommandTarget* target = this;
  87. int depth = 0;
  88. while (target != nullptr)
  89. {
  90. Array <CommandID> commandIDs;
  91. target->getAllCommands (commandIDs);
  92. if (commandIDs.contains (commandID))
  93. return target;
  94. target = target->getNextCommandTarget();
  95. ++depth;
  96. jassert (depth < 100); // could be a recursive command chain??
  97. jassert (target != this); // definitely a recursive command chain!
  98. if (depth > 100 || target == this)
  99. break;
  100. }
  101. if (target == nullptr)
  102. {
  103. target = JUCEApplication::getInstance();
  104. if (target != nullptr)
  105. {
  106. Array <CommandID> commandIDs;
  107. target->getAllCommands (commandIDs);
  108. if (commandIDs.contains (commandID))
  109. return target;
  110. }
  111. }
  112. return nullptr;
  113. }
  114. bool ApplicationCommandTarget::isCommandActive (const CommandID commandID)
  115. {
  116. ApplicationCommandInfo info (commandID);
  117. info.flags = ApplicationCommandInfo::isDisabled;
  118. getCommandInfo (commandID, info);
  119. return (info.flags & ApplicationCommandInfo::isDisabled) == 0;
  120. }
  121. //==============================================================================
  122. bool ApplicationCommandTarget::invoke (const InvocationInfo& info, const bool async)
  123. {
  124. ApplicationCommandTarget* target = this;
  125. int depth = 0;
  126. while (target != nullptr)
  127. {
  128. if (target->tryToInvoke (info, async))
  129. return true;
  130. target = target->getNextCommandTarget();
  131. ++depth;
  132. jassert (depth < 100); // could be a recursive command chain??
  133. jassert (target != this); // definitely a recursive command chain!
  134. if (depth > 100 || target == this)
  135. break;
  136. }
  137. if (target == nullptr)
  138. {
  139. target = JUCEApplication::getInstance();
  140. if (target != nullptr)
  141. return target->tryToInvoke (info, async);
  142. }
  143. return false;
  144. }
  145. bool ApplicationCommandTarget::invokeDirectly (const CommandID commandID, const bool asynchronously)
  146. {
  147. ApplicationCommandTarget::InvocationInfo info (commandID);
  148. info.invocationMethod = ApplicationCommandTarget::InvocationInfo::direct;
  149. return invoke (info, asynchronously);
  150. }
  151. //==============================================================================
  152. ApplicationCommandTarget::InvocationInfo::InvocationInfo (const CommandID commandID_)
  153. : commandID (commandID_),
  154. commandFlags (0),
  155. invocationMethod (direct),
  156. originatingComponent (nullptr),
  157. isKeyDown (false),
  158. millisecsSinceKeyPressed (0)
  159. {
  160. }
  161. END_JUCE_NAMESPACE