juce_KeyboardFocusTraverser.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. namespace KeyboardFocusHelpers
  18. {
  19. // This will sort a set of components, so that they are ordered in terms of
  20. // left-to-right and then top-to-bottom.
  21. struct ScreenPositionComparator
  22. {
  23. static int compareElements (const Component* const first, const Component* const second)
  24. {
  25. const int explicitOrder1 = getOrder (first);
  26. const int explicitOrder2 = getOrder (second);
  27. if (explicitOrder1 != explicitOrder2)
  28. return explicitOrder1 - explicitOrder2;
  29. const int yDiff = first->getY() - second->getY();
  30. return yDiff == 0 ? first->getX() - second->getX()
  31. : yDiff;
  32. }
  33. static int getOrder (const Component* const c)
  34. {
  35. const int order = c->getExplicitFocusOrder();
  36. return order > 0 ? order : (std::numeric_limits<int>::max() / 2);
  37. }
  38. };
  39. static void findAllFocusableComponents (Component* const parent, Array <Component*>& comps)
  40. {
  41. if (parent->getNumChildComponents() > 0)
  42. {
  43. Array <Component*> localComps;
  44. ScreenPositionComparator comparator;
  45. for (int i = parent->getNumChildComponents(); --i >= 0;)
  46. {
  47. Component* const c = parent->getChildComponent (i);
  48. if (c->isVisible() && c->isEnabled())
  49. localComps.addSorted (comparator, c);
  50. }
  51. for (int i = 0; i < localComps.size(); ++i)
  52. {
  53. Component* const c = localComps.getUnchecked (i);
  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* const current, const int delta)
  70. {
  71. Component* focusContainer = findFocusContainer (current);
  72. if (focusContainer != nullptr)
  73. {
  74. Array <Component*> comps;
  75. KeyboardFocusHelpers::findAllFocusableComponents (focusContainer, comps);
  76. if (comps.size() > 0)
  77. {
  78. const int index = comps.indexOf (current);
  79. return comps [(index + comps.size() + delta) % comps.size()];
  80. }
  81. }
  82. return nullptr;
  83. }
  84. }
  85. //==============================================================================
  86. KeyboardFocusTraverser::KeyboardFocusTraverser() {}
  87. KeyboardFocusTraverser::~KeyboardFocusTraverser() {}
  88. Component* KeyboardFocusTraverser::getNextComponent (Component* current)
  89. {
  90. jassert (current != nullptr);
  91. return KeyboardFocusHelpers::getIncrementedComponent (current, 1);
  92. }
  93. Component* KeyboardFocusTraverser::getPreviousComponent (Component* current)
  94. {
  95. jassert (current != nullptr);
  96. return KeyboardFocusHelpers::getIncrementedComponent (current, -1);
  97. }
  98. Component* KeyboardFocusTraverser::getDefaultComponent (Component* parentComponent)
  99. {
  100. Array <Component*> comps;
  101. if (parentComponent != nullptr)
  102. KeyboardFocusHelpers::findAllFocusableComponents (parentComponent, comps);
  103. return comps.getFirst();
  104. }