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.

132 lines
4.1KB

  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. static int getOrder (const Component* c)
  24. {
  25. auto order = c->getExplicitFocusOrder();
  26. return order > 0 ? order : (std::numeric_limits<int>::max() / 2);
  27. }
  28. static void findAllFocusableComponents (Component* parent, Array<Component*>& comps)
  29. {
  30. if (parent->getNumChildComponents() != 0)
  31. {
  32. Array<Component*> localComps;
  33. for (auto* c : parent->getChildren())
  34. if (c->isVisible() && c->isEnabled())
  35. localComps.add (c);
  36. // This will sort so that they are ordered in terms of left-to-right
  37. // and then top-to-bottom.
  38. std::stable_sort (localComps.begin(), localComps.end(),
  39. [] (const Component* a, const Component* b)
  40. {
  41. auto explicitOrder1 = getOrder (a);
  42. auto explicitOrder2 = getOrder (b);
  43. if (explicitOrder1 != explicitOrder2)
  44. return explicitOrder1 < explicitOrder2;
  45. if (a->getY() != b->getY())
  46. return a->getY() < b->getY();
  47. return a->getX() < b->getX();
  48. });
  49. for (auto* c : localComps)
  50. {
  51. if (c->getWantsKeyboardFocus())
  52. comps.add (c);
  53. if (! c->isFocusContainer())
  54. findAllFocusableComponents (c, comps);
  55. }
  56. }
  57. }
  58. static Component* findFocusContainer (Component* c)
  59. {
  60. c = c->getParentComponent();
  61. if (c != nullptr)
  62. while (c->getParentComponent() != nullptr && ! c->isFocusContainer())
  63. c = c->getParentComponent();
  64. return c;
  65. }
  66. static Component* getIncrementedComponent (Component* current, int delta)
  67. {
  68. if (auto* focusContainer = findFocusContainer (current))
  69. {
  70. Array<Component*> comps;
  71. KeyboardFocusHelpers::findAllFocusableComponents (focusContainer, comps);
  72. if (! comps.isEmpty())
  73. {
  74. auto index = comps.indexOf (current);
  75. return comps [(index + comps.size() + delta) % comps.size()];
  76. }
  77. }
  78. return nullptr;
  79. }
  80. }
  81. //==============================================================================
  82. KeyboardFocusTraverser::KeyboardFocusTraverser() {}
  83. KeyboardFocusTraverser::~KeyboardFocusTraverser() {}
  84. Component* KeyboardFocusTraverser::getNextComponent (Component* current)
  85. {
  86. jassert (current != nullptr);
  87. return KeyboardFocusHelpers::getIncrementedComponent (current, 1);
  88. }
  89. Component* KeyboardFocusTraverser::getPreviousComponent (Component* current)
  90. {
  91. jassert (current != nullptr);
  92. return KeyboardFocusHelpers::getIncrementedComponent (current, -1);
  93. }
  94. Component* KeyboardFocusTraverser::getDefaultComponent (Component* parentComponent)
  95. {
  96. Array<Component*> comps;
  97. if (parentComponent != nullptr)
  98. KeyboardFocusHelpers::findAllFocusableComponents (parentComponent, comps);
  99. return comps.getFirst();
  100. }
  101. } // namespace juce