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.

208 lines
6.2KB

  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. class ApplicationCommandTarget::MessageTarget : public MessageListener
  19. {
  20. public:
  21. MessageTarget (ApplicationCommandTarget& owner_)
  22. : owner (owner_)
  23. {
  24. }
  25. void handleMessage (const Message& message)
  26. {
  27. jassert (dynamic_cast <const InvokedMessage*> (&message) != nullptr);
  28. owner.tryToInvoke (dynamic_cast <const InvokedMessage&> (message).info, false);
  29. }
  30. struct InvokedMessage : public Message
  31. {
  32. InvokedMessage (const InvocationInfo& info_)
  33. : info (info_)
  34. {}
  35. const InvocationInfo info;
  36. private:
  37. JUCE_DECLARE_NON_COPYABLE (InvokedMessage);
  38. };
  39. private:
  40. ApplicationCommandTarget& owner;
  41. JUCE_DECLARE_NON_COPYABLE (MessageTarget);
  42. };
  43. //==============================================================================
  44. ApplicationCommandTarget::ApplicationCommandTarget()
  45. {
  46. }
  47. ApplicationCommandTarget::~ApplicationCommandTarget()
  48. {
  49. messageInvoker = nullptr;
  50. }
  51. //==============================================================================
  52. bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bool async)
  53. {
  54. if (isCommandActive (info.commandID))
  55. {
  56. if (async)
  57. {
  58. if (messageInvoker == nullptr)
  59. messageInvoker = new MessageTarget (*this);
  60. messageInvoker->postMessage (new MessageTarget::InvokedMessage (info));
  61. return true;
  62. }
  63. else
  64. {
  65. const bool success = perform (info);
  66. jassert (success); // hmm - your target should have been able to perform this command. If it can't
  67. // do it at the moment for some reason, it should clear the 'isActive' flag when it
  68. // returns the command's info.
  69. return success;
  70. }
  71. }
  72. return false;
  73. }
  74. ApplicationCommandTarget* ApplicationCommandTarget::findFirstTargetParentComponent()
  75. {
  76. Component* c = dynamic_cast <Component*> (this);
  77. if (c != nullptr)
  78. // (unable to use the syntax findParentComponentOfClass <ApplicationCommandTarget> () because of a VC6 compiler bug)
  79. return c->findParentComponentOfClass ((ApplicationCommandTarget*) nullptr);
  80. return nullptr;
  81. }
  82. ApplicationCommandTarget* ApplicationCommandTarget::getTargetForCommand (const CommandID commandID)
  83. {
  84. ApplicationCommandTarget* target = this;
  85. int depth = 0;
  86. while (target != nullptr)
  87. {
  88. Array <CommandID> commandIDs;
  89. target->getAllCommands (commandIDs);
  90. if (commandIDs.contains (commandID))
  91. return target;
  92. target = target->getNextCommandTarget();
  93. ++depth;
  94. jassert (depth < 100); // could be a recursive command chain??
  95. jassert (target != this); // definitely a recursive command chain!
  96. if (depth > 100 || target == this)
  97. break;
  98. }
  99. if (target == nullptr)
  100. {
  101. target = JUCEApplication::getInstance();
  102. if (target != nullptr)
  103. {
  104. Array <CommandID> commandIDs;
  105. target->getAllCommands (commandIDs);
  106. if (commandIDs.contains (commandID))
  107. return target;
  108. }
  109. }
  110. return nullptr;
  111. }
  112. bool ApplicationCommandTarget::isCommandActive (const CommandID commandID)
  113. {
  114. ApplicationCommandInfo info (commandID);
  115. info.flags = ApplicationCommandInfo::isDisabled;
  116. getCommandInfo (commandID, info);
  117. return (info.flags & ApplicationCommandInfo::isDisabled) == 0;
  118. }
  119. //==============================================================================
  120. bool ApplicationCommandTarget::invoke (const InvocationInfo& info, const bool async)
  121. {
  122. ApplicationCommandTarget* target = this;
  123. int depth = 0;
  124. while (target != nullptr)
  125. {
  126. if (target->tryToInvoke (info, async))
  127. return true;
  128. target = target->getNextCommandTarget();
  129. ++depth;
  130. jassert (depth < 100); // could be a recursive command chain??
  131. jassert (target != this); // definitely a recursive command chain!
  132. if (depth > 100 || target == this)
  133. break;
  134. }
  135. if (target == nullptr)
  136. {
  137. target = JUCEApplication::getInstance();
  138. if (target != nullptr)
  139. return target->tryToInvoke (info, async);
  140. }
  141. return false;
  142. }
  143. bool ApplicationCommandTarget::invokeDirectly (const CommandID commandID, const bool asynchronously)
  144. {
  145. ApplicationCommandTarget::InvocationInfo info (commandID);
  146. info.invocationMethod = ApplicationCommandTarget::InvocationInfo::direct;
  147. return invoke (info, asynchronously);
  148. }
  149. //==============================================================================
  150. ApplicationCommandTarget::InvocationInfo::InvocationInfo (const CommandID commandID_)
  151. : commandID (commandID_),
  152. commandFlags (0),
  153. invocationMethod (direct),
  154. originatingComponent (nullptr),
  155. isKeyDown (false),
  156. millisecsSinceKeyPressed (0)
  157. {
  158. }