Audio plugin host https://kx.studio/carla
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.

131 lines
4.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. namespace KeyboardFocusHelpers
  21. {
  22. static int getOrder (const Component* c)
  23. {
  24. auto order = c->getExplicitFocusOrder();
  25. return order > 0 ? order : (std::numeric_limits<int>::max() / 2);
  26. }
  27. static void findAllFocusableComponents (Component* parent, Array<Component*>& comps)
  28. {
  29. if (parent->getNumChildComponents() != 0)
  30. {
  31. Array<Component*> localComps;
  32. for (auto* c : parent->getChildren())
  33. if (c->isVisible() && c->isEnabled())
  34. localComps.add (c);
  35. // This will sort so that they are ordered in terms of left-to-right
  36. // and then top-to-bottom.
  37. std::stable_sort (localComps.begin(), localComps.end(),
  38. [] (const Component* a, const Component* b)
  39. {
  40. auto explicitOrder1 = getOrder (a);
  41. auto explicitOrder2 = getOrder (b);
  42. if (explicitOrder1 != explicitOrder2)
  43. return explicitOrder1 < explicitOrder2;
  44. if (a->getY() != b->getY())
  45. return a->getY() < b->getY();
  46. return a->getX() < b->getX();
  47. });
  48. for (auto* c : localComps)
  49. {
  50. if (c->getWantsKeyboardFocus())
  51. comps.add (c);
  52. if (! c->isFocusContainer())
  53. findAllFocusableComponents (c, comps);
  54. }
  55. }
  56. }
  57. static Component* findFocusContainer (Component* c)
  58. {
  59. c = c->getParentComponent();
  60. if (c != nullptr)
  61. while (c->getParentComponent() != nullptr && ! c->isFocusContainer())
  62. c = c->getParentComponent();
  63. return c;
  64. }
  65. static Component* getIncrementedComponent (Component* current, int delta)
  66. {
  67. if (auto* focusContainer = findFocusContainer (current))
  68. {
  69. Array<Component*> comps;
  70. KeyboardFocusHelpers::findAllFocusableComponents (focusContainer, comps);
  71. if (! comps.isEmpty())
  72. {
  73. auto index = comps.indexOf (current);
  74. return comps [(index + comps.size() + delta) % comps.size()];
  75. }
  76. }
  77. return nullptr;
  78. }
  79. }
  80. //==============================================================================
  81. KeyboardFocusTraverser::KeyboardFocusTraverser() {}
  82. KeyboardFocusTraverser::~KeyboardFocusTraverser() {}
  83. Component* KeyboardFocusTraverser::getNextComponent (Component* current)
  84. {
  85. jassert (current != nullptr);
  86. return KeyboardFocusHelpers::getIncrementedComponent (current, 1);
  87. }
  88. Component* KeyboardFocusTraverser::getPreviousComponent (Component* current)
  89. {
  90. jassert (current != nullptr);
  91. return KeyboardFocusHelpers::getIncrementedComponent (current, -1);
  92. }
  93. Component* KeyboardFocusTraverser::getDefaultComponent (Component* parentComponent)
  94. {
  95. Array<Component*> comps;
  96. if (parentComponent != nullptr)
  97. KeyboardFocusHelpers::findAllFocusableComponents (parentComponent, comps);
  98. return comps.getFirst();
  99. }
  100. } // namespace juce