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.

195 lines
6.1KB

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