mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-26 04:31:34 +08:00
Improve ComponentBase and Container::Tab Focusable implementations (#341)
- Provide better defaults for ComponentBase `Focusable()` and `ActiveChild()` methods. This resolves: https://github.com/ArthurSonzogni/FTXUI/issues/335 - Implement `Container::Tab` 's `Focusable()` methods. This prevents the users to navigate into a tab with no interactivity.
This commit is contained in:
parent
f95ed885bb
commit
20f16b3984
@ -27,6 +27,9 @@ Element gaugeDirection(float ratio, GaugeDirection);
|
||||
### Component
|
||||
- Support SIGTSTP. (ctrl+z).
|
||||
- Support task posting. `ScreenInteractive::Post(Task)`.
|
||||
- **bugfix** Container::Tab implements `Focusable()`.
|
||||
- **bugfix** Improved default implementations of ComponentBase `Focusable()` and
|
||||
`ActiveChild()` methods.
|
||||
|
||||
2.0.0
|
||||
-----
|
||||
|
@ -105,7 +105,11 @@ bool ComponentBase::OnEvent(Event event) {
|
||||
/// @return the currently Active child.
|
||||
/// @ingroup component
|
||||
Component ComponentBase::ActiveChild() {
|
||||
return children_.empty() ? nullptr : children_.front();
|
||||
for (auto& child : children_) {
|
||||
if (child->Focusable())
|
||||
return child;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// @brief Return true when the component contains focusable elements.
|
||||
@ -128,14 +132,15 @@ bool ComponentBase::Active() const {
|
||||
|
||||
/// @brief Returns if the elements if focused by the user.
|
||||
/// True when the ComponentBase is focused by the user. An element is Focused
|
||||
/// when it is with all its ancestors the ActiveChild() of their parents.
|
||||
/// when it is with all its ancestors the ActiveChild() of their parents, and it
|
||||
/// Focusable().
|
||||
/// @ingroup component
|
||||
bool ComponentBase::Focused() const {
|
||||
auto current = this;
|
||||
while (current && current->Active()) {
|
||||
current = current->parent_;
|
||||
}
|
||||
return !current;
|
||||
return !current && Focusable();
|
||||
}
|
||||
|
||||
/// @brief Make the |child| to be the "active" one.
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <memory> // for shared_ptr, __shared_ptr_access, allocator, make_shared
|
||||
|
||||
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||
#include "ftxui/component/component.hpp" // for Make
|
||||
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
|
||||
#include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, SuiteApiResolver, TEST, TestFactoryImpl
|
||||
|
||||
@ -155,6 +156,22 @@ TEST(ContainerTest, ChildAt) {
|
||||
EXPECT_EQ(parent->ChildAt(0u), child_2);
|
||||
}
|
||||
|
||||
TEST(ComponentTest, NonFocusableAreNotFocused) {
|
||||
class NonFocusable : public ComponentBase {
|
||||
bool Focusable() const override { return false; }
|
||||
};
|
||||
auto root = Make<NonFocusable>();
|
||||
EXPECT_FALSE(root->Focused());
|
||||
EXPECT_EQ(root->ActiveChild(), nullptr);
|
||||
|
||||
auto child = Make<NonFocusable>();
|
||||
root->Add(child);
|
||||
EXPECT_FALSE(root->Focused());
|
||||
EXPECT_FALSE(child->Focused());
|
||||
EXPECT_EQ(root->ActiveChild(), nullptr);
|
||||
EXPECT_EQ(child->ActiveChild(), nullptr);
|
||||
}
|
||||
|
||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
@ -190,6 +190,12 @@ class TabContainer : public ContainerBase {
|
||||
return text("Empty container");
|
||||
}
|
||||
|
||||
bool Focusable() const override {
|
||||
if (children_.size() == 0)
|
||||
return false;
|
||||
return children_[*selector_ % children_.size()]->Focusable();
|
||||
}
|
||||
|
||||
bool OnMouseEvent(Event event) override {
|
||||
return ActiveChild()->OnEvent(event);
|
||||
}
|
||||
|
@ -305,6 +305,34 @@ TEST(ContainerTest, TakeFocus) {
|
||||
EXPECT_FALSE(c23->Active());
|
||||
}
|
||||
|
||||
TEST(ContainerTest, TabFocusable) {
|
||||
int selected = 0;
|
||||
auto c = Container::Tab(
|
||||
{
|
||||
Focusable(),
|
||||
NonFocusable(),
|
||||
Focusable(),
|
||||
NonFocusable(),
|
||||
},
|
||||
&selected);
|
||||
|
||||
selected = 0;
|
||||
EXPECT_TRUE(c->Focusable());
|
||||
EXPECT_TRUE(c->Focused());
|
||||
|
||||
selected = 1;
|
||||
EXPECT_FALSE(c->Focusable());
|
||||
EXPECT_FALSE(c->Focused());
|
||||
|
||||
selected = 2;
|
||||
EXPECT_TRUE(c->Focusable());
|
||||
EXPECT_TRUE(c->Focused());
|
||||
|
||||
selected = 3;
|
||||
EXPECT_FALSE(c->Focusable());
|
||||
EXPECT_FALSE(c->Focused());
|
||||
}
|
||||
|
||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
Loading…
Reference in New Issue
Block a user