Make component more functionnal

This commit is contained in:
ArthurSonzogni 2021-05-09 20:32:27 +02:00
parent 9d15d1c275
commit 6d75cb2748
No known key found for this signature in database
GPG Key ID: 41D98248C074CD6C
70 changed files with 2182 additions and 1769 deletions

View File

@ -80,6 +80,7 @@ add_library(component
include/ftxui/component/captured_mouse.hpp include/ftxui/component/captured_mouse.hpp
include/ftxui/component/checkbox.hpp include/ftxui/component/checkbox.hpp
include/ftxui/component/component.hpp include/ftxui/component/component.hpp
include/ftxui/component/component_base.hpp
include/ftxui/component/container.hpp include/ftxui/component/container.hpp
include/ftxui/component/event.hpp include/ftxui/component/event.hpp
include/ftxui/component/input.hpp include/ftxui/component/input.hpp
@ -88,7 +89,6 @@ add_library(component
include/ftxui/component/radiobox.hpp include/ftxui/component/radiobox.hpp
include/ftxui/component/receiver.hpp include/ftxui/component/receiver.hpp
include/ftxui/component/screen_interactive.hpp include/ftxui/component/screen_interactive.hpp
include/ftxui/component/slider.hpp
include/ftxui/component/toggle.hpp include/ftxui/component/toggle.hpp
src/ftxui/component/button.cpp src/ftxui/component/button.cpp
src/ftxui/component/checkbox.cpp src/ftxui/component/checkbox.cpp

View File

@ -34,6 +34,7 @@
@example ./examples/component/input.cpp @example ./examples/component/input.cpp
@example ./examples/component/homescreen.cpp @example ./examples/component/homescreen.cpp
@example ./examples/component/radiobox.cpp @example ./examples/component/radiobox.cpp
@example ./examples/component/slider_rgb.cpp
@example ./examples/component/menu.cpp @example ./examples/component/menu.cpp
@example ./examples/component/menu_style.cpp @example ./examples/component/menu_style.cpp
@example ./examples/component/radiobox_in_frame.cpp @example ./examples/component/radiobox_in_frame.cpp

View File

@ -31,7 +31,7 @@ int main(void) {
Dimension::Fit(document) // Height Dimension::Fit(document) // Height
); );
Render(screen, document); Render(screen, document);
std::cout << screen.ToString() << std::endl; screen.Print();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -142,6 +142,13 @@ This provides:
3. A predefined implementation of "keyboard navigation". 3. A predefined implementation of "keyboard navigation".
4. A set of predefined widget: CheckBox, RadioBox, Input, Menu, Toggle. 4. A set of predefined widget: CheckBox, RadioBox, Input, Menu, Toggle.
**List of Component**
You only need one header: ftxui/dom/component.hpp
\include ftxui/component/component.hpp
# ftxui/dom # ftxui/dom
Every elements of the dom are declared from: Every elements of the dom are declared from:

View File

@ -17,6 +17,7 @@ example(modal_dialog)
example(radiobox) example(radiobox)
example(radiobox_in_frame) example(radiobox_in_frame)
example(slider) example(slider)
example(slider_rgb)
example(tab_horizontal) example(tab_horizontal)
example(tab_vertical) example(tab_vertical)
example(toggle) example(toggle)

View File

@ -1,51 +1,43 @@
#include <functional> // for function #include <string> // for operator+, to_wstring, allocator, wstring
#include <memory> // for unique_ptr, make_u...
#include <string> // for wstring
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/component/button.hpp" // for Button #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/component.hpp" // for Button, Make
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/container.hpp" // for Container
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/dom/elements.hpp" // for separator, Element, gauge, text, operator|, vbox, border
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
private: private:
std::vector<std::unique_ptr<Button>> buttons_; std::wstring label_add = L"Increase";
Container container_ = Container::Horizontal(); std::wstring label_rm = L"Decrease";
int value_ = 50;
public: public:
MyComponent() { MyComponent() {
Add(&container_); Add(Container::Horizontal({
Button(&label_rm, [&] { value_--; }),
Button(&label_add, [&] { value_++; }),
}));
}
auto button_add = std::make_unique<Button>(); Element Render() override {
auto button_remove = std::make_unique<Button>(); return vbox({
container_.Add(button_add.get()); text(L"Value = " + std::to_wstring(value_)),
container_.Add(button_remove.get()); separator(),
button_add->label = L"Add one button"; gauge(value_ * 0.01f),
button_remove->label = L"Remove last button"; separator(),
ComponentBase::Render(),
button_add->on_click = [&] { }) |
auto extra_button = std::make_unique<Button>(); border;
extra_button->label = L"extra button";
container_.Add(extra_button.get());
buttons_.push_back(std::move(extra_button));
};
button_remove->on_click = [&] { buttons_.resize(buttons_.size() - 1); };
buttons_.push_back(std::move(button_add));
buttons_.push_back(std::move(button_remove));
} }
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::FitComponent();
MyComponent component; screen.Loop(Make<MyComponent>());
screen.Loop(&component);
return 0; return 0;
} }

View File

@ -1,34 +1,34 @@
#include "ftxui/component/checkbox.hpp" #include "ftxui/component/checkbox.hpp"
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component.hpp" // for Checkbox, Make
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/container.hpp" // for Container
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive, Component
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
private: private:
CheckBox box_1_; std::wstring build_examples_label = L"Build examples";
CheckBox box_2_; std::wstring build_tests_label = L"Build tests";
CheckBox box_3_; std::wstring use_webassembly_label = L"Use WebAssembly";
Container container_ = Container::Vertical();
bool build_examples_state = false;
bool build_tests_state = false;
bool use_webassembly_state = true;
Component container = Container::Vertical({
Checkbox(&build_examples_label, &build_examples_state),
Checkbox(&build_tests_label, &build_tests_state),
Checkbox(&use_webassembly_label, &use_webassembly_state),
});
public: public:
MyComponent() { MyComponent() { Add(container); }
Add(&container_);
container_.Add(&box_1_);
container_.Add(&box_2_);
container_.Add(&box_3_);
box_1_.label = L"Build examples";
box_2_.label = L"Build tests";
box_3_.label = L"Use WebAssembly";
box_3_.state = true;
}
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent component; screen.Loop(Make<MyComponent>());
screen.Loop(&component);
return 0; return 0;
} }

View File

@ -1,50 +1,61 @@
#include <memory> // for allocator_traits<>... #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <string> // for operator+, wstring #include <memory> // for unique_ptr, make_unique, __shared_ptr_access
#include <utility> // for move #include <string> // for operator+, wstring
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/checkbox.hpp" // for CheckBox #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/component.hpp" // for Checkbox, Make
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/container.hpp" // for Container
#include "ftxui/dom/elements.hpp" // for Element, operator| #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/dom/elements.hpp" // for Element, operator|, size, vbox, border, frame, Elements, HEIGHT, LESS_THAN
#include "ftxui/screen/string.hpp" // for to_wstring #include "ftxui/screen/string.hpp" // for to_wstring
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { struct CheckboxAndState {
std::wstring label;
bool state;
Component component;
};
std::unique_ptr<CheckboxAndState> MakeCheckbox(std::wstring label) {
auto out = std::make_unique<CheckboxAndState>();
out->label = label;
out->state = false;
out->component = Checkbox(&out->label, &out->state);
return out;
}
class MyComponent : public ComponentBase {
public: public:
MyComponent() { MyComponent() {
Add(&container); Add(container);
checkbox.resize(30); checkbox.resize(30);
for (int i = 0; i < checkbox.size(); ++i) { for (int i = 0; i < checkbox.size(); ++i) {
checkbox[i].label = (L"CheckBox " + to_wstring(i)); checkbox[i] = MakeCheckbox(L"CheckBox " + to_wstring(i));
container.Add(&checkbox[i]); container->Add(checkbox[i]->component);
} }
} }
// clang-format off // clang-format off
Element Render() override { Element Render() override {
Elements content; Elements content;
for (auto& it : checkbox) { return vbox(container->Render())
content.push_back(it.Render());
}
return vbox(std::move(content))
| frame | frame
| size(HEIGHT, LESS_THAN, 10) | size(HEIGHT, LESS_THAN, 10)
| border; | border;
} }
private: private:
std::vector<CheckBox> checkbox; std::vector<std::unique_ptr<CheckboxAndState>> checkbox;
Container container = Container::Vertical(); Component container = Container::Vertical();
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::FitComponent(); auto screen = ScreenInteractive::FitComponent();
MyComponent component; auto my_component = Make<MyComponent>();
screen.Loop(&component); screen.Loop(my_component);
return 0; return 0;
} }

View File

@ -1,82 +1,81 @@
#include <functional> // for function #include <functional> // for function
#include <memory> // for allocator, unique_ptr #include <memory> // for allocator, __shared_ptr_access
#include <string> // for wstring #include <string> // for wstring, basic_string
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/button.hpp" // for Button #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/checkbox.hpp" // for CheckBox #include "ftxui/component/component.hpp" // for Slider, Checkbox, Button, Input, Make, Menu, Radiobox, Toggle
#include "ftxui/component/component.hpp" // for Component, Compone... #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/container.hpp" // for Container
#include "ftxui/component/input.hpp" // for Input #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/component/menu.hpp" // for Menu #include "ftxui/dom/elements.hpp" // for separator, operator|, Element, size, xflex, text, WIDTH, hbox, vbox, EQUAL, LESS_THAN, border, GREATER_THAN
#include "ftxui/component/radiobox.hpp" // for RadioBox
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/component/slider.hpp" // for Slider
#include "ftxui/component/toggle.hpp" // for Toggle
#include "ftxui/dom/elements.hpp" // for separator, operator|
#include "ftxui/screen/box.hpp" // for ftxui
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
Container container = Container::Vertical(); const std::vector<std::wstring> menu_entries_ = {
Menu menu; L"Menu 1",
Toggle toggle; L"Menu 2",
Container checkbox_container = Container::Vertical(); L"Menu 3",
CheckBox checkbox1; L"Menu 4",
CheckBox checkbox2; };
RadioBox radiobox; int menu_selected_ = 0;
Input input; Component menu_ = Menu(&menu_entries_, &menu_selected_);
Button button;
int toggle_selected_ = 0;
std::vector<std::wstring> toggle_entries_ = {
L"Toggle_1",
L"Toggle_2",
};
Component toggle_ = Toggle(&toggle_entries_, &toggle_selected_);
std::wstring checkbox_1_label_ = L"checkbox1";
std::wstring checkbox_2_label_ = L"checkbox2";
bool checkbox_1_selected_ = false;
bool checkbox_2_selected_ = false;
Component checkbox_container_ = Container::Vertical({
Checkbox(&checkbox_1_label_, &checkbox_1_selected_),
Checkbox(&checkbox_2_label_, &checkbox_2_selected_),
});
int radiobox_selected_ = 0;
std::vector<std::wstring> radiobox_entries_ = {
L"Radiobox 1",
L"Radiobox 2",
L"Radiobox 3",
L"Radiobox 4",
};
Component radiobox_ = Radiobox(&radiobox_entries_, &radiobox_selected_);
std::wstring input_label_;
std::wstring input_placeholder_ = L"input";
Component input_ = Input(&input_label_, &input_placeholder_);
std::wstring button_label_ = L"Quit";
std::function<void()> on_button_clicked_;
Component button_ = Button(&button_label_, [this] { on_button_clicked_(); });
int slider_value_1_ = 12; int slider_value_1_ = 12;
int slider_value_2_ = 56; int slider_value_2_ = 56;
int slider_value_3_ = 128; int slider_value_3_ = 128;
ComponentPtr slider_1_ = Slider(L"R:", &slider_value_1_, 0, 256, 1); Component slider_container_ = Container::Vertical({
ComponentPtr slider_2_ = Slider(L"G:", &slider_value_2_, 0, 256, 1); Slider(L"R:", &slider_value_1_, 0, 256, 1),
ComponentPtr slider_3_ = Slider(L"B:", &slider_value_3_, 0, 256, 1); Slider(L"G:", &slider_value_2_, 0, 256, 1),
Slider(L"B:", &slider_value_3_, 0, 256, 1),
});
public: public:
MyComponent() { MyComponent(std::function<void(void)> on_quit) : on_quit_(on_quit) {
Add(&container); Add(Container::Vertical({
menu.entries = { menu_,
L"Menu 1", toggle_,
L"Menu 2", checkbox_container_,
L"Menu 3", radiobox_,
L"Menu 4", input_,
}; slider_container_,
container.Add(&menu); button_,
}));
toggle.entries = {
L"Toggle_1",
L"Toggle_2",
};
container.Add(&toggle);
container.Add(&checkbox_container);
checkbox1.label = L"checkbox1";
checkbox_container.Add(&checkbox1);
checkbox2.label = L"checkbox2";
checkbox_container.Add(&checkbox2);
radiobox.entries = {
L"Radiobox 1",
L"Radiobox 2",
L"Radiobox 3",
L"Radiobox 4",
};
container.Add(&radiobox);
input.placeholder = L"Input placeholder";
container.Add(&input);
container.Add(slider_1_.get());
container.Add(slider_2_.get());
container.Add(slider_3_.get());
button.label = L"Quit";
button.on_click = [&] { on_quit(); };
container.Add(&button);
} }
Element Render(std::wstring name, Element element) { Element Render(std::wstring name, Element element) {
@ -89,42 +88,36 @@ class MyComponent : public Component {
} }
Element Render(std::wstring name, Component& component) { Element Render(std::wstring name, Component& component) {
return Render(name, component.Render()); return Render(name, component->Render());
} }
Element Render() override { Element Render() override {
return // return //
vbox({ vbox({
Render(L"menu", menu), Render(L"menu", menu_),
separator(), separator(),
Render(L"toggle", toggle), Render(L"toggle", toggle_),
separator(), separator(),
Render(L"checkbox", checkbox_container), Render(L"checkbox", checkbox_container_),
separator(), separator(),
Render(L"radiobox", radiobox), Render(L"radiobox", radiobox_),
separator(), separator(),
Render(L"input", input) | size(WIDTH, LESS_THAN, 50), Render(L"input", input_) | size(WIDTH, LESS_THAN, 50),
separator(), separator(),
Render(L"slider", // Render(L"slider", slider_container_),
vbox({
slider_1_->Render(),
slider_2_->Render(),
slider_3_->Render(),
})),
separator(), separator(),
Render(L"button", button), Render(L"button", button_),
}) | }) |
xflex | size(WIDTH, GREATER_THAN, 40) | border; xflex | size(WIDTH, GREATER_THAN, 40) | border;
} }
std::function<void()> on_quit = [] {}; std::function<void()> on_quit_;
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::FitComponent(); auto screen = ScreenInteractive::FitComponent();
MyComponent component; auto component = Make<MyComponent>(screen.ExitLoopClosure());
component.on_quit = screen.ExitLoopClosure(); screen.Loop(component);
screen.Loop(&component);
return 0; return 0;
} }

View File

