33 auto order =
c->getExplicitFocusOrder();
34 return order > 0 ? order : std::numeric_limits<int>::max();
37 template <
typename FocusContainerFn>
39 std::vector<Component*>& components,
40 FocusContainerFn isFocusContainer)
42 if (
parent ==
nullptr ||
parent->getNumChildComponents() == 0)
45 std::vector<Component*> localComponents;
47 for (
auto*
c :
parent->getChildren())
48 if (
c->isVisible() &&
c->isEnabled())
49 localComponents.push_back (
c);
53 const auto getComponentOrderAttributes = [] (
const Component*
c)
56 c->isAlwaysOnTop() ? 0 : 1,
61 return getComponentOrderAttributes (
a) < getComponentOrderAttributes (
b);
66 std::stable_sort (localComponents.begin(), localComponents.end(), compareComponents);
68 for (
auto*
c : localComponents)
70 components.push_back (
c);
72 if (! (
c->*isFocusContainer)())
79 template <
typename FocusContainerFn>
83 FocusContainerFn isFocusContainer)
85 if (focusContainer !=
nullptr)
87 std::vector<Component*> components;
90 const auto iter = std::find (components.cbegin(), components.cend(), current);
92 if (iter == components.cend())
98 if (iter != std::prev (components.cend()))
99 return *std::next (iter);
104 if (iter != components.cbegin())
105 return *std::prev (iter);
138 if (parentComponent !=
nullptr)
140 std::vector<Component*> components;
145 if (! components.empty())
146 return components.front();
154 std::vector<Component*> components;
166struct FocusTraverserTests :
public UnitTest
168 FocusTraverserTests()
172 void runTest()
override
174 ScopedJuceInitialiser_GUI libraryInitialiser;
175 const MessageManagerLock mml;
177 beginTest (
"Basic traversal");
181 expect (traverser.getDefaultComponent (&
parent) == &
parent.children.front());
183 for (
auto iter =
parent.children.begin(); iter !=
parent.children.end(); ++iter)
184 expect (traverser.getNextComponent (&(*iter)) == (iter == std::prev (
parent.children.cend()) ?
nullptr
185 : &(*std::next (iter))));
187 for (
auto iter =
parent.children.rbegin(); iter !=
parent.children.rend(); ++iter)
188 expect (traverser.getPreviousComponent (&(*iter)) == (iter == std::prev (
parent.children.rend()) ?
nullptr
189 : &(*std::next (iter))));
190 auto allComponents = traverser.getAllComponents (&
parent);
192 expect (std::equal (allComponents.cbegin(), allComponents.cend(),
parent.children.cbegin(),
193 [] (
const Component* c1,
const Component&
c2) { return c1 == &c2; }));
196 beginTest (
"Disabled components are ignored");
198 checkIgnored ([] (Component&
c) {
c.setEnabled (
false); });
201 beginTest (
"Invisible components are ignored");
203 checkIgnored ([] (Component&
c) {
c.setVisible (
false); });
206 beginTest (
"Explicit focus order comes before unspecified");
210 auto& explicitFocusComponent =
parent.children[2];
212 explicitFocusComponent.setExplicitFocusOrder (1);
213 expect (traverser.getDefaultComponent (&
parent) == &explicitFocusComponent);
215 expect (traverser.getAllComponents (&
parent).front() == &explicitFocusComponent);
218 beginTest (
"Explicit focus order comparison");
220 checkComponentProperties ([
this] (Component& child) { child.setExplicitFocusOrder (getRandom().nextInt ({ 1, 100 })); },
221 [] (
const Component& c1,
const Component&
c2) {
return c1.getExplicitFocusOrder()
222 <=
c2.getExplicitFocusOrder(); });
225 beginTest (
"Left to right");
227 checkComponentProperties ([
this] (Component& child) { child.setTopLeftPosition (getRandom().nextInt ({ 0, 100 }), 0); },
228 [] (
const Component& c1,
const Component&
c2) {
return c1.getX() <=
c2.getX(); });
231 beginTest (
"Top to bottom");
233 checkComponentProperties ([
this] (Component& child) { child.setTopLeftPosition (0, getRandom().nextInt ({ 0, 100 })); },
234 [] (
const Component& c1,
const Component&
c2) {
return c1.getY() <=
c2.getY(); });
237 beginTest (
"Focus containers have their own focus");
241 TestComponent container;
242 container.setFocusContainerType (Component::FocusContainerType::focusContainer);
244 root.addAndMakeVisible (container);
246 expect (traverser.getDefaultComponent (&root) == &container);
247 expect (traverser.getNextComponent (&container) ==
nullptr);
248 expect (traverser.getPreviousComponent (&container) ==
nullptr);
250 expect (traverser.getDefaultComponent (&container) == &container.children.front());
252 for (
auto iter = container.children.begin(); iter != container.children.end(); ++iter)
253 expect (traverser.getNextComponent (&(*iter)) == (iter == std::prev (container.children.cend()) ?
nullptr
254 : &(*std::next (iter))));
256 for (
auto iter = container.children.rbegin(); iter != container.children.rend(); ++iter)
257 expect (traverser.getPreviousComponent (&(*iter)) == (iter == std::prev (container.children.rend()) ?
nullptr
258 : &(*std::next (iter))));
260 expect (traverser.getAllComponents (&root).size() == 1);
262 auto allContainerComponents = traverser.getAllComponents (&container);
264 expect (std::equal (allContainerComponents.cbegin(), allContainerComponents.cend(), container.children.cbegin(),
265 [] (
const Component* c1,
const Component&
c2) { return c1 == &c2; }));
268 beginTest (
"Non-focus containers pass-through focus");
272 TestComponent container;
273 container.setFocusContainerType (Component::FocusContainerType::none);
275 root.addAndMakeVisible (container);
277 expect (traverser.getDefaultComponent (&root) == &container);
278 expect (traverser.getNextComponent (&container) == &container.children.front());
279 expect (traverser.getPreviousComponent (&container) ==
nullptr);
281 expect (traverser.getDefaultComponent (&container) == &container.children.front());
283 for (
auto iter = container.children.begin(); iter != container.children.end(); ++iter)
284 expect (traverser.getNextComponent (&(*iter)) == (iter == std::prev (container.children.cend()) ?
nullptr
285 : &(*std::next (iter))));
287 for (
auto iter = container.children.rbegin(); iter != container.children.rend(); ++iter)
288 expect (traverser.getPreviousComponent (&(*iter)) == (iter == std::prev (container.children.rend()) ? &container
289 : &(*std::next (iter))));
291 expect (traverser.getAllComponents (&root).size() == container.children.size() + 1);
296 struct TestComponent :
public Component
300 for (
auto& child : children)
301 addAndMakeVisible (child);
304 std::array<Component, 10> children;
307 void checkComponentProperties (std::function<
void (Component&)>&& childFn,
308 std::function<
bool (
const Component&,
const Component&)>&& testProperty)
312 for (
auto& child :
parent.children)
315 auto*
comp = traverser.getDefaultComponent (&
parent);
317 for (
const auto& child :
parent.children)
319 expect (testProperty (*
comp, child));
323 auto* next = traverser.getNextComponent (
comp);
328 expect (testProperty (*
comp, *next));
333 void checkIgnored (
const std::function<
void(Component&)>& makeIgnored)
337 auto iter =
parent.children.begin();
340 expect (traverser.getDefaultComponent (&
parent) == std::addressof (*std::next (iter)));
344 expect (traverser.getNextComponent (std::addressof (*std::prev (iter))) == std::addressof (*std::next (iter)));
345 expect (traverser.getPreviousComponent (std::addressof (*std::next (iter))) == std::addressof (*std::prev (iter)));
347 auto allComponents = traverser.getAllComponents (&
parent);
349 expect (std::find (allComponents.cbegin(), allComponents.cend(), &
parent.children.front()) == allComponents.cend());
350 expect (std::find (allComponents.cbegin(), allComponents.cend(), std::addressof (*iter)) == allComponents.cend());
353 FocusTraverser traverser;
356static FocusTraverserTests focusTraverserTests;
uint8_t a
Definition Spc_Cpu.h:141
Definition juce_Component.h:36
Component * findFocusContainer() const
Definition juce_Component.cpp:2894
bool isFocusContainer() const noexcept
Definition juce_Component.cpp:2870
std::vector< Component * > getAllComponents(Component *parentComponent) override
Definition juce_FocusTraverser.cpp:152
Component * getDefaultComponent(Component *parentComponent) override
Definition juce_FocusTraverser.cpp:136
Component * getPreviousComponent(Component *current) override
Definition juce_FocusTraverser.cpp:126
Component * getNextComponent(Component *current) override
Definition juce_FocusTraverser.cpp:116
Definition juce_UnitTest.h:70
static void c2(register WDL_FFT_COMPLEX *a)
Definition fft.c:270
static uintptr_t parent
Definition pugl.h:1644
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
Definition juce_FocusTraverser.cpp:30
NavigationDirection
Definition juce_FocusTraverser.cpp:77
@ backwards
Definition juce_FocusTraverser.cpp:77
@ forwards
Definition juce_FocusTraverser.cpp:77
static Component * navigateFocus(Component *current, Component *focusContainer, NavigationDirection direction, FocusContainerFn isFocusContainer)
Definition juce_FocusTraverser.cpp:80
static void findAllComponents(Component *parent, std::vector< Component * > &components, FocusContainerFn isFocusContainer)
Definition juce_FocusTraverser.cpp:38
static int getOrder(const Component *c)
Definition juce_FocusTraverser.cpp:31
Definition juce_UnitTestCategories.h:27
Definition carla_juce.cpp:31
GUI::ui_handle_t gui
Definition main.cpp:50
return c
Definition crypt.c:175