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.

135 lines
4.2KB

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