@ -1,23 +1,22 @@
#include <chrono> // for operator""s, chron... #include <array> // for array
#include <chrono> // for operator""s, chrono_literals
#include <cmath> // for sin #include <cmath> // for sin
#include <functional> // for ref, reference_wra... #include <functional> // for ref, reference_wrapper, function
#include <string> // for allocator, wstring #include <memory> // for make_shared, __shared_ptr_access
#include <thread> // for sleep_for, thread #include <string> // for allocator, wstring, basic_string, operator+, to_wstring
#include <utility> // for move #include <thread> // for sleep_for, thread
#include <vector> // for vector #include <utility> // for move
#include <vector> // for vector
#include "ftxui/component/checkbox.hpp" // for CheckBox #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/component.hpp" // for Checkbox, Input, Menu, Radiobox, Toggle
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/event.hpp" // for Event, Event::Custom #include "ftxui/component/container.hpp" // for Container
#include "ftxui/component/input.hpp" // for Input #include "ftxui/component/event.hpp" // for Event, Event::Custom
#include "ftxui/component/menu.hpp" // for Menu #include "ftxui/component/input.hpp" // for InputBase
#include "ftxui/component/radiobox.hpp" // for RadioBox #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/dom/elements.hpp" // for text, operator|, color, bgcolor, Element, filler, size, vbox, flex, hbox, graph, separator, EQUAL, WIDTH, hcenter, bold, border, window, Elements, HEIGHT, hflow, flex_grow, frame, gauge, LESS_THAN, spinner, dim, GREATER_THAN
#include "ftxui/component/toggle.hpp" // for Toggle #include "ftxui/screen/color.hpp" // for Color, Color::BlueLight, Color::RedLight, Color::Black, Color::Blue, Color::Cyan, Color::CyanLight, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::White, Color::Yellow, Color::YellowLight, Color::Default
#include "ftxui/dom/elements.hpp" // for text, operator|
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color, Color::Blue...
using namespace ftxui; using namespace ftxui;
@ -39,7 +38,7 @@ class Graph {
} }
}; };
class HTopComponent : public Component { class HTopComponent : public ComponentBase {
Graph my_graph; Graph my_graph;
public: public:
@ -102,110 +101,121 @@ class HTopComponent : public Component {
} }
}; };
class CompilerComponent : public Component { const std::vector<std::wstring> compiler_entries = {
Container container = Container::Horizontal(); L"gcc",
RadioBox compiler; L"clang",
Container flag = Container::Vertical(); L"emcc",
CheckBox flag_checkbox[4]; L"game_maker",
Container subcontainer = Container::Vertical(); L"Ada compilers",
Container input_container = Container::Horizontal(); L"ALGOL 60 compilers",
Input input_add; L"ALGOL 68 compilers",
Menu input; L"Assemblers (Intel *86)",
Input executable; L"Assemblers (Motorola 68*)",
L"Assemblers (Zilog Z80)",
L"Assemblers (other)",
L"BASIC Compilers",
L"BASIC interpreters",
L"Batch compilers",
L"C compilers",
L"Source-to-source compilers",
L"C++ compilers",
L"C# compilers",
L"COBOL compilers",
L"Common Lisp compilers",
L"D compilers",
L"DIBOL/DBL compilers",
L"ECMAScript interpreters",
L"Eiffel compilers",
L"Fortran compilers",
L"Go compilers",
L"Haskell compilers",
L"Java compilers",
L"Pascal compilers",
L"Perl Interpreters",
L"PHP compilers",
L"PL/I compilers",
L"Python compilers",
L"Scheme compilers and interpreters",
L"Smalltalk compilers",
L"Tcl Interpreters",
L"VMS Interpreters",
L"Rexx Interpreters",
L"CLI compilers",
};
class CompilerComponent : public ComponentBase {
int compiler_selected = 0;
Component compiler = Radiobox(&compiler_entries, &compiler_selected);
std::array<std::wstring, 4> options_label = {
L"-Wall",
L"-Werror",
L"-lpthread",
L"-O3",
};
std::array<bool, 4> options_state = {
false,
false,
false,
false,
};
std::wstring input_add_content = L"";
std::wstring input_add_placeholder = L"input_files";
Component input_add = Input(&input_add_content, &input_add_placeholder);
std::vector<std::wstring> input_entries;
int input_selected = 0;
Component input = Menu(&input_entries, &input_selected);
std::wstring executable_content_ = L"";
std::wstring executable_placeholder_ = L"executable";
Component executable_ = Input(&executable_content_, &executable_placeholder_);
Component flags = Container::Vertical({
Checkbox(&options_label[0], &options_state[0]),
Checkbox(&options_label[1], &options_state[1]),
Checkbox(&options_label[2], &options_state[2]),
Checkbox(&options_label[3], &options_state[3]),
});
public: public:
~CompilerComponent() override {} ~CompilerComponent() override {}
CompilerComponent() { CompilerComponent() {
Add(&container); Add(Container::Horizontal({
compiler,
flags,
Container::Vertical({
executable_,
Container::Horizontal({
input_add,
input,
}),
}),
}));
// Compiler ---------------------------------------------------------------- InputBase::From(input_add)->on_enter = [this] {
compiler.entries = { input_entries.push_back(input_add_content);
L"gcc", input_add_content = L"";
L"clang",
L"emcc",
L"game_maker",
L"Ada compilers",
L"ALGOL 60 compilers",
L"ALGOL 68 compilers",
L"Assemblers (Intel *86)",
L"Assemblers (Motorola 68*)",
L"Assemblers (Zilog Z80)",
L"Assemblers (other)",
L"BASIC Compilers",
L"BASIC interpreters",
L"Batch compilers",
L"C compilers",
L"Source-to-source compilers",
L"C++ compilers",
L"C# compilers",
L"COBOL compilers",
L"Common Lisp compilers",
L"D compilers",
L"DIBOL/DBL compilers",
L"ECMAScript interpreters",
L"Eiffel compilers",
L"Fortran compilers",
L"Go compilers",
L"Haskell compilers",
L"Java compilers",
L"Pascal compilers",
L"Perl Interpreters",
L"PHP compilers",
L"PL/I compilers",
L"Python compilers",
L"Scheme compilers and interpreters",
L"Smalltalk compilers",
L"Tcl Interpreters",
L"VMS Interpreters",
L"Rexx Interpreters",
L"CLI compilers",
}; };
container.Add(&compiler);
// Flags ----------------------------------------------------------------
container.Add(&flag);
flag_checkbox[0].label = L"-Wall";
flag_checkbox[1].label = L"-Werror";
flag_checkbox[2].label = L"-lpthread";
flag_checkbox[3].label = L"-O3";
for (auto& c : flag_checkbox)
flag.Add(&c);
container.Add(&subcontainer);
// Executable
// ----------------------------------------------------------------
executable.placeholder = L"executable";
subcontainer.Add(&executable);
// Input ----------------------------------------------------------------
subcontainer.Add(&input_container);
input_add.placeholder = L"input files";
input_add.on_enter = [this] {
input.entries.push_back(input_add.content);
input_add.content = L"";
};
input_container.Add(&input_add);
input_container.Add(&input);
} }
Element Render() override { Element Render() override {
auto compiler_win = window(text(L"Compiler"), compiler.Render() | frame); auto compiler_win = window(text(L"Compiler"), compiler->Render() | frame);
auto flags_win = window(text(L"Flags"), flag.Render()); auto flags_win = window(text(L"Flags"), flags->Render());
auto executable_win = window(text(L"Executable:"), executable.Render()); auto executable_win = window(text(L"Executable:"), executable_->Render());
auto input_win = auto input_win =
window(text(L"Input"), window(text(L"Input"),
hbox({ hbox({
vbox({ vbox({
hbox({ hbox({
text(L"Add: "), text(L"Add: "),
input_add.Render(), input_add->Render(),
}) | size(WIDTH, EQUAL, 20) | }) | size(WIDTH, EQUAL, 20) |
size(HEIGHT, EQUAL, 1), size(HEIGHT, EQUAL, 1),
filler(), filler(),
}), }),
separator(), separator(),
input.Render() | frame | size(HEIGHT, EQUAL, 3) | flex, input->Render() | frame | size(HEIGHT, EQUAL, 3) | flex,
})); }));
return vbox({ return vbox({
hbox({ hbox({
@ -225,28 +235,29 @@ class CompilerComponent : public Component {
Elements RenderCommandLine() { Elements RenderCommandLine() {
Elements line; Elements line;
// Compiler // Compiler
line.push_back(text(compiler.entries[compiler.selected]) | bold); line.push_back(text(compiler_entries[compiler_selected]) | bold);
// flags // flags
for (auto& it : flag_checkbox) { for (int i = 0; i < 4; ++i) {
if (it.state) { if (options_state[i]) {
line.push_back(text(L" ")); line.push_back(text(L" "));
line.push_back(text(it.label) | dim); line.push_back(text(options_label[i]) | dim);
} }
} }
// Executable // Executable
if (!executable.content.empty()) { if (!executable_content_.empty()) {
line.push_back(text(L" -O ") | bold); line.push_back(text(L" -O ") | bold);
line.push_back(text(executable.content) | color(Color::BlueLight) | bold); line.push_back(text(executable_content_) | color(Color::BlueLight) |
bold);
} }
// Input // Input
for (auto& it : input.entries) { for (auto& it : input_entries) {
line.push_back(text(L" " + it) | color(Color::RedLight)); line.push_back(text(L" " + it) | color(Color::RedLight));
} }
return line; return line;
} }
}; };
class SpinnerComponent : public Component { class SpinnerComponent : public ComponentBase {
Element Render() override { Element Render() override {
Elements entries; Elements entries;
for (int i = 0; i < 22; ++i) { for (int i = 0; i < 22; ++i) {
@ -258,7 +269,7 @@ class SpinnerComponent : public Component {
} }
}; };
class ColorComponent : public Component { class ColorComponent : public ComponentBase {
Element Render() override { Element Render() override {
return hbox({ return hbox({
vbox({ vbox({
@ -304,7 +315,7 @@ class ColorComponent : public Component {
} }
}; };
class GaugeComponent : public Component { class GaugeComponent : public ComponentBase {
Element RenderGauge(int delta) { Element RenderGauge(int delta) {
float progress = (shift + delta) % 1000 / 1000.f; float progress = (shift + delta) % 1000 / 1000.f;
return hbox({ return hbox({
@ -337,38 +348,35 @@ class GaugeComponent : public Component {
}; };
}; };
class Tab : public Component { class Tab : public ComponentBase {
public: public:
Container main_container = Container::Vertical(); int tab_index = 0;
std::vector<std::wstring> tab_entries = {
L"htop", L"color", L"spinner", L"gauge", L"compiler",
};
Component tab_selection = Toggle(&tab_entries, &tab_index);
Component container =
Container::Tab(&tab_index,
{
std::make_shared<HTopComponent>(),
std::make_shared<ColorComponent>(),
std::make_shared<SpinnerComponent>(),
std::make_shared<GaugeComponent>(),
std::make_shared<CompilerComponent>(),
});
Toggle tab_selection; Component main_container = Container::Vertical({
Container container = Container::Tab(&tab_selection.selected); tab_selection,
container,
});
HTopComponent htop_component; Tab() { Add(main_container); }
ColorComponent color_component;
SpinnerComponent spinner_component;
GaugeComponent gauge_component;
CompilerComponent compiler_component;
Tab() {
Add(&main_container);
main_container.Add(&tab_selection);
tab_selection.entries = {
L"htop", L"color", L"spinner", L"gauge", L"compiler",
};
main_container.Add(&container);
container.Add(&htop_component);
container.Add(&color_component);
container.Add(&spinner_component);
container.Add(&gauge_component);
container.Add(&compiler_component);
}
Element Render() override { Element Render() override {
return vbox({ return vbox({
text(L"FTXUI Demo") | bold | hcenter, text(L"FTXUI Demo") | bold | hcenter,
tab_selection.Render() | hcenter, tab_selection->Render() | hcenter,
container.Render() | flex, container->Render() | flex,
}); });
} }
}; };
@ -385,8 +393,8 @@ int main(int argc, const char* argv[]) {
} }
}); });
Tab tab; Component tab = std::make_shared<Tab>();
screen.Loop(&tab); screen.Loop(tab);
return 0; return 0;
} }

View File

@ -1,44 +1,45 @@
#include "ftxui/component/input.hpp" #include <memory> // for allocator, __shared_ptr_access
#include "ftxui/component/container.hpp" // for Container #include <string> // for operator+, wstring, char_traits
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Input, Make
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/container.hpp" // for Container
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, hbox, separator, border, vbox, Element
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
public:
MyComponent() {
Add(&container);
container.Add(&input_1);
container.Add(&input_2);
container.Add(&input_3);
input_1.placeholder = L"input1";
input_2.placeholder = L"input2";
input_3.placeholder = L"input3";
}
std::function<void()> on_enter = []() {};
private: private:
Container container = Container::Vertical(); std::wstring first_name_;
Input input_1; std::wstring last_name_;
Input input_2; std::wstring first_name_placeholder_ = L"first_name";
Input input_3; std::wstring last_name_placeholder_ = L"last_name";
Component input_first_name_ = Input(&first_name_, &first_name_placeholder_);
Component input_last_name_ = Input(&last_name_, &last_name_placeholder_);
Element Render() override { Element Render() override {
return border(vbox({ return border(vbox({
hbox({text(L" input_1 : "), input_1.Render()}), text(L"Hello " + first_name_ + L" " + last_name_),
hbox({text(L" input_2 : "), input_2.Render()}), separator(),
hbox({text(L" input_3 : "), input_3.Render()}), hbox({text(L" First name : "), input_first_name_->Render()}),
hbox({text(L" Last name : "), input_last_name_->Render()}),
}));
}
public:
MyComponent() {
Add(Container::Vertical({
input_first_name_,
input_last_name_,
})); }));
} }
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent component; screen.Loop(Make<MyComponent>());
component.on_enter = screen.ExitLoopClosure();
screen.Loop(&component);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,24 +1,30 @@
#include <functional> // for function #include <functional> // for function
#include <iostream> // for basic_ostream::ope... #include <iostream> // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream
#include <string> // for wstring, allocator #include <string> // for wstring, allocator, basic_string
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/menu.hpp" // for Menu #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Menu
#include "ftxui/component/menu.hpp" // for MenuBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
using namespace ftxui; using namespace ftxui;
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
Menu menu; std::vector<std::wstring> entries = {
menu.entries = {L"entry 1", L"entry 2", L"entry 3"}; L"entry 1",
menu.selected = 0; L"entry 2",
menu.on_enter = screen.ExitLoopClosure(); L"entry 3",
};
int selected = 0;
screen.Loop(&menu); auto menu = Menu(&entries, &selected);
MenuBase::From(menu)->on_enter = screen.ExitLoopClosure();
std::cout << "Selected element = " << menu.selected << std::endl; screen.Loop(menu);
std::cout << "Selected element = " << selected << std::endl;
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,84 +1,88 @@
#include <functional> // for function #include <functional> // for function
#include <string> // for wstring, allocator #include <memory> // for __shared_ptr_access, shared_ptr
#include <vector> // for vector #include <string> // for wstring, allocator, operator+, to_string, basic_string
#include <vector> // for vector
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component.hpp" // for Menu, Make
#include "ftxui/component/menu.hpp" // for Menu #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/container.hpp" // for Container
#include "ftxui/dom/elements.hpp" // for text, separator, bold #include "ftxui/component/menu.hpp" // for MenuBase
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/screen/string.hpp" // for to_wstring #include "ftxui/dom/elements.hpp" // for text, separator, bold, hcenter, vbox, hbox, gauge, Element, operator|, border
#include "ftxui/screen/string.hpp" // for to_wstring
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
public:
MyComponent() {
Add(&container);
container.Add(&left_menu);
container.Add(&right_menu);
left_menu.entries = {
L"0%", L"10%", L"20%", L"30%", L"40%",
L"50%", L"60%", L"70%", L"80%", L"90%",
};
right_menu.entries = {
L"0%", L"1%", L"2%", L"3%", L"4%", L"5%",
L"6%", L"7%", L"8%", L"9%", L"10%",
};
left_menu.on_enter = [this]() { on_enter(); };
right_menu.on_enter = [this]() { on_enter(); };
}
std::function<void()> on_enter = []() {};
private: private:
Container container = Container::Horizontal(); std::vector<std::wstring> left_menu_entries = {
Menu left_menu; L"0%", L"10%", L"20%", L"30%", L"40%",
Menu right_menu; L"50%", L"60%", L"70%", L"80%", L"90%",
};
std::vector<std::wstring> right_menu_entries = {
L"0%", L"1%", L"2%", L"3%", L"4%", L"5%",
L"6%", L"7%", L"8%", L"9%", L"10%",
};
int left_menu_selected = 0;
int right_menu_selected = 0;
Component left_menu_ = Menu(&left_menu_entries, &left_menu_selected);
Component right_menu_ = Menu(&right_menu_entries, &right_menu_selected);
Component container = Container::Horizontal({
left_menu_,
right_menu_,
});
Element Render() override { Element Render() override {
int sum = left_menu.selected * 10 + right_menu.selected; int sum = left_menu_selected * 10 + right_menu_selected;
return border(vbox({ return vbox({
// -------- Top panel -------------- // -------- Top panel --------------
hbox({ hbox({
// -------- Left Menu -------------- // -------- Left Menu --------------
vbox({ vbox({
hcenter(bold(text(L"Percentage by 10%"))), hcenter(bold(text(L"Percentage by 10%"))),
separator(), separator(),
left_menu.Render(), left_menu_->Render(),
}) | flex, }),
// -------- Right Menu -------------- separator(),
vbox({ // -------- Right Menu --------------
hcenter(bold(text(L"Percentage by 1%"))), vbox({
separator(), hcenter(bold(text(L"Percentage by 1%"))),
right_menu.Render(), separator(),
}) | flex, right_menu_->Render(),
filler(), }),
}), separator(),
separator(), }),
// -------- Bottom panel -------------- separator(),
vbox({ // -------- Bottom panel --------------
hbox({ vbox({
text(L" gauge : "), hbox({
gauge(sum / 100.0), text(L" gauge : "),
}), gauge(sum / 100.0),
hbox({ }),
text(L" text : "), hbox({
text(to_wstring(std::to_string(sum) + " %")), text(L" text : "),
}), text(to_wstring(std::to_string(sum) + " %")),
}) | flex, }),
})); }),
}) |
border;
} }
public:
MyComponent() {
Add(container);
MenuBase::From(left_menu_)->on_enter = [this]() { on_enter(); };
MenuBase::From(right_menu_)->on_enter = [this]() { on_enter(); };
}
std::function<void()> on_enter = []() {};
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent component; auto component = Make<MyComponent>();
component.on_enter = screen.ExitLoopClosure(); component->on_enter = screen.ExitLoopClosure();
screen.Loop(&component); screen.Loop(component);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,92 +1,100 @@
#include <functional> // for function #include <functional> // for function
#include <initializer_list> // for initializer_list #include <initializer_list> // for initializer_list
#include <string> // for wstring, allocator #include <memory> // for __shared_ptr_access
#include <string> // for wstring, allocator, basic_string
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component.hpp" // for Menu, Make
#include "ftxui/component/menu.hpp" // for Menu #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/container.hpp" // for Container
#include "ftxui/dom/elements.hpp" // for operator|, Element #include "ftxui/component/menu.hpp" // for MenuBase
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/screen/color.hpp" // for Color, Color::Blue #include "ftxui/dom/elements.hpp" // for operator|, Element, separator, bgcolor, color, flex, Decorator, bold, hbox, border, dim
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::BlueLight, Color::Red, Color::Yellow
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { std::vector<std::wstring> entries = {
L"Monkey", L"Dog", L"Cat", L"Bird", L"Elephant",
};
class MyComponent : public ComponentBase {
public: public:
MyComponent() { MyComponent(std::function<void(void)> exit) {
Add(&container); on_enter_ = exit;
for (Menu* menu : { Add(container);
&menu_1,
&menu_2,
&menu_3,
&menu_4,
&menu_5,
&menu_6,
}) {
container.Add(menu);
menu->entries = {
L"Monkey", L"Dog", L"Cat", L"Bird", L"Elephant",
};
menu->on_enter = [this]() { on_enter(); };
}
menu_2.focused_style = bold | color(Color::Blue); for (Component menu :
menu_2.selected_style = color(Color::Blue); {menu_1_, menu_2_, menu_3_, menu_4_, menu_5_, menu_6_})
menu_2.selected_focused_style = bold | color(Color::Blue); MenuBase::From(menu)->on_enter = [this] { on_enter_(); };
menu_3.selected_style = color(Color::Blue); MenuBase::From(menu_2_)->focused_style = bold | color(Color::Blue);
menu_3.focused_style = bgcolor(Color::Blue); MenuBase::From(menu_2_)->selected_style = color(Color::Blue);
menu_3.selected_focused_style = bgcolor(Color::Blue); MenuBase::From(menu_2_)->selected_focused_style = bold | color(Color::Blue);
menu_4.selected_style = bgcolor(Color::Blue); MenuBase::From(menu_3_)->selected_style = color(Color::Blue);
menu_4.focused_style = bgcolor(Color::BlueLight); MenuBase::From(menu_3_)->focused_style = bgcolor(Color::Blue);
menu_4.selected_focused_style = bgcolor(Color::BlueLight); MenuBase::From(menu_3_)->selected_focused_style = bgcolor(Color::Blue);
menu_5.normal_style = bgcolor(Color::Blue); MenuBase::From(menu_4_)->selected_style = bgcolor(Color::Blue);
menu_5.selected_style = bgcolor(Color::Yellow); MenuBase::From(menu_4_)->focused_style = bgcolor(Color::BlueLight);
menu_5.focused_style = bgcolor(Color::Red); MenuBase::From(menu_4_)->selected_focused_style = bgcolor(Color::BlueLight);
menu_5.selected_focused_style = bgcolor(Color::Red);
menu_6.normal_style = dim | color(Color::Blue); MenuBase::From(menu_5_)->normal_style = bgcolor(Color::Blue);
menu_6.selected_style = color(Color::Blue); MenuBase::From(menu_5_)->selected_style = bgcolor(Color::Yellow);
menu_6.focused_style = bold | color(Color::Blue); MenuBase::From(menu_5_)->focused_style = bgcolor(Color::Red);
menu_6.selected_focused_style = bold | color(Color::Blue); MenuBase::From(menu_5_)->selected_focused_style = bgcolor(Color::Red);
MenuBase::From(menu_6_)->normal_style = dim | color(Color::Blue);
MenuBase::From(menu_6_)->selected_style = color(Color::Blue);
MenuBase::From(menu_6_)->focused_style = bold | color(Color::Blue);
MenuBase::From(menu_6_)->selected_focused_style = bold | color(Color::Blue);
} }
std::function<void()> on_enter = []() {}; std::function<void()> on_enter_;
private: private:
Container container = Container::Horizontal(); int menu_1_selected_ = 0;
Menu menu_1; int menu_2_selected_ = 0;
Menu menu_2; int menu_3_selected_ = 0;
Menu menu_3; int menu_4_selected_ = 0;
Menu menu_4; int menu_5_selected_ = 0;
Menu menu_5; int menu_6_selected_ = 0;
Menu menu_6; Component menu_1_ = Menu(&entries, &menu_1_selected_);
Component menu_2_ = Menu(&entries, &menu_2_selected_);
Component menu_3_ = Menu(&entries, &menu_3_selected_);
Component menu_4_ = Menu(&entries, &menu_4_selected_);
Component menu_5_ = Menu(&entries, &menu_5_selected_);
Component menu_6_ = Menu(&entries, &menu_6_selected_);
Component container = Container::Horizontal({
menu_1_,
menu_2_,
menu_3_,
menu_4_,
menu_5_,
menu_6_,
});
// clang-format off // clang-format off
Element Render() override { Element Render() override {
return return
hbox({ hbox({
menu_1.Render() | flex, separator(), menu_1_->Render() | flex, separator(),
menu_2.Render() | flex, separator(), menu_2_->Render() | flex, separator(),
menu_3.Render() | flex, separator(), menu_3_->Render() | flex, separator(),
menu_4.Render() | flex, separator(), menu_4_->Render() | flex, separator(),
menu_5.Render() | flex, separator(), menu_5_->Render() | flex, separator(),
menu_6.Render() | flex, menu_6_->Render() | flex,
}) | border; }) | border;
} }
// clang-format on // clang-format on
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent component; screen.Loop(Make<MyComponent>(screen.ExitLoopClosure()));
component.on_enter = screen.ExitLoopClosure();
screen.Loop(&component);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,132 +1,130 @@
#include <functional> // for function #include <functional> // for function
#include <memory> // for allocator_traits<>... #include <memory> // for allocator, __shared_ptr_access, shared_ptr, make_shared
#include <string> // for operator+, wstring #include <string> // for wstring, operator+, basic_string, char_traits
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/button.hpp" // for Button #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/component.hpp" // for Button, Make
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/container.hpp" // for Container
#include "ftxui/dom/elements.hpp" // for Element, operator| #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/dom/elements.hpp" // for Element, operator|, filler, text, hbox, separator, center, vbox, bold, border, clear_under, dbox, size, GREATER_THAN, HEIGHT
using namespace ftxui; using namespace ftxui;
// The main screen, at depth 0. It display the main content. // The main screen, at depth 0. It display the main content.
class Content : public Component { class Content : public ComponentBase {
private:
std::wstring label_rate_ftxui_ = L"Rate FTXUI";
std::wstring label_quit_ = L"Quit";
bool modal_open_ = false;
Component button_rate_ftxui_ =
Button(&label_rate_ftxui_, [this] { on_rate_ftxui(); });
Component button_quit_ = Button(&label_quit_, [this] { on_quit(); });
Component container_ = Container::Horizontal({
button_rate_ftxui_,
button_quit_,
});
public: public:
std::function<void()> on_rate_ftxui = [] {}; std::wstring rating = L"3/5 stars";
std::function<void()> on_quit = [] {}; std::function<void()> on_rate_ftxui;
std::wstring rating_ = L"3/5 stars"; std::function<void()> on_quit;
Content() {
Add(&container_); Content() { Add(container_); }
container_.Add(&button_rate_ftxui);
container_.Add(&button_quit_);
button_rate_ftxui.on_click = [&] { on_rate_ftxui(); };
button_quit_.on_click = [&] { on_quit(); };
}
Element Render() final { Element Render() final {
auto button_elements = hbox({
button_rate_ftxui.Render(),
filler(),
button_quit_.Render(),
});
auto document = // auto document = //
vbox({ vbox({
text(L"Modal dialog example"), text(L"Modal dialog example"),
separator(), separator(),
text(L"☆☆☆ FTXUI:" + rating_ + L" ☆☆☆") | bold, text(L"☆☆☆ FTXUI:" + rating + L" ☆☆☆") | bold,
filler(), filler(),
button_elements, hbox({
button_rate_ftxui_->Render(),
filler(),
button_quit_->Render(),
}),
}) | }) |
border; border;
return document | size(HEIGHT, GREATER_THAN, 18) | center; return document | size(HEIGHT, GREATER_THAN, 18) | center;
} }
};
private: std::vector<std::wstring> rating_labels = {
Container container_ = Container::Horizontal(); L"1/5 stars", L"2/5 stars", L"3/5 stars", L"4/5 stars", L"5/5 stars",
Button button_rate_ftxui = Button(L"Rate FTXUI");
Button button_quit_ = Button(L"Quit");
}; };
// The "modal" screen, at depth 1. It display the modal dialog. // The "modal" screen, at depth 1. It display the modal dialog.
class Modal : public Component { class Modal : public ComponentBase {
private:
Component container_ = Container::Horizontal({
Button(&rating_labels[0], [this] { on_click(rating_labels[0]); }),
Button(&rating_labels[1], [this] { on_click(rating_labels[1]); }),
Button(&rating_labels[2], [this] { on_click(rating_labels[2]); }),
Button(&rating_labels[3], [this] { on_click(rating_labels[3]); }),
Button(&rating_labels[4], [this] { on_click(rating_labels[4]); }),
});
public: public:
std::function<void(std::wstring)> on_click; std::function<void(std::wstring)> on_click;
Modal() { Modal() { Add(container_); }
Add(&container_);
buttons_.resize(5);
for (int i = 0; i < 5; ++i) {
std::wstring stars = std::to_wstring(i + 1) + L"/5 stars";
buttons_[i] = Button(stars);
buttons_[i].on_click = [&, stars] { on_click(stars); };
container_.Add(&buttons_[i]);
}
}
Element Render() final { Element Render() final {
return vbox({ return vbox({
text(L"Do you like FTXUI?"), text(L"Do you like FTXUI?"),
separator(), separator(),
hbox({ hbox(container_->Render()),
buttons_[0].Render(),
buttons_[1].Render(),
buttons_[2].Render(),
buttons_[3].Render(),
buttons_[4].Render(),
}),
}) | }) |
border; border;
} }
private:
Container container_ = Container::Horizontal();
std::vector<Button> buttons_;
}; };
class MyComponent : public Component { class MyComponent : public ComponentBase {
private:
std::shared_ptr<Content> content_ = std::make_shared<Content>();
std::shared_ptr<Modal> modal_ = std::make_shared<Modal>();
int depth = 0;
Component container_ = Container::Tab(&depth,
{
content_,
modal_,
});
std::function<void()> on_quit_;
public: public:
std::function<void()> on_quit = [] {}; MyComponent(std::function<void()> on_quit) : on_quit_(on_quit) {
Add(container_);
MyComponent() { content_->on_quit = [&] { on_quit(); };
Add(&container_); content_->on_rate_ftxui = [this] { depth = 1; };
container_.Add(&content_); modal_->on_click = [&](std::wstring rating) {
container_.Add(&modal_); content_->rating = rating;
depth = 0;
content_.on_quit = [&] { on_quit(); };
content_.on_rate_ftxui = [&] { modal_.TakeFocus(); };
modal_.on_click = [&](std::wstring rating) {
content_.rating_ = rating;
content_.TakeFocus();
}; };
} }
Element Render() final { Element Render() final {
Element document = content_.Render(); Element document = content_->Render();
if (modal_.Focused()) {
if (depth == 1) {
document = dbox({ document = dbox({
document, document,
modal_.Render() | clear_under | center, modal_->Render() | clear_under | center,
}); });
} }
return document; return document;
} }
private:
Container container_ = Container::Tab(nullptr);
Content content_;
Modal modal_;
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent my_component; screen.Loop(Make<MyComponent>(screen.ExitLoopClosure()));
my_component.on_quit = screen.ExitLoopClosure();
screen.Loop(&my_component);
return 0; return 0;
} }

View File

@ -1,18 +1,23 @@
#include "ftxui/component/radiobox.hpp" #include <string> // for wstring, allocator, basic_string
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Radiobox
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
using namespace ftxui; using namespace ftxui;
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); std::vector<std::wstring> radiobox_list = {
RadioBox radiobox;
radiobox.entries = {
L"Use gcc", L"Use gcc",
L"Use clang", L"Use clang",
L"Use emscripten", L"Use emscripten",
L"Use tcc", L"Use tcc",
}; };
screen.Loop(&radiobox); int selected = 0;
auto screen = ScreenInteractive::TerminalOutput();
screen.Loop(Radiobox(&radiobox_list, &selected));
return 0; return 0;
} }

View File

@ -1,35 +1,36 @@
#include <string> // for wstring, operator+ #include <string> // for wstring, operator+
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/radiobox.hpp" // for RadioBox #include "ftxui/component/component.hpp" // for Make, Radiobox
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, operator| #include "ftxui/dom/elements.hpp" // for Element, operator|, size, border, frame, HEIGHT, LESS_THAN
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/screen/string.hpp" // for to_wstring
#include "ftxui/screen/string.hpp" // for to_wstring
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
RadioBox radiobox; private:
std::vector<std::wstring> entries_;
int selected_ = 0;
public: public:
MyComponent() { MyComponent() {
for (int i = 0; i < 30; ++i) { for (int i = 0; i < 30; ++i)
radiobox.entries.push_back(L"RadioBox " + to_wstring(i)); entries_.push_back(L"RadioBox " + to_wstring(i));
} Add(Radiobox(&entries_, &selected_));
Add(&radiobox);
} }
Element Render() override { Element Render() override {
return radiobox.Render() | frame | size(HEIGHT, LESS_THAN, 10) | border; return ComponentBase::Render() | frame | size(HEIGHT, LESS_THAN, 10) |
border;
} }
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::FitComponent(); auto screen = ScreenInteractive::FitComponent();
MyComponent component; screen.Loop(Make<MyComponent>());
screen.Loop(&component);
return 0; return 0;
} }

View File

@ -1,82 +1,16 @@
#include <functional> // for function #include <memory> // for allocator
#include <memory> // for allocator, unique_ptr
#include <string> // for operator+, to_wstring
#include "ftxui/component/component.hpp" // for Component, Compone... #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component.hpp" // for Slider
#include "ftxui/component/event.hpp" // for Event, Event::Escape
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/component/slider.hpp" // for Slider
#include "ftxui/dom/elements.hpp" // for separator, operator|
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color
using namespace ftxui; using namespace ftxui;
Element ColorTile(int red, int green, int blue) {
return text(L"") | size(WIDTH, GREATER_THAN, 14) |
size(HEIGHT, GREATER_THAN, 7) | bgcolor(Color::RGB(red, green, blue));
}
Element ColorString(int red, int green, int blue) {
return text(L"RGB = (" + //
std::to_wstring(red) + L"," + //
std::to_wstring(green) + L"," + //
std::to_wstring(blue) + L")" //
);
}
class MyComponent : public Component {
public:
MyComponent(int* red, int* green, int* blue, std::function<void(void)> quit)
: red_(red), green_(green), blue_(blue), quit_(quit) {
Add(&container_);
container_.Add(slider_red_.get());
container_.Add(slider_green_.get());
container_.Add(slider_blue_.get());
}
Element Render() {
return hbox({
ColorTile(*red_, *green_, *blue_),
separator(),
vbox({
slider_red_->Render(),
separator(),
slider_green_->Render(),
separator(),
slider_blue_->Render(),
separator(),
ColorString(*red_, *green_, *blue_),
}) | xflex,
}) |
border | size(WIDTH, LESS_THAN, 80);
}
bool OnEvent(Event event) {
if (event == Event::Return || event == Event::Escape)
quit_();
return Component::OnEvent(event);
}
private:
int* red_;
int* green_;
int* blue_;
Container container_ = Container::Vertical();
ComponentPtr slider_red_ = Slider(L"Red :", red_, 0, 255, 1);
ComponentPtr slider_green_ = Slider(L"Green:", green_, 0, 255, 1);
ComponentPtr slider_blue_ = Slider(L"Blue :", blue_, 0, 255, 1);
std::function<void(void)> quit_;
};
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
int red = 128; int value = 50;
int green = 25; auto slider = Slider(L"Value:", &value, 0, 100, 1);
int blue = 100; screen.Loop(slider);
auto component = MyComponent(&red, &green, &blue, screen.ExitLoopClosure());
screen.Loop(&component);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,71 +1,77 @@
#include <functional> // for function #include <memory> // for __shared_ptr_access
#include <string> // for wstring, allocator #include <string> // for wstring, allocator, basic_string
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component.hpp" // for Radiobox, Make, Toggle
#include "ftxui/component/radiobox.hpp" // for RadioBox #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/container.hpp" // for Container
#include "ftxui/component/toggle.hpp" // for Toggle #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, operator| #include "ftxui/dom/elements.hpp" // for Element, separator, operator|, vbox, border
#include "ftxui/screen/box.hpp" // for ftxui
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
private:
std::vector<std::wstring> tab_values_ = {
L"tab_1",
L"tab_2",
L"tab_3",
};
int tab_selected_ = 0;
Component tab_toggle_ = Toggle(&tab_values_, &tab_selected_);
std::vector<std::wstring> tab_1_entries_ = {
L"Forest",
L"Water",
L"I don't know",
};
int tab_1_selected_ = 0;
std::vector<std::wstring> tab_2_entries_ = {
L"Hello",
L"Hi",
L"Hay",
};
int tab_2_selected_ = 0;
std::vector<std::wstring> tab_3_entries_ = {
L"Table",
L"Nothing",
L"Is",
L"Empty",
};
int tab_3_selected_ = 0;
Component tab_container_ =
Container::Tab(&tab_selected_,
{
Radiobox(&tab_1_entries_, &tab_1_selected_),
Radiobox(&tab_2_entries_, &tab_2_selected_),
Radiobox(&tab_3_entries_, &tab_3_selected_),
});
Component container_ = Container::Vertical({
tab_toggle_,
tab_container_,
});
public: public:
MyComponent() { MyComponent() { Add(container_); }
Add(&container_);
container_.Add(&toggle_);
toggle_.entries = {
L"tab_1",
L"tab_2",
L"tab_3",
};
container_.Add(&tab_container_);
radiobox_1_.entries = {L"Forest", L"Water", L"I don't know"};
tab_container_.Add(&radiobox_1_);
radiobox_2_.entries = {
L"Hello",
L"Hi",
L"Hay",
};
tab_container_.Add(&radiobox_2_);
radiobox_3_.entries = {
L"Table",
L"Nothing",
L"Is",
L"Empty",
};
tab_container_.Add(&radiobox_3_);
}
std::function<void()> on_enter = []() {};
Element Render() { Element Render() {
return vbox(toggle_.Render(), separator(), tab_container_.Render()) | return vbox({
tab_toggle_->Render(),
separator(),
tab_container_->Render(),
}) |
border; border;
} }
private:
Toggle toggle_;
Container container_ = Container::Vertical();
Container tab_container_ = Container::Tab(&(toggle_.selected));
RadioBox radiobox_1_;
RadioBox radiobox_2_;
RadioBox radiobox_3_;
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent component; screen.Loop(Make<MyComponent>());
component.on_enter = screen.ExitLoopClosure();
screen.Loop(&component);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,64 +1,77 @@
#include <functional> // for function #include <memory> // for __shared_ptr_access
#include <string> // for wstring, allocator #include <string> // for wstring, allocator, basic_string
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/container.hpp" // for Container #include "ftxui/component/component.hpp" // for Radiobox, Make, Menu
#include "ftxui/component/menu.hpp" // for Menu #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/container.hpp" // for Container
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, separator, hbox, operator|, border
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
public:
MyComponent() {
Add(&container_);
container_.Add(&menu_);
menu_.entries = {
L"menu_1",
L"menu_2",
L"menu_3",
};
container_.Add(&tab_container_);
menu_1_.entries = {L"Forest", L"Water", L"I don't know"};
tab_container_.Add(&menu_1_);
menu_2_.entries = {
L"Hello",
L"Hi",
L"Hay",
};
tab_container_.Add(&menu_2_);
menu_3_.entries = {
L"Table",
L"Nothing",
L"Is",
L"Empty",
};
tab_container_.Add(&menu_3_);
}
std::function<void()> on_enter = []() {};
private: private:
Menu menu_; std::vector<std::wstring> tab_values_ = {
Container container_ = Container::Horizontal(); L"tab_1",
Container tab_container_ = Container::Tab(&(menu_.selected)); L"tab_2",
Menu menu_1_; L"tab_3",
Menu menu_2_; };
Menu menu_3_; int tab_selected_ = 0;
Component tab_toggle_ = Menu(&tab_values_, &tab_selected_);
std::vector<std::wstring> tab_1_entries_ = {
L"Forest",
L"Water",
L"I don't know",
};
int tab_1_selected_ = 0;
std::vector<std::wstring> tab_2_entries_ = {
L"Hello",
L"Hi",
L"Hay",
};
int tab_2_selected_ = 0;
std::vector<std::wstring> tab_3_entries_ = {
L"Table",
L"Nothing",
L"Is",
L"Empty",
};
int tab_3_selected_ = 0;
Component tab_container_ =
Container::Tab(&tab_selected_,
{
Radiobox(&tab_1_entries_, &tab_1_selected_),
Radiobox(&tab_2_entries_, &tab_2_selected_),
Radiobox(&tab_3_entries_, &tab_3_selected_),
});
Component container_ = Container::Horizontal({
tab_toggle_,
tab_container_,
});
public:
MyComponent() { Add(container_); }
Element Render() {
return hbox({
tab_toggle_->Render(),
separator(),
tab_container_->Render(),
}) |
border;
}
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent component; screen.Loop(Make<MyComponent>());
component.on_enter = screen.ExitLoopClosure();
screen.Loop(&component);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,59 +1,82 @@
#include "ftxui/component/toggle.hpp" #include <functional> // for function
#include "ftxui/component/container.hpp" // for Container #include <memory> // for allocator, __shared_ptr_access
#include "ftxui/component/event.hpp" // for Event, Event::Return #include <string> // for wstring, basic_string
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Toggle, Make
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/container.hpp" // for Container
#include "ftxui/component/event.hpp" // for Event, Event::Return
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, hbox, vbox, Element
using namespace ftxui; using namespace ftxui;
class MyComponent : public Component { class MyComponent : public ComponentBase {
public:
MyComponent() {
Add(&container_);
container_.Add(&toggle_1_);
container_.Add(&toggle_2_);
container_.Add(&toggle_3_);
container_.Add(&toggle_4_);
toggle_1_.entries = {L"On", L"Off"};
toggle_2_.entries = {L"Enabled", L"Disabled"};
toggle_3_.entries = {L"10€", L"0€"};
toggle_4_.entries = {L"Nothing", L"One element", L"Several elements"};
}
std::function<void()> on_enter = []() {};
private: private:
Container container_ = Container::Vertical(); std::vector<std::wstring> toggle_1_entries_ = {
Toggle toggle_1_; L"On",
Toggle toggle_2_; L"Off",
Toggle toggle_3_; };
Toggle toggle_4_; std::vector<std::wstring> toggle_2_entries_ = {
L"Enabled",
L"Disabled",
};
std::vector<std::wstring> toggle_3_entries_ = {
L"10€",
L"0€",
};
std::vector<std::wstring> toggle_4_entries_ = {
L"Nothing",
L"One element",
L"Several elements",
};
int toggle_1_selected_ = 0;
int toggle_2_selected_ = 0;
int toggle_3_selected_ = 0;
int toggle_4_selected_ = 0;
Component toggle_1_ = Toggle(&toggle_1_entries_, &toggle_1_selected_);
Component toggle_2_ = Toggle(&toggle_2_entries_, &toggle_2_selected_);
Component toggle_3_ = Toggle(&toggle_3_entries_, &toggle_3_selected_);
Component toggle_4_ = Toggle(&toggle_4_entries_, &toggle_4_selected_);
std::function<void()> exit_;
Element Render() override { Element Render() override {
return vbox({ return vbox({
text(L"Choose your options:"), text(L"Choose your options:"),
text(L""), text(L""),
hbox(text(L" * Poweroff on startup : "), toggle_1_.Render()), hbox(text(L" * Poweroff on startup : "), toggle_1_->Render()),
hbox(text(L" * Out of process : "), toggle_2_.Render()), hbox(text(L" * Out of process : "), toggle_2_->Render()),
hbox(text(L" * Price of the information : "), toggle_3_.Render()), hbox(text(L" * Price of the information : "), toggle_3_->Render()),
hbox(text(L" * Number of elements : "), toggle_4_.Render()), hbox(text(L" * Number of elements : "), toggle_4_->Render()),
}); });
} }
bool OnEvent(Event event) override { bool OnEvent(Event event) override {
if (event == Event::Return) { if (event == Event::Return) {
on_enter(); exit_();
return true; return true;
} }
return Component::OnEvent(event); return ComponentBase::OnEvent(event);
}
public:
MyComponent(std::function<void()> exit) : exit_(exit) {
Add(Container::Vertical({
toggle_1_,
toggle_2_,
toggle_3_,
toggle_4_,
}));
} }
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
MyComponent component; screen.Loop(Make<MyComponent>(screen.ExitLoopClosure()));
component.on_enter = screen.ExitLoopClosure();
screen.Loop(&component);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -33,15 +33,18 @@
"./component/menu.js", "./component/menu.js",
"./component/menu2.js", "./component/menu2.js",
"./component/menu_style.js", "./component/menu_style.js",
"./component/modal_dialog.js",
"./component/radiobox.js", "./component/radiobox.js",
"./component/radiobox_in_frame.js", "./component/radiobox_in_frame.js",
"./component/slider.js",
"./component/tab_horizontal.js", "./component/tab_horizontal.js",
"./component/tab_vertical.js", "./component/tab_vertical.js",
"./component/toggle.js", "./component/toggle.js",
"./component/modal_dialog.js",
"./dom/border.js", "./dom/border.js",
"./dom/color_gallery.js", "./dom/color_gallery.js",
"./dom/color_info_palette256.js",
"./dom/color_truecolor_HSV.js",
"./dom/color_truecolor_RGB.js",
"./dom/dbox.js", "./dom/dbox.js",
"./dom/gauge.js", "./dom/gauge.js",
"./dom/graph.js", "./dom/graph.js",
@ -55,16 +58,12 @@
"./dom/style_blink.js", "./dom/style_blink.js",
"./dom/style_bold.js", "./dom/style_bold.js",
"./dom/style_color.js", "./dom/style_color.js",
"./dom/color_truecolor_RGB.js",
"./dom/color_truecolor_HSV.js",
"./dom/color_info_palette256.js",
"./dom/style_dim.js", "./dom/style_dim.js",
"./dom/style_gallery.js", "./dom/style_gallery.js",
"./dom/style_inverted.js", "./dom/style_inverted.js",
"./dom/style_underlined.js", "./dom/style_underlined.js",
"./dom/vbox_hbox.js", "./dom/vbox_hbox.js",
"./dom/window.js", "./dom/window.js",
"./util/print_key_press.js", "./util/print_key_press.js",
]; ];

View File

@ -4,16 +4,17 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <algorithm> // for max #include <algorithm> // for max
#include <ftxui/component/component.hpp> // for Component #include <ftxui/component/component.hpp> // for Make
#include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive #include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive
#include <string> // for allocator, operator+ #include <string> // for allocator, operator+, wstring, char_traits, to_wstring, string
#include <utility> // for move #include <utility> // for move
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/event.hpp" // for Event #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for text, vbox, window #include "ftxui/component/event.hpp" // for Event
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Middle, Mouse::None, Mouse::Pressed, Mouse::Released, Mouse::Right, Mouse::WheelDown, Mouse::WheelUp
#include "ftxui/dom/elements.hpp" // for text, vbox, window, Elements, Element
using namespace ftxui; using namespace ftxui;
@ -71,7 +72,7 @@ std::wstring Stringify(Event event) {
return out; return out;
} }
class DrawKey : public Component { class DrawKey : public ComponentBase {
public: public:
~DrawKey() override = default; ~DrawKey() override = default;
@ -94,6 +95,5 @@ class DrawKey : public Component {
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
DrawKey draw_key; screen.Loop(Make<DrawKey>());
screen.Loop(&draw_key);
} }

View File

@ -1,36 +1,35 @@
#ifndef FTXUI_COMPONENT_BUTTON_HPP #ifndef FTXUI_COMPONENT_BUTTON_HPP
#define FTXUI_COMPONENT_BUTTON_HPP #define FTXUI_COMPONENT_BUTTON_HPP
#include <functional> #include <functional> // for function
#include <string> #include <string> // for wstring
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp" // for Component
#include "ftxui/dom/elements.hpp" #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/screen/box.hpp" #include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {
struct Event; struct Event;
/// @brief A button. An action is associated to the click event. /// @brief A button. An action is associated to the click event.
/// @ingroup dom /// @ingroup dom
class Button : public Component { class ButtonBase : public ComponentBase {
public: public:
// Access this interface from a Component
static ButtonBase* From(Component);
// Constructor. // Constructor.
Button() = default; ButtonBase(const std::wstring* label, std::function<void()> on_click);
Button(std::wstring label) : label(label) {} ~ButtonBase() override = default;
~Button() override = default;
/// The Button label.
std::wstring label = L"button";
/// Called when the user press the "enter" button.
std::function<void()> on_click = [] {};
// Component implementation. // Component implementation.
Element Render() override; Element Render() override;
bool OnEvent(Event) override; bool OnEvent(Event) override;
private: private:
const std::wstring* label_;
std::function<void()> on_click_;
Box box_; Box box_;
}; };

View File

@ -1,10 +1,13 @@
#ifndef FTXUI_COMPONENT_CHECKBOX_HPP #ifndef FTXUI_COMPONENT_CHECKBOX_HPP
#define FTXUI_COMPONENT_CHECKBOX_HPP #define FTXUI_COMPONENT_CHECKBOX_HPP
#include <string> #include <functional> // for function
#include <string> // for wstring, allocator
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp" // for Component
#include "ftxui/screen/box.hpp" #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" // for Element, Decorator, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {
struct Event; struct Event;
@ -12,14 +15,14 @@ struct Event;
/// @brief A Checkbox. It can be checked or unchecked.Display an element on a /// @brief A Checkbox. It can be checked or unchecked.Display an element on a
/// ftxui::Screen. /// ftxui::Screen.
/// @ingroup dom /// @ingroup dom
class CheckBox : public Component { class CheckboxBase : public ComponentBase {
public: public:
// Constructor. // Access this interface from a Component
CheckBox() = default; static CheckboxBase* From(Component component);
~CheckBox() override = default;
bool state = false; // The current state. true=checked, false:unchecked. // Constructor.
std::wstring label = L"label"; // The CheckBox label. CheckboxBase(const std::wstring* label, bool* state);
~CheckboxBase() override = default;
#if defined(_WIN32) #if defined(_WIN32)
std::wstring checked = L"[X] "; /// Prefix for a "checked" state. std::wstring checked = L"[X] "; /// Prefix for a "checked" state.
@ -32,7 +35,7 @@ class CheckBox : public Component {
Decorator focused_style = inverted; /// Decorator used when focused. Decorator focused_style = inverted; /// Decorator used when focused.
Decorator unfocused_style = nothing; /// Decorator used when unfocused. Decorator unfocused_style = nothing; /// Decorator used when unfocused.
/// Called when the user change the state of the CheckBox. /// Called when the user change the state of the CheckboxBase.
std::function<void()> on_change = []() {}; std::function<void()> on_change = []() {};
// Component implementation. // Component implementation.
@ -42,6 +45,8 @@ class CheckBox : public Component {
private: private:
bool OnMouseEvent(Event event); bool OnMouseEvent(Event event);
const std::wstring* const label_;
bool* const state_;
int cursor_position = 0; int cursor_position = 0;
Box box_; Box box_;
}; };

View File

@ -1,77 +1,45 @@
#ifndef FTXUI_COMPONENT_COMPONENT_HPP #ifndef FTXUI_COMPONENT_HPP
#define FTXUI_COMPONENT_COMPONENT_HPP #define FTXUI_COMPONENT_HPP
#include <memory> // for unique_ptr #include <functional> // for function
#include <vector> // for vector #include <memory> // for shared_ptr, make_shared
#include <string> // for wstring
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for CaptureMouse #include "ftxui/component/component_base.hpp"
#include "ftxui/dom/elements.hpp" // for Element
namespace ftxui { namespace ftxui {
class Delegate; class ComponentBase;
class Focus;
struct Event;
/// @brief It implement rendering itself as ftxui::Element. It implement using Component = std::shared_ptr<ComponentBase>;
/// keyboard navigation by responding to ftxui::Event. using Components = std::vector<Component>;
/// @ingroup component
class Component {
public:
// Constructor/Destructor.
Component() = default;
virtual ~Component();
// Component hierarchy. template <class T, class... Args>
Component* Parent(); std::shared_ptr<T> Make(Args&&... args) {
void Add(Component* children); return std::make_shared<T>(args...);
}
// Renders the component. Component Button(const std::wstring* label, std::function<void()> on_click);
virtual Element Render(); Component Checkbox(const std::wstring* label, bool* checked);
Component Input(std::wstring* content, const std::wstring* placeholder);
Component Menu(const std::vector<std::wstring>* entries, int* selected_);
Component Radiobox(const std::vector<std::wstring>* entries, int* selected_);
Component Toggle(const std::vector<std::wstring>* entries, int* selected);
// Handles an event. template <class T> // T = {int, float}
// By default, reduce on children with a lazy OR. Component Slider(std::wstring label, T* value, T min, T max, T increment);
//
// Returns whether the event was handled or not.
virtual bool OnEvent(Event);
// Focus management ---------------------------------------------------------- // namespace Component {
// // Component Vertical(Components children);
// If this component contains children, this indicates which one is active, // Component Horizontal(Components children);
// nullptr if none is active. // Component Tab(int* selector, Components children);
// //} // namespace Component
// We say an element has the focus if the chain of ActiveChild() from the
// root component contains this object.
virtual Component* ActiveChild();
// Whether this is the active child of its parent. }; // namespace ftxui
bool Active();
// Whether all the ancestors are active.
bool Focused();
// Make the |child| to be the "active" one. #endif /* end of include guard: FTXUI_COMPONENT_HPP */
virtual void SetActiveChild(Component* child);
// Configure all the ancestors to give focus to this component. // Copyright 2021 Arthur Sonzogni. All rights reserved.
void TakeFocus();
protected:
CapturedMouse CaptureMouse(const Event& event);
std::vector<Component*> children_;
private:
Component* parent_ = nullptr;
void Detach();
void Attach(Component* parent);
};
using ComponentPtr = std::unique_ptr<Component>;
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_HPP */
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in // Use of this source code is governed by the MIT license that can be found in
// the LICENSE file. // the LICENSE file.

View File

@ -0,0 +1,81 @@
#ifndef FTXUI_COMPONENT_BASE_HPP
#define FTXUI_COMPONENT_BASE_HPP
#include <memory> // for unique_ptr
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for CaptureMouse
#include "ftxui/dom/elements.hpp" // for Element
namespace ftxui {
class Delegate;
class Focus;
struct Event;
class ComponentBase;
using Component = std::shared_ptr<ComponentBase>;
using Components = std::vector<Component>;
/// @brief It implement rendering itself as ftxui::Element. It implement
/// keyboard navigation by responding to ftxui::Event.
/// @ingroup component
class ComponentBase {
public:
// Constructor/Destructor.
ComponentBase() = default;
virtual ~ComponentBase();
// ComponentBase hierarchy.
ComponentBase* Parent();
void Add(Component children);
// Renders the component.
virtual Element Render();
// Handles an event.
// By default, reduce on children with a lazy OR.
//
// Returns whether the event was handled or not.
virtual bool OnEvent(Event);
// Focus management ----------------------------------------------------------
//
// If this component contains children, this indicates which one is active,
// nullptr if none is active.
//
// We say an element has the focus if the chain of ActiveChild() from the
// root component contains this object.
virtual Component ActiveChild();
// Whether this is the active child of its parent.
bool Active();
// Whether all the ancestors are active.
bool Focused();
// Make the |child| to be the "active" one.
virtual void SetActiveChild(ComponentBase* child);
void SetActiveChild(Component child);
// Configure all the ancestors to give focus to this component.
void TakeFocus();
protected:
CapturedMouse CaptureMouse(const Event& event);
std::vector<Component> children_;
private:
ComponentBase* parent_ = nullptr;
void Detach();
};
using Component = std::shared_ptr<ComponentBase>;
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_BASE_HPP */
// 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.

View File

@ -1,26 +1,32 @@
#ifndef FTXUI_COMPONENT_CONTAINER_HPP #ifndef FTXUI_COMPONENT_CONTAINER_HPP
#define FTXUI_COMPONENT_CONTAINER_HPP #define FTXUI_COMPONENT_CONTAINER_HPP
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp" // for Component, Components
#include "ftxui/component/event.hpp" #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/dom/elements.hpp" #include "ftxui/component/event.hpp" // for Event
#include "ftxui/dom/elements.hpp" // for Element
namespace ftxui { namespace ftxui {
/// @brief A component where focus and events are automatically handled for you. /// @brief A component where focus and events are automatically handled for you.
class Container : public Component { class Container : public ComponentBase {
public: public:
static Container Vertical(); static Component Vertical();
static Container Horizontal(); static Component Vertical(Components children);
static Container Tab(int* selector);
static Component Horizontal();
static Component Horizontal(Components children);
static Component Tab(int* selector);
static Component Tab(int* selector, Components children);
~Container() override = default; ~Container() override = default;
// Component override. // Component override.
bool OnEvent(Event event) override; bool OnEvent(Event event) override;
Element Render() override; Element Render() override;
Component* ActiveChild() override; Component ActiveChild() override;
virtual void SetActiveChild(Component*) override; virtual void SetActiveChild(ComponentBase*) override;
protected: protected:
// Handlers // Handlers

View File

@ -8,7 +8,7 @@
namespace ftxui { namespace ftxui {
class ScreenInteractive; class ScreenInteractive;
class Component; class ComponentBase;
/// @brief Represent an event. It can be key press event, a terminal resize, or /// @brief Represent an event. It can be key press event, a terminal resize, or
/// more ... /// more ...
@ -76,7 +76,7 @@ struct Event {
//--- State section ---------------------------------------------------------- //--- State section ----------------------------------------------------------
private: private:
friend Component; friend ComponentBase;
friend ScreenInteractive; friend ScreenInteractive;
enum class Type { enum class Type {
Unknown, Unknown,

View File

@ -1,27 +1,29 @@
#ifndef FTXUI_COMPONENT_INPUT_H_ #ifndef FTXUI_COMPONENT_INPUT_H_
#define FTXUI_COMPONENT_INPUT_H_ #define FTXUI_COMPONENT_INPUT_H_
#include <functional> #include <functional> // for function
#include <string> #include <string> // for wstring
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp" // for Component
#include "ftxui/dom/elements.hpp" #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/screen/box.hpp" #include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {
struct Event; struct Event;
/// @brief An input box. The user can type text into it. /// @brief An input box. The user can type text into it.
/// @ingroup component. /// @ingroup component.
class Input : public Component { class InputBase : public ComponentBase {
public: public:
// Access this interface from a Component
static InputBase* From(Component component);
// Constructor. // Constructor.
Input() = default; InputBase(std::wstring* content, const std::wstring* placeholder);
~Input() override = default; ~InputBase() override = default;
// State. // State.
std::wstring content;
std::wstring placeholder;
int cursor_position = 0; int cursor_position = 0;
// State update callback. // State update callback.
@ -33,6 +35,9 @@ class Input : public Component {
bool OnEvent(Event) override; bool OnEvent(Event) override;
private: private:
std::wstring* const content_;
const std::wstring* const placeholder_;
bool OnMouseEvent(Event); bool OnMouseEvent(Event);
Box input_box_; Box input_box_;
Box cursor_box_; Box cursor_box_;

View File

@ -1,28 +1,30 @@
#ifndef FTXUI_COMPONENT_MENU #ifndef FTXUI_COMPONENT_MENU
#define FTXUI_COMPONENT_MENU #define FTXUI_COMPONENT_MENU
#include <functional> #include <functional> // for function
#include <string> #include <string> // for wstring
#include <vector> #include <vector> // for vector
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp" // for Component
#include "ftxui/dom/elements.hpp" #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/screen/box.hpp" #include "ftxui/dom/elements.hpp" // for Element, Decorator, operator|, bold, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {
struct Event; struct Event;
/// @brief A list of items. The user can navigate through them. /// @brief A list of items. The user can navigate through them.
/// @ingroup component /// @ingroup component
class Menu : public Component { class MenuBase : public ComponentBase {
public: public:
// Access this interface from a Component
static MenuBase* From(Component component);
// Constructor. // Constructor.
Menu() = default; MenuBase(const std::vector<std::wstring>* entries, int* selected_);
~Menu() override = default; ~MenuBase() override = default;
// State. // State.
std::vector<std::wstring> entries = {};
int selected = 0;
int focused = 0; int focused = 0;
Decorator normal_style = nothing; Decorator normal_style = nothing;
@ -38,7 +40,10 @@ class Menu : public Component {
Element Render() override; Element Render() override;
bool OnEvent(Event) override; bool OnEvent(Event) override;
private: protected:
const std::vector<std::wstring>* const entries_;
int* selected_ = 0;
bool OnMouseEvent(Event); bool OnMouseEvent(Event);
std::vector<Box> boxes_; std::vector<Box> boxes_;

View File

@ -1,12 +1,14 @@
#ifndef FTXUI_COMPONENT_RADIOBOX_HPP #ifndef FTXUI_COMPONENT_RADIOBOX_HPP
#define FTXUI_COMPONENT_RADIOBOX_HPP #define FTXUI_COMPONENT_RADIOBOX_HPP
#include <string> #include <functional> // for function
#include <vector> #include <string> // for wstring, allocator
#include <vector> // for vector
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp" // for Component
#include "ftxui/dom/elements.hpp" #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/screen/box.hpp" #include "ftxui/dom/elements.hpp" // for Element, Decorator, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {
struct Event; struct Event;
@ -14,15 +16,16 @@ struct Event;
/// @brief A list of selectable element. One and only one can be selected at /// @brief A list of selectable element. One and only one can be selected at
/// the same time. /// the same time.
/// @ingroup component /// @ingroup component
class RadioBox : public Component { class RadioboxBase : public ComponentBase {
public: public:
// Constructor. // Access this interface from a Component
RadioBox() = default; static RadioboxBase* From(Component component);
~RadioBox() override = default;
// Constructor.
RadioboxBase(const std::vector<std::wstring>* entries, int* selected);
~RadioboxBase() override = default;
int selected = 0;
int focused = 0; int focused = 0;
std::vector<std::wstring> entries;
#if defined(_WIN32) #if defined(_WIN32)
std::wstring checked = L"(*) "; std::wstring checked = L"(*) ";
@ -43,6 +46,9 @@ class RadioBox : public Component {
bool OnEvent(Event) override; bool OnEvent(Event) override;
private: private:
const std::vector<std::wstring>* const entries_;
int* const selected_;
bool OnMouseEvent(Event event); bool OnMouseEvent(Event event);
int cursor_position = 0; int cursor_position = 0;
std::vector<Box> boxes_; std::vector<Box> boxes_;

View File

@ -3,15 +3,18 @@
#include <atomic> // for atomic #include <atomic> // for atomic
#include <ftxui/component/receiver.hpp> #include <ftxui/component/receiver.hpp>
#include <memory> // for unique_ptr #include <functional> // for function
#include <string> // for string #include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse #include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/event.hpp" #include "ftxui/component/event.hpp"
#include "ftxui/screen/screen.hpp" // for Screen #include "ftxui/screen/screen.hpp" // for Screen
namespace ftxui { namespace ftxui {
class Component; class ComponentBase;
using Component = std::shared_ptr<ComponentBase>;
struct Event; struct Event;
class ScreenInteractive : public Screen { class ScreenInteractive : public Screen {
@ -22,15 +25,15 @@ class ScreenInteractive : public Screen {
static ScreenInteractive TerminalOutput(); static ScreenInteractive TerminalOutput();
~ScreenInteractive(); ~ScreenInteractive();
void Loop(Component*); void Loop(Component);
std::function<void()> ExitLoopClosure(); std::function<void()> ExitLoopClosure();
void PostEvent(Event event); void PostEvent(Event event);
CapturedMouse CaptureMouse(); CapturedMouse CaptureMouse();
private: private:
void Draw(Component* component); void Draw(Component component);
void EventLoop(Component* component); void EventLoop(Component component);
enum class Dimension { enum class Dimension {
FitComponent, FitComponent,

View File

@ -1,23 +0,0 @@
#ifndef FTXUI_COMPONENT_SLIDER_HPP
#define FTXUI_COMPONENT_SLIDER_HPP
#include <string>
#include "ftxui/component/component.hpp"
namespace ftxui {
// ComponentPtr Slider(std::string label,
// float* value,
// float min = 0.f,
// float max = 100.f,
// float increment = (max - min) * 0.05f);
template <class T> // T = {int, float}
ComponentPtr Slider(std::wstring label, T* value, T min, T max, T increment);
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_SLIDER_HPP */
// 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.

View File

@ -1,26 +1,30 @@
#ifndef FTXUI_COMPONENT_TOGGLE_H_ #ifndef FTXUI_COMPONENT_TOGGLE_H_
#define FTXUI_COMPONENT_TOGGLE_H_ #define FTXUI_COMPONENT_TOGGLE_H_
#include <string> #include <functional> // for function
#include <vector> #include <string> // for wstring
#include <vector> // for vector
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp" // for Component
#include "ftxui/dom/elements.hpp" #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/screen/box.hpp" #include "ftxui/dom/elements.hpp" // for Element, Decorator, operator|, bold, dim, inverted
#include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {
struct Event; struct Event;
/// @brief An horizontal list of elements. The user can navigate through them. /// @brief An horizontal list of elements. The user can navigate through them.
/// @ingroup component /// @ingroup component
class Toggle : public Component { class ToggleBase : public ComponentBase {
public: public:
// Access this interface from a Component
static ToggleBase* From(Component component);
// Constructor. // Constructor.
~Toggle() override = default; ToggleBase(const std::vector<std::wstring>* entries, int* selected);
~ToggleBase() override = default;
// State. // State.
std::vector<std::wstring> entries = {L"On", L"Off"};
int selected = 0;
int focused = 0; int focused = 0;
Decorator normal_style = dim; Decorator normal_style = dim;
@ -36,7 +40,10 @@ class Toggle : public Component {
Element Render() override; Element Render() override;
bool OnEvent(Event) override; bool OnEvent(Event) override;
private: protected:
const std::vector<std::wstring>* const entries_;
int* selected_ = 0;
bool OnMouseEvent(Event event); bool OnMouseEvent(Event event);
std::vector<Box> boxes_; std::vector<Box> boxes_;
}; };

View File

@ -5,4 +5,7 @@
{ symbol: [ "ICANON", private, "<termios.h>", public ] }, { symbol: [ "ICANON", private, "<termios.h>", public ] },
{ symbol: [ "termios", private, "<termios.h>", public ] }, { symbol: [ "termios", private, "<termios.h>", public ] },
{ symbol: [ "TCSANOW", private, "<termios.h>", public ] }, { symbol: [ "TCSANOW", private, "<termios.h>", public ] },
{ symbol: [ "__shared_ptr_access", private, "", public ] },
{ symbol: [ "ftxui", private , "", public ] },
{ include: ["ext/alloc_traits.h", "private", "<memory>", "public"] }
] ]

View File

@ -9,12 +9,47 @@
namespace ftxui { namespace ftxui {
Element Button::Render() { /// @brief Draw a button. Execute a function when clicked.
auto style = Focused() ? inverted : nothing; /// @param label The label of the button.
return text(label) | border | style | reflect(box_); /// @param on_click The action to execute when clicked.
/// @ingroup component
/// @see ButtonBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::wstring label = L"Click to quit";
/// Component button = Button(&label, screen.ExitLoopClosure());
/// screen.Loop(button)
/// ```
///
/// ### Output
///
/// ```bash
/// ┌─────────────┐
/// │Click to quit│
/// └─────────────┘
/// ```
Component Button(const std::wstring* label, std::function<void()> on_click) {
return Make<ButtonBase>(label, on_click);
} }
bool Button::OnEvent(Event event) { // static
ButtonBase* ButtonBase::From(Component component) {
return static_cast<ButtonBase*>(component.get());
}
ButtonBase::ButtonBase(const std::wstring* label,
std::function<void()> on_click)
: label_(label), on_click_(on_click) {}
Element ButtonBase::Render() {
auto style = Focused() ? inverted : nothing;
return text(*label_) | border | style | reflect(box_);
}
bool ButtonBase::OnEvent(Event event) {
if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) { if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
@ -23,7 +58,7 @@ bool Button::OnEvent(Event event) {
if (event.mouse().button == Mouse::Left && if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) { event.mouse().motion == Mouse::Pressed) {
on_click(); on_click_();
return true; return true;
} }
@ -31,7 +66,7 @@ bool Button::OnEvent(Event event) {
} }
if (event == Event::Return) { if (event == Event::Return) {
on_click(); on_click_();
return true; return true;
} }
return false; return false;

View File

@ -9,29 +9,62 @@
namespace ftxui { namespace ftxui {
Element CheckBox::Render() { /// @brief Draw checkable element.
/// @param label The label of the checkbox.
/// @param checked Whether the checkbox is checked or not.
/// @ingroup component
/// @see CheckboxBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::wstring label = L"Make a sandwidth";
/// bool checked = false;
/// Component checkbox = Checkbox(&label, &checked);
/// screen.Loop(checkbox)
/// ```
///
/// ### Output
///
/// ```bash
/// ☐ Make a sandwitch
/// ```
Component Checkbox(const std::wstring* label, bool* checked) {
return Make<CheckboxBase>(label, checked);
}
// static
CheckboxBase* From(Component component) {
return static_cast<CheckboxBase*>(component.get());
}
CheckboxBase::CheckboxBase(const std::wstring* label, bool* state)
: label_(label), state_(state) {}
Element CheckboxBase::Render() {
bool is_focused = Focused(); bool is_focused = Focused();
auto style = is_focused ? focused_style : unfocused_style; auto style = is_focused ? focused_style : unfocused_style;
auto focus_management = is_focused ? focus : state ? select : nothing; auto focus_management = is_focused ? focus : *state_ ? select : nothing;
return hbox(text(state ? checked : unchecked), return hbox(text(*state_ ? checked : unchecked),
text(label) | style | focus_management) | text(*label_) | style | focus_management) |
reflect(box_); reflect(box_);
} }
bool CheckBox::OnEvent(Event event) { bool CheckboxBase::OnEvent(Event event) {
if (event.is_mouse()) if (event.is_mouse())
return OnMouseEvent(event); return OnMouseEvent(event);
if (event == Event::Character(' ') || event == Event::Return) { if (event == Event::Character(' ') || event == Event::Return) {
state = !state; *state_ = !*state_;
on_change(); on_change();
return true; return true;
} }
return false; return false;
} }
bool CheckBox::OnMouseEvent(Event event) { bool CheckboxBase::OnMouseEvent(Event event) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
if (!box_.Contain(event.mouse().x, event.mouse().y)) if (!box_.Contain(event.mouse().x, event.mouse().y))
return false; return false;
@ -40,7 +73,7 @@ bool CheckBox::OnMouseEvent(Event event) {
if (event.mouse().button == Mouse::Left && if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) { event.mouse().motion == Mouse::Pressed) {
state = !state; *state_ = !*state_;
on_change(); on_change();
return true; return true;
} }

View File

@ -1,10 +1,14 @@
#include <algorithm> // for find_if
#include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <iterator> // for begin, end
#include <utility> // for move
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
#include "ftxui/component/component.hpp" #include "ftxui/component/component.hpp"
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
#include <algorithm> #include "ftxui/component/event.hpp" // for Event
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/component/captured_mouse.hpp" #include "ftxui/dom/elements.hpp" // for text, Element
#include "ftxui/component/event.hpp"
#include "ftxui/component/screen_interactive.hpp"
namespace ftxui { namespace ftxui {
@ -13,33 +17,35 @@ class CaptureMouseImpl : public CapturedMouseInterface {
public: public:
~CaptureMouseImpl() override {} ~CaptureMouseImpl() override {}
}; };
} } // namespace
Component::~Component() { ComponentBase::~ComponentBase() {
Detach(); Detach();
} }
/// @brief Return the parent Component, or nul if any. /// @brief Return the parent ComponentBase, or nul if any.
/// @see Attach /// @see Attach
/// @see Detach /// @see Detach
/// @see Parent /// @see Parent
/// @ingroup component /// @ingroup component
Component* Component::Parent() { ComponentBase* ComponentBase::Parent() {
return parent_; return parent_;
} }
/// @brief Add a children. /// @brief Add a children.
/// @@param child The child to be attached. /// @@param child The child to be attached.
/// @ingroup component /// @ingroup component
void Component::Add(Component* child) { void ComponentBase::Add(Component child) {
child->Attach(this); child->Detach();
child->parent_ = this;
children_.push_back(std::move(child));
} }
/// @brief Draw the component. /// @brief Draw the component.
/// Build a ftxui::Element to be drawn on the ftxi::Screen representing this /// Build a ftxui::Element to be drawn on the ftxi::Screen representing this
/// ftxui::Component. /// ftxui::ComponentBase.
/// @ingroup component /// @ingroup component
Element Component::Render() { Element ComponentBase::Render() {
if (children_.size() == 1) if (children_.size() == 1)
return children_.front()->Render(); return children_.front()->Render();
@ -52,8 +58,8 @@ Element Component::Render() {
/// The default implementation called OnEvent on every child until one return /// The default implementation called OnEvent on every child until one return
/// true. If none returns true, return false. /// true. If none returns true, return false.
/// @ingroup component /// @ingroup component
bool Component::OnEvent(Event event) { bool ComponentBase::OnEvent(Event event) {
for (Component* child : children_) { for (Component& child : children_) {
if (child->OnEvent(event)) if (child->OnEvent(event))
return true; return true;
} }
@ -63,27 +69,27 @@ bool Component::OnEvent(Event event) {
/// @brief Return the currently Active child. /// @brief Return the currently Active child.
/// @return the currently Active child. /// @return the currently Active child.
/// @ingroup component /// @ingroup component
Component* Component::ActiveChild() { Component ComponentBase::ActiveChild() {
return children_.empty() ? nullptr : children_.front(); return children_.empty() ? nullptr : children_.front();
} }
/// @brief Returns if the element if the currently active child of its parent. /// @brief Returns if the element if the currently active child of its parent.
/// @ingroup component /// @ingroup component
bool Component::Active() { bool ComponentBase::Active() {
return !parent_ || parent_->ActiveChild() == this; return !parent_ || parent_->ActiveChild().get() == this;
} }
/// @brief Returns if the elements if focused by the user. /// @brief Returns if the elements if focused by the user.
/// True when the Component is focused by the user. An element is Focused when /// True when the ComponentBase is focused by the user. An element is Focused
/// it is with all its ancestors the ActiveChild() of their parents. /// when it is with all its ancestors the ActiveChild() of their parents.
/// @ingroup component /// @ingroup component
bool Component::Focused() { bool ComponentBase::Focused() {
Component* current = this; ComponentBase* current = this;
for (;;) { for (;;) {
Component* parent = current->parent_; ComponentBase* parent = current->parent_;
if (!parent) if (!parent)
return true; return true;
if (parent->ActiveChild() != current) if (parent->ActiveChild().get() != current)
return false; return false;
current = parent; current = parent;
} }
@ -92,13 +98,20 @@ bool Component::Focused() {
/// @brief Make the |child| to be the "active" one. /// @brief Make the |child| to be the "active" one.
/// @argument child the child to become active. /// @argument child the child to become active.
/// @ingroup component /// @ingroup component
void Component::SetActiveChild(Component*) {} void ComponentBase::SetActiveChild(ComponentBase*) {}
/// @brief Make the |child| to be the "active" one.
/// @argument child the child to become active.
/// @ingroup component
void ComponentBase::SetActiveChild(Component child) {
SetActiveChild(child.get());
}
/// @brief Configure all the ancestors to give focus to this component. /// @brief Configure all the ancestors to give focus to this component.
/// @ingroup component /// @ingroup component
void Component::TakeFocus() { void ComponentBase::TakeFocus() {
Component* child = this; ComponentBase* child = this;
Component* parent = parent_; ComponentBase* parent = parent_;
while (parent) { while (parent) {
parent->SetActiveChild(child); parent->SetActiveChild(child);
child = parent; child = parent;
@ -110,7 +123,7 @@ void Component::TakeFocus() {
/// them. It represents a component taking priority over others. /// them. It represents a component taking priority over others.
/// @argument event /// @argument event
/// @ingroup component /// @ingroup component
CapturedMouse Component::CaptureMouse(const Event& event) { CapturedMouse ComponentBase::CaptureMouse(const Event& event) {
if (!event.screen_) if (!event.screen_)
return std::make_unique<CaptureMouseImpl>(); return std::make_unique<CaptureMouseImpl>();
return event.screen_->CaptureMouse(); return event.screen_->CaptureMouse();
@ -121,25 +134,17 @@ CapturedMouse Component::CaptureMouse(const Event& event) {
/// @see Detach /// @see Detach
/// @see Parent /// @see Parent
/// @ingroup component /// @ingroup component
void Component::Detach() { void ComponentBase::Detach() {
if (!parent_) if (!parent_)
return; return;
auto it = std::find(std::begin(parent_->children_), auto it = std::find_if(std::begin(parent_->children_), //
std::end(parent_->children_), this); std::end(parent_->children_), //
[this](const Component& that) { //
return this == that.get();
});
parent_->children_.erase(it); parent_->children_.erase(it);
} }
/// @brief Attach this element to its parent.
/// @see Attach
/// @see Detach
/// @see Parent
/// @ingroup component
void Component::Attach(Component* parent) {
Detach();
parent_ = parent;
parent_->children_.push_back(this);
}
} // namespace ftxui } // namespace ftxui
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,33 +1,69 @@
#include "ftxui/component/container.hpp" #include <stddef.h> // for size_t
#include <algorithm> // for max, min
#include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <memory> // for __shared_ptr_access, shared_ptr, make_shared, __shared_ptr_access<>::element_type, allocator_traits<>::value_type
#include <utility> // for move
#include <vector> // for vector, allocator
#include <stddef.h> #include "ftxui/component/container.hpp"
#include <algorithm>
#include <vector>
namespace ftxui { namespace ftxui {
Component ContainerVertical(Components children) {
return Container::Vertical(std::move(children));
}
Component ContainerHorizontal(Components children) {
return Container::Horizontal(std::move(children));
}
Component ContainerTab(int* selector, Components children) {
return Container::Tab(selector, std::move(children));
}
// static // static
Container Container::Horizontal() { Component Container::Vertical() {
Container container; return Vertical({});
container.event_handler_ = &Container::HorizontalEvent; }
container.render_handler_ = &Container::HorizontalRender;
// static
Component Container::Vertical(Components children) {
auto container = std::make_shared<Container>();
container->event_handler_ = &Container::VerticalEvent;
container->render_handler_ = &Container::VerticalRender;
for (Component& child : children)
container->Add(std::move(child));
return container; return container;
} }
// static // static
Container Container::Vertical() { Component Container::Horizontal() {
Container container; return Horizontal({});
container.event_handler_ = &Container::VerticalEvent; }
container.render_handler_ = &Container::VerticalRender;
// static
Component Container::Horizontal(Components children) {
auto container = std::make_shared<Container>();
container->event_handler_ = &Container::HorizontalEvent;
container->render_handler_ = &Container::HorizontalRender;
for (Component& child : children)
container->Add(std::move(child));
return container; return container;
} }
// static // static
Container Container::Tab(int* selector) { Component Container::Tab(int* selector) {
Container container; return Tab(selector, {});
container.event_handler_ = &Container::TabEvent; }
container.render_handler_ = &Container::TabRender;
container.selector_ = selector; // static
Component Container::Tab(int* selector, Components children) {
auto container = std::make_shared<Container>();
container->selector_ = selector;
container->event_handler_ = &Container::TabEvent;
container->render_handler_ = &Container::TabRender;
for (Component& child : children)
container->Add(std::move(child));
return container; return container;
} }
@ -44,7 +80,7 @@ bool Container::OnEvent(Event event) {
return (this->*event_handler_)(event); return (this->*event_handler_)(event);
} }
Component* Container::ActiveChild() { Component Container::ActiveChild() {
if (children_.size() == 0) if (children_.size() == 0)
return nullptr; return nullptr;
@ -52,9 +88,9 @@ Component* Container::ActiveChild() {
return children_[selected % children_.size()]; return children_[selected % children_.size()];
} }
void Container::SetActiveChild(Component* child) { void Container::SetActiveChild(ComponentBase* child) {
for (size_t i = 0; i < children_.size(); ++i) { for (size_t i = 0; i < children_.size(); ++i) {
if (children_[i] == child) { if (children_[i].get() == child) {
(selector_ ? *selector_ : selected_) = i; (selector_ ? *selector_ : selected_) = i;
return; return;
} }
@ -114,7 +150,7 @@ Element Container::HorizontalRender() {
} }
Element Container::TabRender() { Element Container::TabRender() {
Component* active_child = ActiveChild(); Component active_child = ActiveChild();
if (active_child) if (active_child)
return active_child->Render(); return active_child->Render();
return text(L"Empty container"); return text(L"Empty container");
@ -124,7 +160,7 @@ bool Container::OnMouseEvent(Event event) {
if (selector_) if (selector_)
return ActiveChild()->OnEvent(event); return ActiveChild()->OnEvent(event);
for (Component* child : children_) { for (Component& child : children_) {
if (child->OnEvent(event)) if (child->OnEvent(event))
return true; return true;
} }

View File

@ -1,205 +1,205 @@
#include <gtest/gtest-message.h> // for Message #include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver #include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
#include <memory> // for allocator #include <memory> // for __shared_ptr_access, shared_ptr, allocator
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/container.hpp" #include "ftxui/component/container.hpp"
#include "ftxui/screen/box.hpp" // for ftxui #include "gtest/gtest_pred_impl.h" // for AssertionResult, EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, Test, TEST
#include "gtest/gtest_pred_impl.h" // for AssertionResult, EXPECT_EQ, EXPEC...
using namespace ftxui; using namespace ftxui;
TEST(ContainerTest, HorizontalEvent) { TEST(ContainerTest, HorizontalEvent) {
auto container = Container::Horizontal(); auto container = Container::Horizontal();
Component c0, c1, c2; Component c0, c1, c2;
container.Add(&c0); container->Add(c0);
container.Add(&c1); container->Add(c1);
container.Add(&c2); container->Add(c2);
// With arrow key. // With arrow key.
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::ArrowRight); container->OnEvent(Event::ArrowRight);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::ArrowRight); container->OnEvent(Event::ArrowRight);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::ArrowRight); container->OnEvent(Event::ArrowRight);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::ArrowLeft); container->OnEvent(Event::ArrowLeft);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::ArrowLeft); container->OnEvent(Event::ArrowLeft);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::ArrowLeft); container->OnEvent(Event::ArrowLeft);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With arrow key in the wrong dimension. // With arrow key in the wrong dimension.
container.OnEvent(Event::ArrowUp); container->OnEvent(Event::ArrowUp);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::ArrowDown); container->OnEvent(Event::ArrowDown);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With vim like characters. // With vim like characters.
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Character('l')); container->OnEvent(Event::Character('l'));
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Character('l')); container->OnEvent(Event::Character('l'));
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::Character('l')); container->OnEvent(Event::Character('l'));
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::Character('h')); container->OnEvent(Event::Character('h'));
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Character('h')); container->OnEvent(Event::Character('h'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Character('h')); container->OnEvent(Event::Character('h'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With vim like characters in the wrong direction. // With vim like characters in the wrong direction.
container.OnEvent(Event::Character('j')); container->OnEvent(Event::Character('j'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Character('k')); container->OnEvent(Event::Character('k'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With tab characters. // With tab characters.
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
} }
TEST(ContainerTest, VerticalEvent) { TEST(ContainerTest, VerticalEvent) {
auto container = Container::Vertical(); auto container = Container::Vertical();
Component c0, c1, c2; Component c0, c1, c2;
container.Add(&c0); container->Add(c0);
container.Add(&c1); container->Add(c1);
container.Add(&c2); container->Add(c2);
// With arrow key. // With arrow key.
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::ArrowDown); container->OnEvent(Event::ArrowDown);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::ArrowDown); container->OnEvent(Event::ArrowDown);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::ArrowDown); container->OnEvent(Event::ArrowDown);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::ArrowUp); container->OnEvent(Event::ArrowUp);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::ArrowUp); container->OnEvent(Event::ArrowUp);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::ArrowUp); container->OnEvent(Event::ArrowUp);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With arrow key in the wrong dimension. // With arrow key in the wrong dimension.
container.OnEvent(Event::ArrowLeft); container->OnEvent(Event::ArrowLeft);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::ArrowRight); container->OnEvent(Event::ArrowRight);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With vim like characters. // With vim like characters.
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Character('j')); container->OnEvent(Event::Character('j'));
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Character('j')); container->OnEvent(Event::Character('j'));
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::Character('j')); container->OnEvent(Event::Character('j'));
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::Character('k')); container->OnEvent(Event::Character('k'));
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Character('k')); container->OnEvent(Event::Character('k'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Character('k')); container->OnEvent(Event::Character('k'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With vim like characters in the wrong direction. // With vim like characters in the wrong direction.
container.OnEvent(Event::Character('h')); container->OnEvent(Event::Character('h'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Character('l')); container->OnEvent(Event::Character('l'));
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
// With tab characters. // With tab characters.
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::Tab); container->OnEvent(Event::Tab);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
container.OnEvent(Event::TabReverse); container->OnEvent(Event::TabReverse);
} }
TEST(ContainerTest, SetActiveChild) { TEST(ContainerTest, SetActiveChild) {
auto container = Container::Horizontal(); auto container = Container::Horizontal();
Component c0, c1, c2; Component c0, c1, c2;
container.Add(&c0); container->Add(c0);
container.Add(&c1); container->Add(c1);
container.Add(&c2); container->Add(c2);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
EXPECT_TRUE(c0.Focused()); EXPECT_TRUE(c0->Focused());
EXPECT_TRUE(c0.Active()); EXPECT_TRUE(c0->Active());
EXPECT_FALSE(c1.Focused()); EXPECT_FALSE(c1->Focused());
EXPECT_FALSE(c1.Active()); EXPECT_FALSE(c1->Active());
EXPECT_FALSE(c2.Focused()); EXPECT_FALSE(c2->Focused());
EXPECT_FALSE(c2.Active()); EXPECT_FALSE(c2->Active());
container.SetActiveChild(&c0); container->SetActiveChild(c0);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
EXPECT_TRUE(c0.Focused()); EXPECT_TRUE(c0->Focused());
EXPECT_TRUE(c0.Active()); EXPECT_TRUE(c0->Active());
EXPECT_FALSE(c1.Focused()); EXPECT_FALSE(c1->Focused());
EXPECT_FALSE(c1.Active()); EXPECT_FALSE(c1->Active());
EXPECT_FALSE(c2.Focused()); EXPECT_FALSE(c2->Focused());
EXPECT_FALSE(c2.Active()); EXPECT_FALSE(c2->Active());
container.SetActiveChild(&c1); container->SetActiveChild(c1);
EXPECT_EQ(container.ActiveChild(), &c1); EXPECT_EQ(container->ActiveChild(), c1);
EXPECT_FALSE(c0.Focused()); EXPECT_FALSE(c0->Focused());
EXPECT_FALSE(c0.Active()); EXPECT_FALSE(c0->Active());
EXPECT_TRUE(c1.Focused()); EXPECT_TRUE(c1->Focused());
EXPECT_TRUE(c1.Active()); EXPECT_TRUE(c1->Active());
EXPECT_FALSE(c2.Focused()); EXPECT_FALSE(c2->Focused());
EXPECT_FALSE(c2.Active()); EXPECT_FALSE(c2->Active());
container.SetActiveChild(&c2); container->SetActiveChild(c2);
EXPECT_EQ(container.ActiveChild(), &c2); EXPECT_EQ(container->ActiveChild(), c2);
EXPECT_FALSE(c0.Focused()); EXPECT_FALSE(c0->Focused());
EXPECT_FALSE(c0.Active()); EXPECT_FALSE(c0->Active());
EXPECT_FALSE(c1.Focused()); EXPECT_FALSE(c1->Focused());
EXPECT_FALSE(c1.Active()); EXPECT_FALSE(c1->Active());
EXPECT_TRUE(c2.Focused()); EXPECT_TRUE(c2->Focused());
EXPECT_TRUE(c2.Active()); EXPECT_TRUE(c2->Active());
container.SetActiveChild(&c0); container->SetActiveChild(c0);
EXPECT_EQ(container.ActiveChild(), &c0); EXPECT_EQ(container->ActiveChild(), c0);
EXPECT_TRUE(c0.Focused()); EXPECT_TRUE(c0->Focused());
EXPECT_TRUE(c0.Active()); EXPECT_TRUE(c0->Active());
EXPECT_FALSE(c1.Focused()); EXPECT_FALSE(c1->Focused());
EXPECT_FALSE(c1.Active()); EXPECT_FALSE(c1->Active());
EXPECT_FALSE(c2.Focused()); EXPECT_FALSE(c2->Focused());
EXPECT_FALSE(c2.Active()); EXPECT_FALSE(c2->Active());
} }
TEST(ContainerTest, TakeFocus) { TEST(ContainerTest, TakeFocus) {
@ -214,74 +214,74 @@ TEST(ContainerTest, TakeFocus) {
auto c22 = Container::Horizontal(); auto c22 = Container::Horizontal();
auto c23 = Container::Horizontal(); auto c23 = Container::Horizontal();
c.Add(&c1); c->Add(c1);
c.Add(&c2); c->Add(c2);
c.Add(&c3); c->Add(c3);
c1.Add(&c11); c1->Add(c11);
c1.Add(&c12); c1->Add(c12);
c1.Add(&c13); c1->Add(c13);
c2.Add(&c21); c2->Add(c21);
c2.Add(&c22); c2->Add(c22);
c2.Add(&c23); c2->Add(c23);
EXPECT_TRUE(c.Focused()); EXPECT_TRUE(c->Focused());
EXPECT_TRUE(c1.Focused()); EXPECT_TRUE(c1->Focused());
EXPECT_FALSE(c2.Focused()); EXPECT_FALSE(c2->Focused());
EXPECT_TRUE(c11.Focused()); EXPECT_TRUE(c11->Focused());
EXPECT_FALSE(c12.Focused()); EXPECT_FALSE(c12->Focused());
EXPECT_FALSE(c13.Focused()); EXPECT_FALSE(c13->Focused());
EXPECT_FALSE(c21.Focused()); EXPECT_FALSE(c21->Focused());
EXPECT_FALSE(c22.Focused()); EXPECT_FALSE(c22->Focused());
EXPECT_FALSE(c23.Focused()); EXPECT_FALSE(c23->Focused());
EXPECT_TRUE(c.Active()); EXPECT_TRUE(c->Active());
EXPECT_TRUE(c1.Active()); EXPECT_TRUE(c1->Active());
EXPECT_FALSE(c2.Active()); EXPECT_FALSE(c2->Active());
EXPECT_TRUE(c11.Active()); EXPECT_TRUE(c11->Active());
EXPECT_FALSE(c12.Active()); EXPECT_FALSE(c12->Active());
EXPECT_FALSE(c13.Active()); EXPECT_FALSE(c13->Active());
EXPECT_TRUE(c21.Active()); EXPECT_TRUE(c21->Active());
EXPECT_FALSE(c22.Active()); EXPECT_FALSE(c22->Active());
EXPECT_FALSE(c23.Active()); EXPECT_FALSE(c23->Active());
c22.TakeFocus(); c22->TakeFocus();
EXPECT_TRUE(c.Focused()); EXPECT_TRUE(c->Focused());
EXPECT_FALSE(c1.Focused()); EXPECT_FALSE(c1->Focused());
EXPECT_TRUE(c2.Focused()); EXPECT_TRUE(c2->Focused());
EXPECT_FALSE(c11.Focused()); EXPECT_FALSE(c11->Focused());
EXPECT_FALSE(c12.Focused()); EXPECT_FALSE(c12->Focused());
EXPECT_FALSE(c13.Focused()); EXPECT_FALSE(c13->Focused());
EXPECT_FALSE(c21.Focused()); EXPECT_FALSE(c21->Focused());
EXPECT_TRUE(c22.Focused()); EXPECT_TRUE(c22->Focused());
EXPECT_FALSE(c23.Focused()); EXPECT_FALSE(c23->Focused());
EXPECT_TRUE(c.Active()); EXPECT_TRUE(c->Active());
EXPECT_FALSE(c1.Active()); EXPECT_FALSE(c1->Active());
EXPECT_TRUE(c2.Active()); EXPECT_TRUE(c2->Active());
EXPECT_TRUE(c11.Active()); EXPECT_TRUE(c11->Active());
EXPECT_FALSE(c12.Active()); EXPECT_FALSE(c12->Active());
EXPECT_FALSE(c13.Active()); EXPECT_FALSE(c13->Active());
EXPECT_FALSE(c21.Active()); EXPECT_FALSE(c21->Active());
EXPECT_TRUE(c22.Active()); EXPECT_TRUE(c22->Active());
EXPECT_FALSE(c23.Active()); EXPECT_FALSE(c23->Active());
c1.TakeFocus(); c1->TakeFocus();
EXPECT_TRUE(c.Focused()); EXPECT_TRUE(c->Focused());
EXPECT_TRUE(c1.Focused()); EXPECT_TRUE(c1->Focused());
EXPECT_FALSE(c2.Focused()); EXPECT_FALSE(c2->Focused());
EXPECT_TRUE(c11.Focused()); EXPECT_TRUE(c11->Focused());
EXPECT_FALSE(c12.Focused()); EXPECT_FALSE(c12->Focused());
EXPECT_FALSE(c13.Focused()); EXPECT_FALSE(c13->Focused());
EXPECT_FALSE(c21.Focused()); EXPECT_FALSE(c21->Focused());
EXPECT_FALSE(c22.Focused()); EXPECT_FALSE(c22->Focused());
EXPECT_FALSE(c23.Focused()); EXPECT_FALSE(c23->Focused());
EXPECT_TRUE(c.Active()); EXPECT_TRUE(c->Active());
EXPECT_TRUE(c1.Active()); EXPECT_TRUE(c1->Active());
EXPECT_FALSE(c2.Active()); EXPECT_FALSE(c2->Active());
EXPECT_TRUE(c11.Active()); EXPECT_TRUE(c11->Active());
EXPECT_FALSE(c12.Active()); EXPECT_FALSE(c12->Active());
EXPECT_FALSE(c13.Active()); EXPECT_FALSE(c13->Active());
EXPECT_FALSE(c21.Active()); EXPECT_FALSE(c21->Active());
EXPECT_TRUE(c22.Active()); EXPECT_TRUE(c22->Active());
EXPECT_FALSE(c23.Active()); EXPECT_FALSE(c23->Active());
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,7 +1,8 @@
#include "ftxui/component/event.hpp" #include <utility> // for move
#include "ftxui/component/mouse.hpp" #include "ftxui/component/event.hpp"
#include "ftxui/screen/string.hpp" #include "ftxui/component/mouse.hpp" // for Mouse
#include "ftxui/screen/string.hpp" // for to_wstring
namespace ftxui { namespace ftxui {

View File

@ -1,39 +1,73 @@
#include <algorithm> // for max, min
#include <memory> // for shared_ptr
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Backspace, Event::Custom, Event::Delete, Event::End, Event::Home, Event::Return
#include "ftxui/component/input.hpp" #include "ftxui/component/input.hpp"
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include <algorithm> #include "ftxui/component/screen_interactive.hpp" // for Component
#include <memory>
#include "ftxui/component/captured_mouse.hpp"
#include "ftxui/component/mouse.hpp"
#include "ftxui/component/screen_interactive.hpp"
namespace ftxui { namespace ftxui {
/// @brief An input box for editing text.
/// @param content The editable content.
/// @param placeholder The text displayed when content is still empty.
/// @ingroup component
/// @see InputBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::wstring content= L"";
/// std::wstring placeholder = L"placeholder";
/// Component input = Input(&content, &placeholder);
/// screen.Loop(input);
/// ```
///
/// ### Output
///
/// ```bash
/// placeholder
/// ```
Component Input(std::wstring* content, const std::wstring* placeholder) {
return Make<InputBase>(content, placeholder);
}
// static
InputBase* InputBase::From(Component component) {
return static_cast<InputBase*>(component.get());
}
InputBase::InputBase(std::wstring* content, const std::wstring* placeholder)
: content_(content), placeholder_(placeholder) {}
// Component implementation. // Component implementation.
Element Input::Render() { Element InputBase::Render() {
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position)); cursor_position =
std::max(0, std::min<int>(content_->size(), cursor_position));
auto main_decorator = flex | size(HEIGHT, EQUAL, 1); auto main_decorator = flex | size(HEIGHT, EQUAL, 1);
bool is_focused = Focused(); bool is_focused = Focused();
// Placeholder. // placeholder.
if (content.size() == 0) { if (content_->size() == 0) {
if (is_focused) if (is_focused)
return text(placeholder) | focus | dim | inverted | main_decorator | return text(*placeholder_) | focus | dim | inverted | main_decorator |
reflect(input_box_); reflect(input_box_);
else else
return text(placeholder) | dim | main_decorator | reflect(input_box_); return text(*placeholder_) | dim | main_decorator | reflect(input_box_);
} }
// Not focused. // Not focused.
if (!is_focused) if (!is_focused)
return text(content) | main_decorator | reflect(input_box_); return text(*content_) | main_decorator | reflect(input_box_);
std::wstring part_before_cursor = content.substr(0, cursor_position); std::wstring part_before_cursor = content_->substr(0, cursor_position);
std::wstring part_at_cursor = cursor_position < (int)content.size() std::wstring part_at_cursor = cursor_position < (int)content_->size()
? content.substr(cursor_position, 1) ? content_->substr(cursor_position, 1)
: L" "; : L" ";
std::wstring part_after_cursor = cursor_position < (int)content.size() - 1 std::wstring part_after_cursor = cursor_position < (int)content_->size() - 1
? content.substr(cursor_position + 1) ? content_->substr(cursor_position + 1)
: L""; : L"";
auto focused = is_focused ? focus : select; auto focused = is_focused ? focus : select;
@ -47,8 +81,9 @@ Element Input::Render() {
// clang-format on // clang-format on
} }
bool Input::OnEvent(Event event) { bool InputBase::OnEvent(Event event) {
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position)); cursor_position =
std::max(0, std::min<int>(content_->size(), cursor_position));
if (event.is_mouse()) if (event.is_mouse())
return OnMouseEvent(event); return OnMouseEvent(event);
@ -59,7 +94,7 @@ bool Input::OnEvent(Event event) {
if (event == Event::Backspace) { if (event == Event::Backspace) {
if (cursor_position == 0) if (cursor_position == 0)
return false; return false;
content.erase(cursor_position - 1, 1); content_->erase(cursor_position - 1, 1);
cursor_position--; cursor_position--;
on_change(); on_change();
return true; return true;
@ -67,9 +102,9 @@ bool Input::OnEvent(Event event) {
// Delete // Delete
if (event == Event::Delete) { if (event == Event::Delete) {
if (cursor_position == int(content.size())) if (cursor_position == int(content_->size()))
return false; return false;
content.erase(cursor_position, 1); content_->erase(cursor_position, 1);
on_change(); on_change();
return true; return true;
} }
@ -89,7 +124,7 @@ bool Input::OnEvent(Event event) {
return true; return true;
} }
if (event == Event::ArrowRight && cursor_position < (int)content.size()) { if (event == Event::ArrowRight && cursor_position < (int)content_->size()) {
cursor_position++; cursor_position++;
return true; return true;
} }
@ -100,13 +135,13 @@ bool Input::OnEvent(Event event) {
} }
if (event == Event::End) { if (event == Event::End) {
cursor_position = (int)content.size(); cursor_position = (int)content_->size();
return true; return true;
} }
// Content // Content
if (event.is_character()) { if (event.is_character()) {
content.insert(cursor_position, 1, event.character()); content_->insert(cursor_position, 1, event.character());
cursor_position++; cursor_position++;
on_change(); on_change();
return true; return true;
@ -114,7 +149,7 @@ bool Input::OnEvent(Event event) {
return false; return false;
} }
bool Input::OnMouseEvent(Event event) { bool InputBase::OnMouseEvent(Event event) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
if (!input_box_.Contain(event.mouse().x, event.mouse().y)) if (!input_box_.Contain(event.mouse().x, event.mouse().y))
@ -127,7 +162,7 @@ bool Input::OnMouseEvent(Event event) {
int new_cursor_position = int new_cursor_position =
cursor_position + event.mouse().x - cursor_box_.x_min; cursor_position + event.mouse().x - cursor_box_.x_min;
new_cursor_position = new_cursor_position =
std::max(0, std::min<int>(content.size(), new_cursor_position)); std::max(0, std::min<int>(content_->size(), new_cursor_position));
if (cursor_position != new_cursor_position) { if (cursor_position != new_cursor_position) {
cursor_position = new_cursor_position; cursor_position = new_cursor_position;
on_change(); on_change();

View File

@ -1,159 +1,181 @@
#include "ftxui/component/input.hpp" #include <gtest/gtest-message.h> // for Message
#include "ftxui/component/event.hpp" #include <gtest/gtest-test-part.h> // for TestPartResult
#include <memory> // for __shared_ptr_access
#include "gtest/gtest.h" #include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Backspace, Event::Delete, Event::End, Event::Home
#include "ftxui/component/input.hpp"
#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, SuiteApiResolver, TEST, TestFactoryImpl
using namespace ftxui; using namespace ftxui;
TEST(InputTest, Init) { TEST(InputTest, Init) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
EXPECT_EQ(input.content, L""); EXPECT_EQ(InputBase::From(input)->cursor_position, 0);
EXPECT_EQ(input.placeholder, L"");
EXPECT_EQ(input.cursor_position, 0);
} }
TEST(InputTest, Type) { TEST(InputTest, Type) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
input.OnEvent(Event::Character('a')); input->OnEvent(Event::Character('a'));
EXPECT_EQ(input.content, L"a"); EXPECT_EQ(content, L"a");
EXPECT_EQ(input.cursor_position, 1u); EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
input.OnEvent(Event::Character('b')); input->OnEvent(Event::Character('b'));
EXPECT_EQ(input.content, L"ab"); EXPECT_EQ(content, L"ab");
EXPECT_EQ(input.cursor_position, 2u); EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
} }
TEST(InputTest, Arrow) { TEST(InputTest, Arrow) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
input.OnEvent(Event::Character('a')); input->OnEvent(Event::Character('a'));
input.OnEvent(Event::Character('b')); input->OnEvent(Event::Character('b'));
input.OnEvent(Event::Character('c')); input->OnEvent(Event::Character('c'));
EXPECT_EQ(input.cursor_position, 3u); EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
EXPECT_EQ(input.cursor_position, 2u); EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
EXPECT_EQ(input.cursor_position, 1u); EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
EXPECT_EQ(input.cursor_position, 0u); EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
EXPECT_EQ(input.cursor_position, 0u); EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
input.OnEvent(Event::ArrowRight); input->OnEvent(Event::ArrowRight);
EXPECT_EQ(input.cursor_position, 1u); EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
input.OnEvent(Event::ArrowRight); input->OnEvent(Event::ArrowRight);
EXPECT_EQ(input.cursor_position, 2u); EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
input.OnEvent(Event::ArrowRight); input->OnEvent(Event::ArrowRight);
EXPECT_EQ(input.cursor_position, 3u); EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
input.OnEvent(Event::ArrowRight); input->OnEvent(Event::ArrowRight);
EXPECT_EQ(input.cursor_position, 3u); EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
} }
TEST(InputTest, Insert) { TEST(InputTest, Insert) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
input.OnEvent(Event::Character('a')); input->OnEvent(Event::Character('a'));
input.OnEvent(Event::Character('b')); input->OnEvent(Event::Character('b'));
input.OnEvent(Event::Character('c')); input->OnEvent(Event::Character('c'));
EXPECT_EQ(input.content, L"abc"); EXPECT_EQ(content, L"abc");
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
input.OnEvent(Event::Character('-')); input->OnEvent(Event::Character('-'));
EXPECT_EQ(input.content, L"a-bc"); EXPECT_EQ(content, L"a-bc");
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
input.OnEvent(Event::Character('-')); input->OnEvent(Event::Character('-'));
EXPECT_EQ(input.content, L"a--bc"); EXPECT_EQ(content, L"a--bc");
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
input.OnEvent(Event::Character('-')); input->OnEvent(Event::Character('-'));
EXPECT_EQ(input.content, L"-a--bc"); EXPECT_EQ(content, L"-a--bc");
} }
TEST(InputTest, Home) { TEST(InputTest, Home) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
input.OnEvent(Event::Character('a')); input->OnEvent(Event::Character('a'));
input.OnEvent(Event::Character('b')); input->OnEvent(Event::Character('b'));
input.OnEvent(Event::Character('c')); input->OnEvent(Event::Character('c'));
EXPECT_EQ(input.content, L"abc"); EXPECT_EQ(content, L"abc");
EXPECT_EQ(input.cursor_position, 3u); EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
input.OnEvent(Event::Home); input->OnEvent(Event::Home);
EXPECT_EQ(input.cursor_position, 0u); EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
input.OnEvent(Event::Character('-')); input->OnEvent(Event::Character('-'));
EXPECT_EQ(input.content, L"-abc"); EXPECT_EQ(content, L"-abc");
} }
TEST(InputTest, End) { TEST(InputTest, End) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
input.OnEvent(Event::Character('a')); input->OnEvent(Event::Character('a'));
input.OnEvent(Event::Character('b')); input->OnEvent(Event::Character('b'));
input.OnEvent(Event::Character('c')); input->OnEvent(Event::Character('c'));
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
EXPECT_EQ(input.cursor_position, 1u); EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
input.OnEvent(Event::End); input->OnEvent(Event::End);
EXPECT_EQ(input.cursor_position, 3u); EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
} }
TEST(InputTest, Delete) { TEST(InputTest, Delete) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
input.OnEvent(Event::Character('a')); input->OnEvent(Event::Character('a'));
input.OnEvent(Event::Character('b')); input->OnEvent(Event::Character('b'));
input.OnEvent(Event::Character('c')); input->OnEvent(Event::Character('c'));
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
EXPECT_EQ(input.content, L"abc"); EXPECT_EQ(content, L"abc");
EXPECT_EQ(input.cursor_position, 2u); EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
input.OnEvent(Event::Delete); input->OnEvent(Event::Delete);
EXPECT_EQ(input.content, L"ab"); EXPECT_EQ(content, L"ab");
EXPECT_EQ(input.cursor_position, 2u); EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
input.OnEvent(Event::Delete); input->OnEvent(Event::Delete);
EXPECT_EQ(input.content, L"ab"); EXPECT_EQ(content, L"ab");
EXPECT_EQ(input.cursor_position, 2u); EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
} }
TEST(InputTest, Backspace) { TEST(InputTest, Backspace) {
Input input; std::wstring content;
std::wstring placeholder;
Component input = Input(&content, &placeholder);
input.OnEvent(Event::Character('a')); input->OnEvent(Event::Character('a'));
input.OnEvent(Event::Character('b')); input->OnEvent(Event::Character('b'));
input.OnEvent(Event::Character('c')); input->OnEvent(Event::Character('c'));
input.OnEvent(Event::ArrowLeft); input->OnEvent(Event::ArrowLeft);
EXPECT_EQ(input.content, L"abc"); EXPECT_EQ(content, L"abc");
EXPECT_EQ(input.cursor_position, 2u); EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
input.OnEvent(Event::Backspace); input->OnEvent(Event::Backspace);
EXPECT_EQ(input.content, L"ac"); EXPECT_EQ(content, L"ac");
EXPECT_EQ(input.cursor_position, 1u); EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
input.OnEvent(Event::Backspace); input->OnEvent(Event::Backspace);
EXPECT_EQ(input.content, L"c"); EXPECT_EQ(content, L"c");
EXPECT_EQ(input.cursor_position, 0u); EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
input.OnEvent(Event::Backspace); input->OnEvent(Event::Backspace);
EXPECT_EQ(input.content, L"c"); EXPECT_EQ(content, L"c");
EXPECT_EQ(input.cursor_position, 0u); EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
} }
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@ -1,23 +1,63 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max, min
#include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <memory> // for shared_ptr, allocator_traits<>::value_type
#include <utility> // for move
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::Return, Event::Tab, Event::TabReverse
#include "ftxui/component/menu.hpp" #include "ftxui/component/menu.hpp"
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Released
#include <stddef.h> #include "ftxui/component/screen_interactive.hpp" // for Component
#include <algorithm>
#include <memory>
#include <utility>
#include "ftxui/component/captured_mouse.hpp"
#include "ftxui/component/mouse.hpp"
#include "ftxui/component/screen_interactive.hpp"
namespace ftxui { namespace ftxui {
Element Menu::Render() { /// @brief A list of text. The focused element is selected.
/// @param entries The list of entries in the menu.
/// @param selected The index of the currently selected element.
/// @ingroup component
/// @see MenuBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// std::vector<std::wstring> entries = {
/// L"entry 1",
/// L"entry 2",
/// L"entry 3",
/// };
/// int selected = 0;
/// auto menu = Menu(&entries, &selected);
/// screen.Loop(menu);
/// ```
///
/// ### Output
///
/// ```bash
/// > entry 1
/// entry 2
/// entry 3
/// ```
Component Menu(const std::vector<std::wstring>* entries, int* selected) {
return Make<MenuBase>(entries, selected);
}
// static
MenuBase* MenuBase::From(Component component) {
return static_cast<MenuBase*>(component.get());
}
MenuBase::MenuBase(const std::vector<std::wstring>* entries, int* selected)
: entries_(entries), selected_(selected) {}
Element MenuBase::Render() {
Elements elements; Elements elements;
bool is_menu_focused = Focused(); bool is_menu_focused = Focused();
boxes_.resize(entries.size()); boxes_.resize(entries_->size());
for (size_t i = 0; i < entries.size(); ++i) { for (size_t i = 0; i < entries_->size(); ++i) {
bool is_focused = (focused == int(i)) && is_menu_focused; bool is_focused = (focused == int(i)) && is_menu_focused;
bool is_selected = (selected == int(i)); bool is_selected = (*selected_ == int(i));
auto style = is_selected auto style = is_selected
? (is_focused ? selected_focused_style : selected_style) ? (is_focused ? selected_focused_style : selected_style)
@ -26,13 +66,13 @@ Element Menu::Render() {
: is_menu_focused ? focus : is_menu_focused ? focus
: select; : select;
auto icon = is_selected ? L"> " : L" "; auto icon = is_selected ? L"> " : L" ";
elements.push_back(text(icon + entries[i]) | style | focus_management | elements.push_back(text(icon + entries_->at(i)) | style | focus_management |
reflect(boxes_[i])); reflect(boxes_[i]));
} }
return vbox(std::move(elements)); return vbox(std::move(elements));
} }
bool Menu::OnEvent(Event event) { bool MenuBase::OnEvent(Event event) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
if (event.is_mouse()) if (event.is_mouse())
@ -41,20 +81,20 @@ bool Menu::OnEvent(Event event) {
if (!Focused()) if (!Focused())
return false; return false;
int old_selected = selected; int old_selected = *selected_;
if (event == Event::ArrowUp || event == Event::Character('k')) if (event == Event::ArrowUp || event == Event::Character('k'))
selected--; (*selected_)--;
if (event == Event::ArrowDown || event == Event::Character('j')) if (event == Event::ArrowDown || event == Event::Character('j'))
selected++; (*selected_)++;
if (event == Event::Tab && entries.size()) if (event == Event::Tab && entries_->size())
selected = (selected + 1) % entries.size(); *selected_ = (*selected_ + 1) % entries_->size();
if (event == Event::TabReverse && entries.size()) if (event == Event::TabReverse && entries_->size())
selected = (selected + entries.size() - 1) % entries.size(); *selected_ = (*selected_ + entries_->size() - 1) % entries_->size();
selected = std::max(0, std::min(int(entries.size()) - 1, selected)); *selected_ = std::max(0, std::min(int(entries_->size()) - 1, *selected_));
if (selected != old_selected) { if (*selected_ != old_selected) {
focused = selected; focused = *selected_;
on_change(); on_change();
return true; return true;
} }
@ -67,7 +107,7 @@ bool Menu::OnEvent(Event event) {
return false; return false;
} }
bool Menu::OnMouseEvent(Event event) { bool MenuBase::OnMouseEvent(Event event) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
for (int i = 0; i < boxes_.size(); ++i) { for (int i = 0; i < boxes_.size(); ++i) {
@ -78,8 +118,8 @@ bool Menu::OnMouseEvent(Event event) {
focused = i; focused = i;
if (event.mouse().button == Mouse::Left && if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Released) { event.mouse().motion == Mouse::Released) {
if (selected != i) { if (*selected_ != i) {
selected = i; *selected_ = i;
on_change(); on_change();
} }
return true; return true;

View File

@ -1,36 +1,76 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max, min
#include <functional> // for function
#include <memory> // for shared_ptr, allocator_traits<>::value_type
#include <utility> // for move
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::Return, Event::Tab, Event::TabReverse
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/component/radiobox.hpp" #include "ftxui/component/radiobox.hpp"
#include "ftxui/component/screen_interactive.hpp" // for Component
#include <stddef.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <utility>
#include "ftxui/component/captured_mouse.hpp"
#include "ftxui/component/mouse.hpp"
#include "ftxui/component/screen_interactive.hpp"
namespace ftxui { namespace ftxui {
Element RadioBox::Render() { /// @brief A list of element, where only one can be selected.
/// @param entries The list of entries in the list.
/// @param selected The index of the currently selected element.
/// @ingroup component
/// @see RadioboxBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// std::vector<std::wstring> entries = {
/// L"entry 1",
/// L"entry 2",
/// L"entry 3",
/// };
/// int selected = 0;
/// auto menu = Radiobox(&entries, &selected);
/// screen.Loop(menu);
/// ```
///
/// ### Output
///
/// ```bash
/// ◉ entry 1
/// ○ entry 2
/// ○ entry 3
/// ```
Component Radiobox(const std::vector<std::wstring>* entries, int* selected) {
return Make<RadioboxBase>(entries, selected);
}
// static
RadioboxBase* RadioboxBase::From(Component component) {
return static_cast<RadioboxBase*>(component.get());
}
RadioboxBase::RadioboxBase(const std::vector<std::wstring>* entries,
int* selected_)
: entries_(entries), selected_(selected_) {}
Element RadioboxBase::Render() {
std::vector<Element> elements; std::vector<Element> elements;
bool is_focused = Focused(); bool is_focused = Focused();
boxes_.resize(entries.size()); boxes_.resize(entries_->size());
for (size_t i = 0; i < entries.size(); ++i) { for (size_t i = 0; i < entries_->size(); ++i) {
auto style = auto style =
(focused == int(i) && is_focused) ? focused_style : unfocused_style; (focused == int(i) && is_focused) ? focused_style : unfocused_style;
auto focus_management = (focused != int(i)) ? nothing auto focus_management = (focused != int(i)) ? nothing
: is_focused ? focus : is_focused ? focus
: select; : select;
const std::wstring& symbol = selected == int(i) ? checked : unchecked; const std::wstring& symbol = *selected_ == int(i) ? checked : unchecked;
elements.push_back(hbox(text(symbol), text(entries[i]) | style) | elements.push_back(hbox(text(symbol), text(entries_->at(i)) | style) |
focus_management | reflect(boxes_[i])); focus_management | reflect(boxes_[i]));
} }
return vbox(std::move(elements)); return vbox(std::move(elements));
} }
bool RadioBox::OnEvent(Event event) { bool RadioboxBase::OnEvent(Event event) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
if (event.is_mouse()) if (event.is_mouse())
@ -44,12 +84,12 @@ bool RadioBox::OnEvent(Event event) {
new_focused--; new_focused--;
if (event == Event::ArrowDown || event == Event::Character('j')) if (event == Event::ArrowDown || event == Event::Character('j'))
new_focused++; new_focused++;
if (event == Event::Tab && entries.size()) if (event == Event::Tab && entries_->size())
new_focused = (new_focused + 1) % entries.size(); new_focused = (new_focused + 1) % entries_->size();
if (event == Event::TabReverse && entries.size()) if (event == Event::TabReverse && entries_->size())
new_focused = (new_focused + entries.size() - 1) % entries.size(); new_focused = (new_focused + entries_->size() - 1) % entries_->size();
new_focused = std::max(0, std::min(int(entries.size()) - 1, new_focused)); new_focused = std::max(0, std::min(int(entries_->size()) - 1, new_focused));
if (focused != new_focused) { if (focused != new_focused) {
focused = new_focused; focused = new_focused;
@ -57,14 +97,14 @@ bool RadioBox::OnEvent(Event event) {
} }
if (event == Event::Character(' ') || event == Event::Return) { if (event == Event::Character(' ') || event == Event::Return) {
selected = focused; *selected_ = focused;
on_change(); on_change();
} }
return false; return false;
} }
bool RadioBox::OnMouseEvent(Event event) { bool RadioboxBase::OnMouseEvent(Event event) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
for (int i = 0; i < boxes_.size(); ++i) { for (int i = 0; i < boxes_.size(); ++i) {
@ -78,8 +118,8 @@ bool RadioBox::OnMouseEvent(Event event) {
event.mouse().motion == Mouse::Pressed) { event.mouse().motion == Mouse::Pressed) {
cursor_position = i; cursor_position = i;
TakeFocus(); TakeFocus();
if (selected != i) { if (*selected_ != i) {
selected = i; *selected_ = i;
on_change(); on_change();
} }
return true; return true;

View File

@ -1,7 +1,8 @@
#include <gtest/gtest-message.h> // for Message #include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl #include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
#include <memory> // for __shared_ptr_access, shared_ptr
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::Tab, Event::TabReverse #include "ftxui/component/event.hpp" // for Event, Event::Return, Event::ArrowDown, Event::ArrowUp, Event::Tab, Event::TabReverse
#include "ftxui/component/mouse.hpp" // for ftxui #include "ftxui/component/mouse.hpp" // for ftxui
#include "ftxui/component/radiobox.hpp" #include "ftxui/component/radiobox.hpp"
#include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, TEST #include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, TEST
@ -9,76 +10,105 @@
using namespace ftxui; using namespace ftxui;
TEST(RadioboxTest, Navigation) { TEST(RadioboxTest, Navigation) {
RadioBox radiobox; int selected = 0;
radiobox.entries = {L"1", L"2", L"3"}; std::vector<std::wstring> entries = {L"1", L"2", L"3"};
auto radiobox = Radiobox(&entries, &selected);
// With arrow key. // With arrow key.
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 0);
radiobox.OnEvent(Event::ArrowDown); radiobox->OnEvent(Event::ArrowDown);
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::ArrowDown); EXPECT_EQ(selected, 1);
EXPECT_EQ(radiobox.focused, 2); radiobox->OnEvent(Event::ArrowDown);
radiobox.OnEvent(Event::ArrowDown); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 2); EXPECT_EQ(selected, 2);
radiobox.OnEvent(Event::ArrowUp); radiobox->OnEvent(Event::ArrowDown);
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::ArrowUp); EXPECT_EQ(selected, 2);
EXPECT_EQ(radiobox.focused, 0); radiobox->OnEvent(Event::ArrowUp);
radiobox.OnEvent(Event::ArrowUp); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 1);
radiobox->OnEvent(Event::ArrowUp);
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 0);
radiobox->OnEvent(Event::ArrowUp);
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 0);
// With vim like characters. // With vim like characters.
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 0);
radiobox.OnEvent(Event::Character('j')); radiobox->OnEvent(Event::Character('j'));
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::Character('j')); EXPECT_EQ(selected, 1);
EXPECT_EQ(radiobox.focused, 2); radiobox->OnEvent(Event::Character('j'));
radiobox.OnEvent(Event::Character('j')); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 2); EXPECT_EQ(selected, 2);
radiobox.OnEvent(Event::Character('k')); radiobox->OnEvent(Event::Character('j'));
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::Character('k')); EXPECT_EQ(selected, 2);
EXPECT_EQ(radiobox.focused, 0); radiobox->OnEvent(Event::Character('k'));
radiobox.OnEvent(Event::Character('k')); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 1);
radiobox->OnEvent(Event::Character('k'));
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 0);
radiobox->OnEvent(Event::Character('k'));
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 0);
// With more entries // With more entries
radiobox.entries = {L"1", L"2", L"3"}; entries = {L"1", L"2", L"3"};
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 0);
radiobox.OnEvent(Event::ArrowDown); radiobox->OnEvent(Event::ArrowDown);
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::ArrowDown); EXPECT_EQ(selected, 1);
EXPECT_EQ(radiobox.focused, 2); radiobox->OnEvent(Event::ArrowDown);
radiobox.OnEvent(Event::ArrowDown); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 2); EXPECT_EQ(selected, 2);
radiobox.OnEvent(Event::ArrowUp); radiobox->OnEvent(Event::ArrowDown);
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::ArrowUp); EXPECT_EQ(selected, 2);
EXPECT_EQ(radiobox.focused, 0); radiobox->OnEvent(Event::ArrowUp);
radiobox.OnEvent(Event::ArrowUp); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 1);
radiobox->OnEvent(Event::ArrowUp);
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 0);
radiobox->OnEvent(Event::ArrowUp);
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 0);
// With tab. // With tab.
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 0);
radiobox.OnEvent(Event::Tab); radiobox->OnEvent(Event::Tab);
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::Tab); EXPECT_EQ(selected, 1);
EXPECT_EQ(radiobox.focused, 2); radiobox->OnEvent(Event::Tab);
radiobox.OnEvent(Event::Tab); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 0); EXPECT_EQ(selected, 2);
radiobox.OnEvent(Event::Tab); radiobox->OnEvent(Event::Tab);
EXPECT_EQ(radiobox.focused, 1); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::Tab); EXPECT_EQ(selected, 0);
EXPECT_EQ(radiobox.focused, 2); radiobox->OnEvent(Event::Tab);
radiobox.OnEvent(Event::TabReverse); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 1); EXPECT_EQ(selected, 1);
radiobox.OnEvent(Event::TabReverse); radiobox->OnEvent(Event::Tab);
EXPECT_EQ(radiobox.focused, 0); radiobox->OnEvent(Event::Return);
radiobox.OnEvent(Event::TabReverse); EXPECT_EQ(selected, 2);
EXPECT_EQ(radiobox.focused, 2); radiobox->OnEvent(Event::TabReverse);
radiobox.OnEvent(Event::TabReverse); radiobox->OnEvent(Event::Return);
EXPECT_EQ(radiobox.focused, 1); EXPECT_EQ(selected, 1);
radiobox.OnEvent(Event::TabReverse); radiobox->OnEvent(Event::TabReverse);
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 0);
radiobox->OnEvent(Event::TabReverse);
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 2);
radiobox->OnEvent(Event::TabReverse);
radiobox->OnEvent(Event::Return);
EXPECT_EQ(selected, 1);
radiobox->OnEvent(Event::TabReverse);
radiobox->OnEvent(Event::Return);
} }
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -1,24 +1,23 @@
#include "ftxui/component/screen_interactive.hpp"
#include <stdio.h> // for fileno, stdin #include <stdio.h> // for fileno, stdin
#include <algorithm> // for copy, max, min #include <algorithm> // for copy, max, min
#include <csignal> // for signal, SIGINT #include <csignal> // for signal, SIGINT, SIGWINCH
#include <cstdlib> // for exit, NULL #include <cstdlib> // for exit, NULL
#include <iostream> // for cout, ostream #include <iostream> // for cout, ostream, basic_ostream, operator<<, endl, flush
#include <stack> // for stack #include <stack> // for stack
#include <thread> // for thread #include <thread> // for thread
#include <utility> // for move #include <utility> // for move
#include <vector> // for vector #include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse #include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
#include "ftxui/component/component.hpp" // for Component #include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/event.hpp" // for Event #include "ftxui/component/event.hpp" // for Event
#include "ftxui/component/mouse.hpp" // for Mouse #include "ftxui/component/mouse.hpp" // for Mouse
#include "ftxui/component/receiver.hpp" // for ReceiverImpl #include "ftxui/component/receiver.hpp" // for ReceiverImpl, SenderImpl, MakeReceiver
#include "ftxui/component/terminal_input_parser.hpp" // for TerminalInputPa... #include "ftxui/component/screen_interactive.hpp"
#include "ftxui/component/terminal_input_parser.hpp" // for TerminalInputParser
#include "ftxui/dom/node.hpp" // for Node, Render #include "ftxui/dom/node.hpp" // for Node, Render
#include "ftxui/dom/requirement.hpp" // for Requirement #include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/terminal.hpp" // for Terminal::Dimen... #include "ftxui/screen/terminal.hpp" // for Terminal::Dimensions, Terminal
#if defined(_WIN32) #if defined(_WIN32)
#define DEFINE_CONSOLEV2_PROPERTIES #define DEFINE_CONSOLEV2_PROPERTIES
@ -31,9 +30,9 @@
#error Must be compiled in UNICODE mode #error Must be compiled in UNICODE mode
#endif #endif
#else #else
#include <sys/select.h> // for select, FD_ISSET #include <sys/select.h> // for select, FD_ISSET, FD_SET, FD_ZERO, fd_set
#include <termios.h> // for tcsetattr, tcge... #include <termios.h> // for tcsetattr, termios, tcgetattr, TCSANOW, cc_t, ECHO, ICANON, VMIN, VTIME
#include <unistd.h> // for STDIN_FILENO, read #include <unistd.h> // for STDIN_FILENO, read
#endif #endif
// Quick exit is missing in standard CLang headers // Quick exit is missing in standard CLang headers
@ -110,7 +109,7 @@ void EventListener(std::atomic<bool>* quit, Sender<Event> out) {
char c; char c;
while (!*quit) { while (!*quit) {
while(read(STDIN_FILENO, &c, 1), c) while (read(STDIN_FILENO, &c, 1), c)
parser.Add(c); parser.Add(c);
emscripten_sleep(1); emscripten_sleep(1);
@ -278,7 +277,7 @@ CapturedMouse ScreenInteractive::CaptureMouse() {
[this] { mouse_captured = false; }); [this] { mouse_captured = false; });
} }
void ScreenInteractive::Loop(Component* component) { void ScreenInteractive::Loop(Component component) {
// Install a SIGINT handler and restore the old handler on exit. // Install a SIGINT handler and restore the old handler on exit.
auto old_sigint_handler = std::signal(SIGINT, OnExit); auto old_sigint_handler = std::signal(SIGINT, OnExit);
on_exit_functions.push( on_exit_functions.push(
@ -417,7 +416,7 @@ void ScreenInteractive::Loop(Component* component) {
OnExit(0); OnExit(0);
} }
void ScreenInteractive::Draw(Component* component) { void ScreenInteractive::Draw(Component component) {
auto document = component->Render(); auto document = component->Render();
int dimx = 0; int dimx = 0;
int dimy = 0; int dimy = 0;

View File

@ -1,21 +1,22 @@
#include "ftxui/component/slider.hpp" #include <string> // for allocator, wstring
#include <utility> // for move
#include <memory> #include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include <utility> #include "ftxui/component/component.hpp" // for Make, Slider
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/captured_mouse.hpp" #include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight
#include "ftxui/component/mouse.hpp" #include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
#include "ftxui/component/screen_interactive.hpp" #include "ftxui/component/screen_interactive.hpp" // for Component
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, text, color, operator|, xflex, gauge, dim, hbox, reflect, underlined, vcenter
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/color.hpp" #include "ftxui/screen/color.hpp" // for Color, Color::GrayDark, Color::GrayLight
namespace ftxui { namespace ftxui {
template <class T> template <class T>
class SliderImpl : public Component { class SliderBase : public ComponentBase {
public: public:
SliderImpl(std::wstring label, T* value, T min, T max, T increment) SliderBase(std::wstring label, T* value, T min, T max, T increment)
: label_(label), : label_(label),
value_(value), value_(value),
min_(min), min_(min),
@ -53,7 +54,7 @@ class SliderImpl : public Component {
return true; return true;
} }
return Component::OnEvent(event); return ComponentBase::OnEvent(event);
} }
bool OnMouseEvent(Event event) { bool OnMouseEvent(Event event) {
@ -62,8 +63,7 @@ class SliderImpl : public Component {
return true; return true;
} }
if (box_.Contain(event.mouse().x, event.mouse().y) && if (box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event)) {
CaptureMouse(event)) {
TakeFocus(); TakeFocus();
} }
@ -94,23 +94,44 @@ class SliderImpl : public Component {
CapturedMouse captured_mouse_; CapturedMouse captured_mouse_;
}; };
/// @brief An horizontal slider.
/// @param label The name of the slider.
/// @param value The current value of the slider.
/// @param min The minimum value.
/// @param max The maximum value.
/// @param increment The increment when used by the cursor.
/// @ingroup component
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// int value = 50;
/// auto slider = Slider(L"Value:", &value, 0, 100, 1);
/// screen.Loop(slider);
/// ```
///
/// ### Output
///
/// ```bash
/// Value:[██████████████████████████ ]
/// ```
template <class T> template <class T>
ComponentPtr Slider(std::wstring label, T* value, T min, T max, T increment) { Component Slider(std::wstring label, T* value, T min, T max, T increment) {
return std::make_unique<SliderImpl<T>>(std::move(label), value, min, max, return Make<SliderBase<T>>(std::move(label), value, min, max, increment);
increment);
} }
template ComponentPtr Slider(std::wstring label, template Component Slider(std::wstring label,
int* value, int* value,
int min, int min,
int max, int max,
int increment); int increment);
template ComponentPtr Slider(std::wstring label, template Component Slider(std::wstring label,
float* value, float* value,
float min, float min,
float max, float max,
float increment); float increment);
} // namespace ftxui } // namespace ftxui

View File

@ -1,26 +1,38 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <algorithm> // for max, min #include <algorithm> // for max, min
#include <memory> // for shared_ptr, alloca... #include <memory> // for shared_ptr, allocator_traits<>::value_type
#include <utility> // for move #include <utility> // for move
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse #include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left #include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive #include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/component/toggle.hpp" #include "ftxui/component/toggle.hpp"
namespace ftxui { namespace ftxui {
Element Toggle::Render() { Component Toggle(const std::vector<std::wstring>* entries, int* selected) {
return Make<ToggleBase>(entries, selected);
}
// static
ToggleBase* ToggleBase::From(Component component) {
return static_cast<ToggleBase*>(component.get());
}
ToggleBase::ToggleBase(const std::vector<std::wstring>* entries, int* selected)
: entries_(entries), selected_(selected) {}
Element ToggleBase::Render() {
Elements children; Elements children;
bool is_toggle_focused = Focused(); bool is_toggle_focused = Focused();
boxes_.resize(entries.size()); boxes_.resize(entries_->size());
for (size_t i = 0; i < entries.size(); ++i) { for (size_t i = 0; i < entries_->size(); ++i) {
// Separator. // Separator.
if (i != 0) if (i != 0)
children.push_back(separator()); children.push_back(separator());
bool is_focused = (focused == int(i)) && is_toggle_focused; bool is_focused = (focused == int(i)) && is_toggle_focused;
bool is_selected = (selected == int(i)); bool is_selected = (*selected_ == int(i));
auto style = is_selected auto style = is_selected
? (is_focused ? selected_focused_style : selected_style) ? (is_focused ? selected_focused_style : selected_style)
@ -28,30 +40,30 @@ Element Toggle::Render() {
auto focus_management = !is_selected ? nothing auto focus_management = !is_selected ? nothing
: is_toggle_focused ? focus : is_toggle_focused ? focus
: select; : select;
children.push_back(text(entries[i]) | style | focus_management | children.push_back(text(entries_->at(i)) | style | focus_management |
reflect(boxes_[i])); reflect(boxes_[i]));
} }
return hbox(std::move(children)); return hbox(std::move(children));
} }
bool Toggle::OnEvent(Event event) { bool ToggleBase::OnEvent(Event event) {
if (event.is_mouse()) if (event.is_mouse())
return OnMouseEvent(event); return OnMouseEvent(event);
int old_selected = selected; int old_selected = *selected_;
if (event == Event::ArrowLeft || event == Event::Character('h')) if (event == Event::ArrowLeft || event == Event::Character('h'))
selected--; (*selected_)--;
if (event == Event::ArrowRight || event == Event::Character('l')) if (event == Event::ArrowRight || event == Event::Character('l'))
selected++; (*selected_)++;
if (event == Event::Tab && entries.size()) if (event == Event::Tab && entries_->size())
selected = (selected + 1) % entries.size(); *selected_ = (*selected_ + 1) % entries_->size();
if (event == Event::TabReverse && entries.size()) if (event == Event::TabReverse && entries_->size())
selected = (selected + entries.size() - 1) % entries.size(); *selected_ = (*selected_ + entries_->size() - 1) % entries_->size();
selected = std::max(0, std::min(int(entries.size()) - 1, selected)); *selected_ = std::max(0, std::min(int(entries_->size()) - 1, *selected_));
if (old_selected != selected) { if (old_selected != *selected_) {
focused = selected; focused = *selected_;
on_change(); on_change();
return true; return true;
} }
@ -64,7 +76,7 @@ bool Toggle::OnEvent(Event event) {
return false; return false;
} }
bool Toggle::OnMouseEvent(Event event) { bool ToggleBase::OnMouseEvent(Event event) {
if (!CaptureMouse(event)) if (!CaptureMouse(event))
return false; return false;
for (int i = 0; i < boxes_.size(); ++i) { for (int i = 0; i < boxes_.size(); ++i) {
@ -76,8 +88,8 @@ bool Toggle::OnMouseEvent(Event event) {
if (event.mouse().button == Mouse::Left && if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) { event.mouse().motion == Mouse::Pressed) {
TakeFocus(); TakeFocus();
if (selected != i) { if (*selected_ != i) {
selected = i; *selected_ = i;
on_change(); on_change();
} }
return true; return true;

View File

@ -1,5 +1,6 @@
#include <gtest/gtest-message.h> // for Message #include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl #include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
#include <memory> // for __shared_ptr_access, shared_ptr
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse #include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse
#include "ftxui/component/mouse.hpp" // for ftxui #include "ftxui/component/mouse.hpp" // for ftxui
@ -9,131 +10,136 @@
using namespace ftxui; using namespace ftxui;
TEST(ToggleTest, leftRightArrow) { TEST(ToggleTest, leftRightArrow) {
Toggle toggle; std::vector<std::wstring> entries = {L"On", L"Off"};
int selected = 0;
auto toggle = Toggle(&entries, &selected);
// With arrow key. // With arrow key.
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::ArrowRight); toggle->OnEvent(Event::ArrowRight);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::ArrowRight); toggle->OnEvent(Event::ArrowRight);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::ArrowLeft); toggle->OnEvent(Event::ArrowLeft);
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::ArrowLeft); toggle->OnEvent(Event::ArrowLeft);
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
// With vim like characters. // With vim like characters.
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::Character('l')); toggle->OnEvent(Event::Character('l'));
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::Character('l')); toggle->OnEvent(Event::Character('l'));
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::Character('h')); toggle->OnEvent(Event::Character('h'));
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::Character('h')); toggle->OnEvent(Event::Character('h'));
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
// With more entries // With more entries
toggle.entries = {L"1", L"2", L"3"}; entries = {L"1", L"2", L"3"};
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::ArrowRight); toggle->OnEvent(Event::ArrowRight);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::ArrowRight); toggle->OnEvent(Event::ArrowRight);
EXPECT_EQ(toggle.selected, 2); EXPECT_EQ(selected, 2);
toggle.OnEvent(Event::ArrowRight); toggle->OnEvent(Event::ArrowRight);
EXPECT_EQ(toggle.selected, 2); EXPECT_EQ(selected, 2);
toggle.OnEvent(Event::ArrowLeft); toggle->OnEvent(Event::ArrowLeft);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::ArrowLeft); toggle->OnEvent(Event::ArrowLeft);
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::ArrowLeft); toggle->OnEvent(Event::ArrowLeft);
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
} }
TEST(ToggleTest, Tab) { TEST(ToggleTest, Tab) {
Toggle toggle; std::vector<std::wstring> entries = {L"1", L"2", L"3"};
toggle.entries = {L"1", L"2", L"3"}; int selected = 0;
auto toggle = Toggle(&entries, &selected);
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::Tab); toggle->OnEvent(Event::Tab);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::Tab); toggle->OnEvent(Event::Tab);
EXPECT_EQ(toggle.selected, 2); EXPECT_EQ(selected, 2);
toggle.OnEvent(Event::Tab); toggle->OnEvent(Event::Tab);
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::Tab); toggle->OnEvent(Event::Tab);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::Tab); toggle->OnEvent(Event::Tab);
EXPECT_EQ(toggle.selected, 2); EXPECT_EQ(selected, 2);
toggle.OnEvent(Event::TabReverse); toggle->OnEvent(Event::TabReverse);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::TabReverse); toggle->OnEvent(Event::TabReverse);
EXPECT_EQ(toggle.selected, 0); EXPECT_EQ(selected, 0);
toggle.OnEvent(Event::TabReverse); toggle->OnEvent(Event::TabReverse);
EXPECT_EQ(toggle.selected, 2); EXPECT_EQ(selected, 2);
toggle.OnEvent(Event::TabReverse); toggle->OnEvent(Event::TabReverse);
EXPECT_EQ(toggle.selected, 1); EXPECT_EQ(selected, 1);
toggle.OnEvent(Event::TabReverse); toggle->OnEvent(Event::TabReverse);
} }
TEST(ToggleTest, OnChange) { TEST(ToggleTest, OnChange) {
Toggle toggle; std::vector<std::wstring> entries = {L"1", L"2", L"3"};
toggle.entries = {L"1", L"2", L"3"}; int selected = 0;
auto toggle = Toggle(&entries, &selected);
int counter = 0; int counter = 0;
toggle.on_change = [&] { counter++; }; ToggleBase::From(toggle)->on_change = [&] { counter++; };
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left. EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
EXPECT_EQ(counter, 0); EXPECT_EQ(counter, 0);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [0] -> [1] EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [0] -> [1]
EXPECT_EQ(counter, 1); EXPECT_EQ(counter, 1);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [1] -> [2] EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [1] -> [2]
EXPECT_EQ(counter, 2); EXPECT_EQ(counter, 2);
EXPECT_FALSE(toggle.OnEvent(Event::ArrowRight)); // Reached far right. EXPECT_FALSE(toggle->OnEvent(Event::ArrowRight)); // Reached far right.
EXPECT_EQ(counter, 2); EXPECT_EQ(counter, 2);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [2] -> [1] EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [2] -> [1]
EXPECT_EQ(counter, 3); EXPECT_EQ(counter, 3);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [1] -> [0] EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [1] -> [0]
EXPECT_EQ(counter, 4); EXPECT_EQ(counter, 4);
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left. EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
EXPECT_EQ(counter, 4); EXPECT_EQ(counter, 4);
} }
TEST(ToggleTest, OnEnter) { TEST(ToggleTest, OnEnter) {
Toggle toggle; std::vector<std::wstring> entries = {L"1", L"2", L"3"};
toggle.entries = {L"1", L"2", L"3"}; int selected = 0;
auto toggle = Toggle(&entries, &selected);
int counter = 0; int counter = 0;
toggle.on_enter = [&] { counter++; }; ToggleBase::From(toggle)->on_enter = [&] { counter++; };
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left. EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
EXPECT_TRUE(toggle.OnEvent(Event::Return)); EXPECT_TRUE(toggle->OnEvent(Event::Return));
EXPECT_EQ(counter, 1); EXPECT_EQ(counter, 1);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [0] -> [1] EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [0] -> [1]
EXPECT_TRUE(toggle.OnEvent(Event::Return)); EXPECT_TRUE(toggle->OnEvent(Event::Return));
EXPECT_EQ(counter, 2); EXPECT_EQ(counter, 2);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [1] -> [2] EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [1] -> [2]
EXPECT_TRUE(toggle.OnEvent(Event::Return)); EXPECT_TRUE(toggle->OnEvent(Event::Return));
EXPECT_EQ(counter, 3); EXPECT_EQ(counter, 3);
EXPECT_FALSE(toggle.OnEvent(Event::ArrowRight)); // Reached far right. EXPECT_FALSE(toggle->OnEvent(Event::ArrowRight)); // Reached far right.
EXPECT_TRUE(toggle.OnEvent(Event::Return)); EXPECT_TRUE(toggle->OnEvent(Event::Return));
EXPECT_EQ(counter, 4); EXPECT_EQ(counter, 4);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [2] -> [1] EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [2] -> [1]
EXPECT_TRUE(toggle.OnEvent(Event::Return)); EXPECT_TRUE(toggle->OnEvent(Event::Return));
EXPECT_EQ(counter, 5); EXPECT_EQ(counter, 5);
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [1] -> [0] EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [1] -> [0]
EXPECT_TRUE(toggle.OnEvent(Event::Return)); EXPECT_TRUE(toggle->OnEvent(Event::Return));
EXPECT_EQ(counter, 6); EXPECT_EQ(counter, 6);
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left. EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
EXPECT_TRUE(toggle.OnEvent(Event::Return)); EXPECT_TRUE(toggle->OnEvent(Event::Return));
EXPECT_EQ(counter, 7); EXPECT_EQ(counter, 7);
} }

View File

@ -1,10 +1,11 @@
#include <memory> #include <memory> // for make_shared
#include <utility> // for move
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, blink
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,10 +1,11 @@
#include <memory> #include <memory> // for make_shared
#include <utility> // for move
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, bold
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,8 +1,9 @@
#include <algorithm> // for max #include <algorithm> // for max
#include <iterator> // for begin, end #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <memory> // for make_shared, __shared_ptr_access #include <iterator> // for begin, end
#include <utility> // for move #include <memory> // for make_shared, __shared_ptr_access
#include <vector> // for vector #include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for unpack, Element, Decorator, Elements, border, borderWith, window #include "ftxui/dom/elements.hpp" // for unpack, Element, Decorator, Elements, border, borderWith, window
#include "ftxui/dom/node.hpp" // for Node #include "ftxui/dom/node.hpp" // for Node

View File

@ -1,10 +1,11 @@
#include <memory> #include <memory> // for make_shared
#include <utility> // for move
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, clear_under
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,10 +1,11 @@
#include <memory> #include <memory> // for make_shared
#include <utility> // for move
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Decorator, Elements, bgcolor, color
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/color.hpp" #include "ftxui/screen/color.hpp" // for Color
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,5 +1,7 @@
#include "ftxui/dom/elements.hpp" #include <utility> // for move
#include "ftxui/dom/elements.hpp" // for Element, filler, operator|, hbox, flex_grow, vbox, xflex_grow, yflex_grow, align_right, center, hcenter, vcenter
namespace ftxui { namespace ftxui {

View File

@ -1,10 +1,11 @@
#include <memory> #include <memory> // for make_shared
#include <utility> // for move
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, dim
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,10 +1,12 @@
#include <memory> #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <vector> #include <memory> // for make_shared, __shared_ptr_access
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, filler, flex, flex_grow, flex_shrink, notflex, xflex, xflex_grow, xflex_shrink, yflex, yflex_grow, yflex_shrink
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/requirement.hpp" #include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {

View File

@ -1,7 +1,8 @@
#include <algorithm> // for max, min #include <algorithm> // for max, min
#include <memory> // for make_shared, shared_ptr, __shared_ptr_access #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <utility> // for move #include <memory> // for make_shared, shared_ptr, __shared_ptr_access
#include <vector> // for vector #include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for Element, unpack, focus, frame, select, xframe, yframe #include "ftxui/dom/elements.hpp" // for Element, unpack, focus, frame, select, xframe, yframe
#include "ftxui/dom/node.hpp" // for Node #include "ftxui/dom/node.hpp" // for Node

View File

@ -1,9 +1,10 @@
#include <memory> #include <memory> // for make_shared
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, gauge
#include "ftxui/dom/requirement.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/screen/box.hpp" #include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Screen
namespace ftxui { namespace ftxui {

View File

@ -1,10 +1,11 @@
#include <memory> #include <memory> // for make_shared
#include <utility> #include <utility> // for move
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, inverted
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/screen/box.hpp" #include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,5 +1,6 @@
#include <memory> // for __shared_ptr_access #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <vector> // for vector #include <memory> // for __shared_ptr_access
#include <vector> // for vector
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node_decorator.hpp"
#include "ftxui/dom/requirement.hpp" // for Requirement #include "ftxui/dom/requirement.hpp" // for Requirement

View File

@ -1,11 +1,12 @@
#include <memory> #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <utility> #include <memory> // for make_shared, __shared_ptr_access
#include <vector> #include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Decorator, reflect
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/requirement.hpp" #include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/box.hpp" #include "ftxui/screen/box.hpp" // for Box
namespace ftxui { namespace ftxui {

View File

@ -1,9 +1,10 @@
#include <memory> #include <memory> // for make_shared
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, separator
#include "ftxui/dom/node.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/screen/box.hpp" #include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,8 +1,9 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <algorithm> // for min, max #include <algorithm> // for min, max
#include <memory> // for make_shared, __shared_ptr_access #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <utility> // for move #include <memory> // for make_shared, __shared_ptr_access
#include <vector> // for vector #include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for Constraint, Direction, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size #include "ftxui/dom/elements.hpp" // for Constraint, Direction, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size
#include "ftxui/dom/node.hpp" // for Node #include "ftxui/dom/node.hpp" // for Node

View File

@ -1,9 +1,11 @@
#include <stddef.h> #include <stddef.h> // for size_t
#include <memory> #include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <string> #include <memory> // for allocator, allocator_traits<>::value_type
#include <vector> #include <string> // for basic_string, wstring
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, gauge, text, vbox, spinner
namespace ftxui { namespace ftxui {

View File

@ -1,11 +1,12 @@
#include <gtest/gtest-message.h> // for Message #include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult #include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl, TestPartResult
#include <memory> // for allocator #include <memory> // for allocator
#include "ftxui/dom/elements.hpp" // for text, Element, operator|, border #include "ftxui/dom/elements.hpp" // for text, Element, operator|, border
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui #include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/screen.hpp" // for Screen #include "ftxui/screen/screen.hpp" // for Screen
#include "gtest/gtest_pred_impl.h" // for Test, SuiteApiResolver, EXPECT_EQ #include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST
using namespace ftxui; using namespace ftxui;

View File

@ -1,10 +1,11 @@
#include <memory> #include <memory> // for make_shared
#include <utility> #include <utility> // for move
#include "ftxui/dom/elements.hpp" #include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, underlined
#include "ftxui/dom/node_decorator.hpp" #include "ftxui/dom/node.hpp" // for Node
#include "ftxui/screen/box.hpp" #include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
#include "ftxui/screen/screen.hpp" #include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
namespace ftxui { namespace ftxui {

View File

@ -1,4 +1,5 @@
#include <algorithm> // for min #include <algorithm> // for min
#include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <iostream> // for operator<<, basic_ostream, wstringstream, stringstream, flush, cout, ostream #include <iostream> // for operator<<, basic_ostream, wstringstream, stringstream, flush, cout, ostream
#include <sstream> // IWYU pragma: keep #include <sstream> // IWYU pragma: keep

View File

@ -1,4 +1,4 @@
// Copyright 2020 Arthur Sonzogni. All rights reserved. // Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in // Use of this source code is governed by the MIT license that can be found in
// the LICENSE file. // the LICENSE file.