2021-05-10 02:32:27 +08:00
|
|
|
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
|
2023-05-02 19:32:37 +08:00
|
|
|
#include <string> // for string
|
2020-03-27 06:33:55 +08:00
|
|
|
|
2022-04-28 16:43:31 +08:00
|
|
|
#include "ftxui/component/component.hpp" // for Horizontal, Vertical, Button, Tab
|
|
|
|
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
|
2021-07-10 19:20:43 +08:00
|
|
|
#include "ftxui/component/event.hpp" // for Event, Event::Tab, Event::TabReverse, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp
|
2023-05-02 19:32:37 +08:00
|
|
|
#include "gtest/gtest.h" // for AssertionResult, Message, TestPartResult, EXPECT_EQ, EXPECT_FALSE, Test, EXPECT_TRUE, TEST
|
2020-03-27 06:33:55 +08:00
|
|
|
|
2022-04-17 21:47:20 +08:00
|
|
|
namespace ftxui {
|
2020-03-27 06:33:55 +08:00
|
|
|
|
2022-04-17 21:47:20 +08:00
|
|
|
namespace {
|
2021-08-06 04:40:40 +08:00
|
|
|
Component Focusable() {
|
2021-08-09 06:27:37 +08:00
|
|
|
return Button("", [] {});
|
2021-08-06 04:40:40 +08:00
|
|
|
}
|
|
|
|
Component NonFocusable() {
|
|
|
|
return Container::Horizontal({});
|
|
|
|
}
|
2022-04-17 21:47:20 +08:00
|
|
|
} // namespace
|
2021-08-06 04:40:40 +08:00
|
|
|
|
2020-03-27 06:33:55 +08:00
|
|
|
TEST(ContainerTest, HorizontalEvent) {
|
2021-07-10 18:51:11 +08:00
|
|
|
auto container = Container::Horizontal({});
|
2021-08-06 04:40:40 +08:00
|
|
|
auto c0 = Focusable();
|
|
|
|
auto c1 = Focusable();
|
|
|
|
auto c2 = Focusable();
|
2021-05-10 02:32:27 +08:00
|
|
|
container->Add(c0);
|
|
|
|
container->Add(c1);
|
2021-08-06 04:40:40 +08:00
|
|
|
container->Add(NonFocusable());
|
|
|
|
container->Add(NonFocusable());
|
2021-05-10 02:32:27 +08:00
|
|
|
container->Add(c2);
|
2021-08-06 04:40:40 +08:00
|
|
|
container->Add(NonFocusable());
|
2020-03-27 06:33:55 +08:00
|
|
|
|
|
|
|
// With arrow key.
|
2021-05-10 02:32:27 +08:00
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::ArrowRight);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::ArrowRight);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::ArrowRight);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::ArrowLeft);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::ArrowLeft);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::ArrowLeft);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-03-27 06:33:55 +08:00
|
|
|
|
|
|
|
// With arrow key in the wrong dimension.
|
2021-05-10 02:32:27 +08:00
|
|
|
container->OnEvent(Event::ArrowUp);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::ArrowDown);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-03-27 06:33:55 +08:00
|
|
|
|
|
|
|
// With vim like characters.
|
2021-05-10 02:32:27 +08:00
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Character('l'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Character('l'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::Character('l'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::Character('h'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Character('h'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Character('h'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-03-27 06:33:55 +08:00
|
|
|
|
|
|
|
// With vim like characters in the wrong direction.
|
2021-05-10 02:32:27 +08:00
|
|
|
container->OnEvent(Event::Character('j'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Character('k'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-03-27 06:33:55 +08:00
|
|
|
|
|
|
|
// With tab characters.
|
2021-05-10 02:32:27 +08:00
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
2020-03-27 06:33:55 +08:00
|
|
|
}
|
2020-08-16 06:24:18 +08:00
|
|
|
|
2020-08-26 20:57:42 +08:00
|
|
|
TEST(ContainerTest, VerticalEvent) {
|
2021-07-10 18:51:11 +08:00
|
|
|
auto container = Container::Vertical({});
|
2021-08-06 04:40:40 +08:00
|
|
|
auto c0 = Focusable();
|
|
|
|
auto c1 = Focusable();
|
|
|
|
auto c2 = Focusable();
|
2021-05-10 02:32:27 +08:00
|
|
|
container->Add(c0);
|
|
|
|
container->Add(c1);
|
2021-08-06 04:40:40 +08:00
|
|
|
container->Add(NonFocusable());
|
|
|
|
container->Add(NonFocusable());
|
2021-05-10 02:32:27 +08:00
|
|
|
container->Add(c2);
|
2021-08-06 04:40:40 +08:00
|
|
|
container->Add(NonFocusable());
|
2020-08-26 20:57:42 +08:00
|
|
|
|
|
|
|
// With arrow key.
|
2021-05-10 02:32:27 +08:00
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::ArrowDown);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::ArrowDown);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::ArrowDown);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::ArrowUp);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::ArrowUp);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::ArrowUp);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-08-26 20:57:42 +08:00
|
|
|
|
|
|
|
// With arrow key in the wrong dimension.
|
2021-05-10 02:32:27 +08:00
|
|
|
container->OnEvent(Event::ArrowLeft);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::ArrowRight);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-08-26 20:57:42 +08:00
|
|
|
|
|
|
|
// With vim like characters.
|
2021-05-10 02:32:27 +08:00
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Character('j'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Character('j'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::Character('j'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::Character('k'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Character('k'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Character('k'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-08-26 20:57:42 +08:00
|
|
|
|
|
|
|
// With vim like characters in the wrong direction.
|
2021-05-10 02:32:27 +08:00
|
|
|
container->OnEvent(Event::Character('h'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Character('l'));
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
2020-08-26 20:57:42 +08:00
|
|
|
|
|
|
|
// With tab characters.
|
2021-05-10 02:32:27 +08:00
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::Tab);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
container->OnEvent(Event::TabReverse);
|
2020-08-26 20:57:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ContainerTest, SetActiveChild) {
|
2021-07-10 18:51:11 +08:00
|
|
|
auto container = Container::Horizontal({});
|
2021-08-06 04:40:40 +08:00
|
|
|
auto c0 = Focusable();
|
|
|
|
auto c1 = Focusable();
|
|
|
|
auto c2 = Focusable();
|
2021-05-10 02:32:27 +08:00
|
|
|
container->Add(c0);
|
|
|
|
container->Add(c1);
|
|
|
|
container->Add(c2);
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
EXPECT_TRUE(c0->Focused());
|
|
|
|
EXPECT_TRUE(c0->Active());
|
|
|
|
EXPECT_FALSE(c1->Focused());
|
|
|
|
EXPECT_FALSE(c1->Active());
|
|
|
|
EXPECT_FALSE(c2->Focused());
|
|
|
|
EXPECT_FALSE(c2->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
container->SetActiveChild(c0);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
EXPECT_TRUE(c0->Focused());
|
|
|
|
EXPECT_TRUE(c0->Active());
|
|
|
|
EXPECT_FALSE(c1->Focused());
|
|
|
|
EXPECT_FALSE(c1->Active());
|
|
|
|
EXPECT_FALSE(c2->Focused());
|
|
|
|
EXPECT_FALSE(c2->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
container->SetActiveChild(c1);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c1);
|
|
|
|
EXPECT_FALSE(c0->Focused());
|
|
|
|
EXPECT_FALSE(c0->Active());
|
|
|
|
EXPECT_TRUE(c1->Focused());
|
|
|
|
EXPECT_TRUE(c1->Active());
|
|
|
|
EXPECT_FALSE(c2->Focused());
|
|
|
|
EXPECT_FALSE(c2->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
container->SetActiveChild(c2);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c2);
|
|
|
|
EXPECT_FALSE(c0->Focused());
|
|
|
|
EXPECT_FALSE(c0->Active());
|
|
|
|
EXPECT_FALSE(c1->Focused());
|
|
|
|
EXPECT_FALSE(c1->Active());
|
|
|
|
EXPECT_TRUE(c2->Focused());
|
|
|
|
EXPECT_TRUE(c2->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
container->SetActiveChild(c0);
|
|
|
|
EXPECT_EQ(container->ActiveChild(), c0);
|
|
|
|
EXPECT_TRUE(c0->Focused());
|
|
|
|
EXPECT_TRUE(c0->Active());
|
|
|
|
EXPECT_FALSE(c1->Focused());
|
|
|
|
EXPECT_FALSE(c1->Active());
|
|
|
|
EXPECT_FALSE(c2->Focused());
|
|
|
|
EXPECT_FALSE(c2->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ContainerTest, TakeFocus) {
|
2021-07-10 18:51:11 +08:00
|
|
|
auto c = Container::Horizontal({});
|
|
|
|
auto c1 = Container::Vertical({});
|
|
|
|
auto c2 = Container::Vertical({});
|
|
|
|
auto c3 = Container::Vertical({});
|
2021-08-06 04:40:40 +08:00
|
|
|
auto c11 = Focusable();
|
|
|
|
auto c12 = Focusable();
|
|
|
|
auto c13 = Focusable();
|
|
|
|
auto c21 = Focusable();
|
|
|
|
auto c22 = Focusable();
|
|
|
|
auto c23 = Focusable();
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
c->Add(c1);
|
|
|
|
c->Add(c2);
|
|
|
|
c->Add(c3);
|
|
|
|
c1->Add(c11);
|
|
|
|
c1->Add(c12);
|
|
|
|
c1->Add(c13);
|
|
|
|
c2->Add(c21);
|
|
|
|
c2->Add(c22);
|
|
|
|
c2->Add(c23);
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
EXPECT_TRUE(c->Focused());
|
|
|
|
EXPECT_TRUE(c1->Focused());
|
|
|
|
EXPECT_FALSE(c2->Focused());
|
|
|
|
EXPECT_TRUE(c11->Focused());
|
|
|
|
EXPECT_FALSE(c12->Focused());
|
|
|
|
EXPECT_FALSE(c13->Focused());
|
|
|
|
EXPECT_FALSE(c21->Focused());
|
|
|
|
EXPECT_FALSE(c22->Focused());
|
|
|
|
EXPECT_FALSE(c23->Focused());
|
|
|
|
EXPECT_TRUE(c->Active());
|
|
|
|
EXPECT_TRUE(c1->Active());
|
|
|
|
EXPECT_FALSE(c2->Active());
|
|
|
|
EXPECT_TRUE(c11->Active());
|
|
|
|
EXPECT_FALSE(c12->Active());
|
|
|
|
EXPECT_FALSE(c13->Active());
|
|
|
|
EXPECT_TRUE(c21->Active());
|
|
|
|
EXPECT_FALSE(c22->Active());
|
|
|
|
EXPECT_FALSE(c23->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
c22->TakeFocus();
|
|
|
|
EXPECT_TRUE(c->Focused());
|
|
|
|
EXPECT_FALSE(c1->Focused());
|
|
|
|
EXPECT_TRUE(c2->Focused());
|
|
|
|
EXPECT_FALSE(c11->Focused());
|
|
|
|
EXPECT_FALSE(c12->Focused());
|
|
|
|
EXPECT_FALSE(c13->Focused());
|
|
|
|
EXPECT_FALSE(c21->Focused());
|
|
|
|
EXPECT_TRUE(c22->Focused());
|
|
|
|
EXPECT_FALSE(c23->Focused());
|
|
|
|
EXPECT_TRUE(c->Active());
|
|
|
|
EXPECT_FALSE(c1->Active());
|
|
|
|
EXPECT_TRUE(c2->Active());
|
|
|
|
EXPECT_TRUE(c11->Active());
|
|
|
|
EXPECT_FALSE(c12->Active());
|
|
|
|
EXPECT_FALSE(c13->Active());
|
|
|
|
EXPECT_FALSE(c21->Active());
|
|
|
|
EXPECT_TRUE(c22->Active());
|
|
|
|
EXPECT_FALSE(c23->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
|
2021-05-10 02:32:27 +08:00
|
|
|
c1->TakeFocus();
|
|
|
|
EXPECT_TRUE(c->Focused());
|
|
|
|
EXPECT_TRUE(c1->Focused());
|
|
|
|
EXPECT_FALSE(c2->Focused());
|
|
|
|
EXPECT_TRUE(c11->Focused());
|
|
|
|
EXPECT_FALSE(c12->Focused());
|
|
|
|
EXPECT_FALSE(c13->Focused());
|
|
|
|
EXPECT_FALSE(c21->Focused());
|
|
|
|
EXPECT_FALSE(c22->Focused());
|
|
|
|
EXPECT_FALSE(c23->Focused());
|
|
|
|
EXPECT_TRUE(c->Active());
|
|
|
|
EXPECT_TRUE(c1->Active());
|
|
|
|
EXPECT_FALSE(c2->Active());
|
|
|
|
EXPECT_TRUE(c11->Active());
|
|
|
|
EXPECT_FALSE(c12->Active());
|
|
|
|
EXPECT_FALSE(c13->Active());
|
|
|
|
EXPECT_FALSE(c21->Active());
|
|
|
|
EXPECT_TRUE(c22->Active());
|
|
|
|
EXPECT_FALSE(c23->Active());
|
2020-08-26 20:57:42 +08:00
|
|
|
}
|
|
|
|
|
2022-02-19 18:49:12 +08:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2022-04-17 21:47:20 +08:00
|
|
|
} // namespace ftxui
|
|
|
|
|
2020-08-16 06:24:18 +08:00
|
|
|
// 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.
|