mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-10-31 18:48:11 +08:00 
			
		
		
		
	Make component more functionnal
This commit is contained in:
		| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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: | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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", | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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_; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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_; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
							
								
								
									
										81
									
								
								include/ftxui/component/component_base.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								include/ftxui/component/component_base.hpp
									
									
									
									
									
										Normal 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. | ||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
| @@ -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_; | ||||||
|   | |||||||
| @@ -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_; | ||||||
|   | |||||||
| @@ -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_; | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
| @@ -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. |  | ||||||
| @@ -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_; | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								iwyu.imp
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								iwyu.imp
									
									
									
									
									
								
							| @@ -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"] } | ||||||
| ] | ] | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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(); | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ArthurSonzogni
					ArthurSonzogni