diff --git a/CMakeLists.txt b/CMakeLists.txt
index f1cc6b9..600d7ed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@ endif()
project(ftxui
LANGUAGES CXX
- VERSION 0.4.${git_version}
+ VERSION 0.5.${git_version}
)
option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON)
@@ -80,6 +80,7 @@ add_library(component
include/ftxui/component/captured_mouse.hpp
include/ftxui/component/checkbox.hpp
include/ftxui/component/component.hpp
+ include/ftxui/component/component_base.hpp
include/ftxui/component/container.hpp
include/ftxui/component/event.hpp
include/ftxui/component/input.hpp
@@ -88,7 +89,6 @@ add_library(component
include/ftxui/component/radiobox.hpp
include/ftxui/component/receiver.hpp
include/ftxui/component/screen_interactive.hpp
- include/ftxui/component/slider.hpp
include/ftxui/component/toggle.hpp
src/ftxui/component/button.cpp
src/ftxui/component/checkbox.cpp
@@ -99,6 +99,7 @@ add_library(component
src/ftxui/component/menu.cpp
src/ftxui/component/radiobox.cpp
src/ftxui/component/radiobox.cpp
+ src/ftxui/component/renderer.cpp
src/ftxui/component/screen_interactive.cpp
src/ftxui/component/slider.cpp
src/ftxui/component/terminal_input_parser.cpp
diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
index 4599a80..a01c5d8 100644
--- a/doc/Doxyfile.in
+++ b/doc/Doxyfile.in
@@ -44,7 +44,7 @@ PROJECT_NUMBER = @CMAKE_PROJECT_VERSION@
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF = "C++ functionnal terminal UI."
+PROJECT_BRIEF = "C++ functional terminal UI."
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
diff --git a/doc/example_list.md b/doc/example_list.md
index efddeab..5f65403 100644
--- a/doc/example_list.md
+++ b/doc/example_list.md
@@ -34,6 +34,7 @@
@example ./examples/component/input.cpp
@example ./examples/component/homescreen.cpp
@example ./examples/component/radiobox.cpp
+@example ./examples/component/slider_rgb.cpp
@example ./examples/component/menu.cpp
@example ./examples/component/menu_style.cpp
@example ./examples/component/radiobox_in_frame.cpp
diff --git a/doc/mainpage.md b/doc/mainpage.md
index 672fda1..38434b9 100644
--- a/doc/mainpage.md
+++ b/doc/mainpage.md
@@ -31,7 +31,7 @@ int main(void) {
Dimension::Fit(document) // Height
);
Render(screen, document);
- std::cout << screen.ToString() << std::endl;
+ screen.Print();
return EXIT_SUCCESS;
}
@@ -44,28 +44,71 @@ int main(void) {
└────┘└─────────────────────────────────────────────────────────────────┘└─────┘
```
-**cmake**
-```c
+# Build
+
+## Using CMake
+
+CMakeLists.txt
+~~~cmake
cmake_minimum_required (VERSION 3.11)
+# --- Fetch FTXUI --------------------------------------------------------------
include(FetchContent)
+
+set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
FetchContent_Declare(ftxui
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
+ # Specify a GIT_TAG here.
)
+
FetchContent_GetProperties(ftxui)
if(NOT ftxui_POPULATED)
FetchContent_Populate(ftxui)
add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
-add_executable(main src/main.cpp)
-target_link_libraries(main
+# ------------------------------------------------------------------------------
+
+project(ftxui-starter
+ LANGUAGES CXX
+ VERSION 1.0.0
+)
+
+add_executable(ftxui-starter src/main.cpp)
+target_include_directories(ftxui-starter PRIVATE src)
+
+target_link_libraries(ftxui-starter
PRIVATE ftxui::screen
PRIVATE ftxui::dom
PRIVATE ftxui::component # Not needed for this example.
)
-set_target_properties(main PROPERTIES CXX_STANDARD 17)
-```
+
+# C++17 is used. We requires fold expressions at least.
+set_target_properties(ftxui-starter PROPERTIES CXX_STANDARD 17)
+
+~~~
+
+Build
+~~~
+mkdir build && cd build
+cmake ..
+make
+./main
+~~~
+
+## Using NXXM
+
+**.nxxm/deps**
+~~~json
+{
+ "ArthurSonzogni/FTXUI": {}
+}
+~~~
+
+Build:
+~~~
+nxxm . -t clang-cxx17
+~~~
# List of modules.
@@ -82,7 +125,7 @@ input. It defines a set of ftxui::Component. The use can navigates using the
arrow keys and interact with widgets like checkbox/inputbox/... You can make you
own components.
-## screen
+# screen
It defines a ftxui::Screen. This is a grid of ftxui::Pixel. A Pixel represent a
unicode character and its associated style (bold, colors, etc...).
@@ -106,7 +149,7 @@ The screen can be printed as a string using ftxui::Screen::ToString().
}
~~~
-## dom
+# dom
This module defines a hierachical set of Element. An element manages layout and can be responsive to the terminal dimensions.
@@ -130,23 +173,6 @@ You only need one header: ftxui/dom/elements.hpp
\include ftxui/dom/elements.hpp
-## component
-
-Finally, the ftxui/component directory defines the logic to get interactivity.
-
-Please take a look at ./examples/component
-
-This provides:
-1. A main loop.
-2. Get events and respond to them.
-3. A predefined implementation of "keyboard navigation".
-4. A set of predefined widget: CheckBox, RadioBox, Input, Menu, Toggle.
-
-# ftxui/dom
-
-Every elements of the dom are declared from:
-\ref ftxui/dom/elements.hpp
-
## text
The most simple widget. It displays a text.
@@ -219,6 +245,7 @@ border(gauge(0.5))
~~~
## graph
+
@htmlonly
@endhtmlonly
@@ -362,7 +389,25 @@ An horizontal flow layout is implemented by:
└────┘└───────────────────────────────────┘└───────────────────────────────────┘
~~~
-# ftxui/component
+
+# component
+
+The `ftxui/component` directory defines the logic to get produce
+interactive component responding to user's events (keyboard, mouse, etc...)
+
+A ftxui::ScreenInteractive defines a main loop to render a component.
+
+A ftxui::Component is a shared pointer to a ftxui::ComponentBase. The later
+defines
+ - ftxui::ComponentBase::Render(): How to render the interface.
+ - ftxui::ComponentBase::OnEvent(): How to react to events.
+ - ftxui::ComponentBase::Add(): Give a parent/child relation ship in between
+ two component. This defines a tree a components, which help properly define
+ how keyboard navigation works.
+
+Predefined components are available in `ftxui/dom/component.hpp`:
+
+\include ftxui/component/component.hpp
Element are stateless object. On the other side, components are used when an
internal state is needed. Components are used to interact with the user with
@@ -370,7 +415,7 @@ its keyboard. They handle keyboard navigation, including component focus.
## Input
-The component: \ref ftxui::Input
+Produced by: ftxui::Input() from "ftxui/component/component.hpp"
@htmlonly
@@ -378,7 +423,7 @@ The component: \ref ftxui::Input
## Menu
-The component: \ref ftxui::Menu
+Produced by: ftxui::Menu() from "ftxui/component/component.hpp"
@htmlonly
@@ -386,7 +431,7 @@ The component: \ref ftxui::Menu
## Toggle.
-The component: \ref ftxui::Toggle
+Produced by: ftxui::Toggle() from "ftxui/component/component.hpp"
@htmlonly
@@ -394,7 +439,7 @@ The component: \ref ftxui::Toggle
## CheckBox
-The component: \ref ftxui::CheckBox
+Produced by: ftxui::Checkbox() from "ftxui/component/component.hpp"
@htmlonly
@@ -402,99 +447,32 @@ The component: \ref ftxui::CheckBox
## RadioBox
-The component: \ref ftxui::RadioBox
+Produced by: ftxui::Radiobox() from "ftxui/component/component.hpp"
@htmlonly
@endhtmlonly
-# Build
+## Renderer
-Assuming this example example.cpp file.
+Produced by: ftxui::Renderer() from \ref "ftxui/component/component.hpp". This
+component decorate another one by using a different function to render an
+interface.
-**main.cpp**
-~~~cpp
-#include "ftxui/screen/screen.c
-#include "ftxui/dom/elements.c
-#include
+## Container::Horizontal
-int main(int argc, const char *argv[]) {
- using namespace ftxui;
- auto document =
- hbox({
- text(L"left") | bold | border,
- text(L"middle") | flex | border,
- text(L"right") | border,
- });
- auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
- Render(screen, document);
+Produced by: ftxui::Container::Horizontal() from
+"ftxui/component/component.hpp". It displays a list of components horizontally
+and handle keyboard/mouse navigation.
- std::cout << screen.ToString();
+## Container::Vertial
- return 0;
-}
-~~~
+Produced by: ftxui::Container::Vertical() from
+"ftxui/component/component.hpp". It displays a list of components vertically
+and handles keyboard/mouse navigation.
-## Using CMake
+## Container::Tab
-CMakeLists.txt
-~~~cmake
-cmake_minimum_required (VERSION 3.11)
-
-# --- Fetch FTXUI --------------------------------------------------------------
-include(FetchContent)
-
-set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
-FetchContent_Declare(ftxui
- GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
- # Specify a GIT TAG here.
-)
-
-FetchContent_GetProperties(ftxui)
-if(NOT ftxui_POPULATED)
- FetchContent_Populate(ftxui)
- add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL)
-endif()
-
-# ------------------------------------------------------------------------------
-
-project(ftxui-starter
- LANGUAGES CXX
- VERSION 1.0.0
-)
-
-add_executable(ftxui-starter src/main.cpp)
-target_include_directories(ftxui-starter PRIVATE src)
-
-target_link_libraries(ftxui-starter
- PRIVATE ftxui::screen
- PRIVATE ftxui::dom
- PRIVATE ftxui::component # Not needed for this example.
-)
-
-# C++17 is used. We requires fold expressions at least.
-set_target_properties(ftxui-starter PROPERTIES CXX_STANDARD 17)
-
-~~~
-
-Build
-~~~
-mkdir build && cd build
-cmake ..
-make
-./main
-~~~
-
-## Using NXXM
-
-**.nxxm/deps**
-~~~json
-{
- "ArthurSonzogni/FTXUI": {}
-}
-~~~
-
-Build:
-~~~
-nxxm . -t clang-cxx17
-~~~
+Produced by: ftxui::Container::Tab() from
+"ftxui/component/component.hpp". It take a list of component and display only
+one of them. This is useful for implementing a tab bar.
diff --git a/examples/component/CMakeLists.txt b/examples/component/CMakeLists.txt
index 07dc0b3..3f4e5f1 100644
--- a/examples/component/CMakeLists.txt
+++ b/examples/component/CMakeLists.txt
@@ -17,6 +17,7 @@ example(modal_dialog)
example(radiobox)
example(radiobox_in_frame)
example(slider)
+example(slider_rgb)
example(tab_horizontal)
example(tab_vertical)
example(toggle)
diff --git a/examples/component/button.cpp b/examples/component/button.cpp
index dc3ceaf..5bc7852 100644
--- a/examples/component/button.cpp
+++ b/examples/component/button.cpp
@@ -1,51 +1,37 @@
-#include // for function
-#include // for unique_ptr, make_u...
-#include // for wstring
-#include // for move
-#include // for vector
+#include // for __shared_ptr_access, shared_ptr
+#include // for operator+, to_wstring
-#include "ftxui/component/button.hpp" // for Button
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
+#include "ftxui/component/component_base.hpp" // for ComponentBase
#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;
-class MyComponent : public Component {
- private:
- std::vector> buttons_;
- Container container_ = Container::Horizontal();
-
- public:
- MyComponent() {
- Add(&container_);
-
- auto button_add = std::make_unique();
- auto button_remove = std::make_unique();
- container_.Add(button_add.get());
- container_.Add(button_remove.get());
- button_add->label = L"Add one button";
- button_remove->label = L"Remove last button";
-
- button_add->on_click = [&] {
- auto extra_button = std::make_unique();
- 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[]) {
- auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- screen.Loop(&component);
+ int value = 50;
+
+ // The tree of components. This defines how to navigate using the keyboard.
+ auto buttons = Container::Horizontal({
+ Button("Decrease", [&] { value--; }),
+ Button("Increase", [&] { value++; }),
+ });
+
+ // Modify the way to render them on screen:
+ auto component = Renderer(buttons, [&] {
+ return vbox({
+ text(L"value = " + std::to_wstring(value)),
+ separator(),
+ gauge(value * 0.01f),
+ separator(),
+ buttons->Render(),
+ }) |
+ border;
+ });
+
+ auto screen = ScreenInteractive::FitComponent();
+ screen.Loop(component);
return 0;
}
diff --git a/examples/component/checkbox.cpp b/examples/component/checkbox.cpp
index 47189b6..361ee68 100644
--- a/examples/component/checkbox.cpp
+++ b/examples/component/checkbox.cpp
@@ -1,34 +1,23 @@
#include "ftxui/component/checkbox.hpp"
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Checkbox, Vertical
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
using namespace ftxui;
-class MyComponent : public Component {
- private:
- CheckBox box_1_;
- CheckBox box_2_;
- CheckBox box_3_;
- Container container_ = Container::Vertical();
-
- public:
- MyComponent() {
- 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[]) {
+ bool build_examples_state = false;
+ bool build_tests_state = false;
+ bool use_webassembly_state = true;
+
+ auto component = Container::Vertical({
+ Checkbox("Build examples", &build_examples_state),
+ Checkbox("Build tests", &build_tests_state),
+ Checkbox("Use WebAssembly", &use_webassembly_state),
+ });
+
auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- screen.Loop(&component);
+ screen.Loop(component);
return 0;
}
diff --git a/examples/component/checkbox_in_frame.cpp b/examples/component/checkbox_in_frame.cpp
index c1f0f96..26f405b 100644
--- a/examples/component/checkbox_in_frame.cpp
+++ b/examples/component/checkbox_in_frame.cpp
@@ -1,50 +1,36 @@
-#include // for allocator_traits<>...
-#include // for operator+, wstring
-#include // for move
-#include // for vector
+#include // for __shared_ptr_access, allocator_traits<>::value_type, shared_ptr
+#include // for operator+
+#include // for vector
-#include "ftxui/component/checkbox.hpp" // for CheckBox
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Vertical
+#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/dom/elements.hpp" // for Element, operator|
-#include "ftxui/screen/box.hpp" // for ftxui
-#include "ftxui/screen/string.hpp" // for to_wstring
+#include "ftxui/dom/elements.hpp" // for Element, operator|, size, border, frame, HEIGHT, LESS_THAN
+#include "ftxui/screen/string.hpp" // for to_wstring
using namespace ftxui;
-class MyComponent : public Component {
- public:
- MyComponent() {
- Add(&container);
- checkbox.resize(30);
- for (int i = 0; i < checkbox.size(); ++i) {
- checkbox[i].label = (L"CheckBox " + to_wstring(i));
- container.Add(&checkbox[i]);
- }
- }
-
- // clang-format off
- Element Render() override {
- Elements content;
- for (auto& it : checkbox) {
- content.push_back(it.Render());
- }
- return vbox(std::move(content))
- | frame
- | size(HEIGHT, LESS_THAN, 10)
- | border;
- }
-
- private:
- std::vector checkbox;
- Container container = Container::Vertical();
+struct CheckboxState {
+ bool checked;
};
int main(int argc, const char* argv[]) {
+ int size = 30;
+ std::vector states(size);
+ auto container = Container::Vertical({});
+ for (int i = 0; i < size; ++i) {
+ states[i].checked = false;
+ container->Add(Checkbox(L"Checkbox" + to_wstring(i), &states[i].checked));
+ }
+
+ auto component = Renderer(container, [&] {
+ return container->Render() | frame | ftxui::size(HEIGHT, LESS_THAN, 10) |
+ border;
+ });
+
auto screen = ScreenInteractive::FitComponent();
- MyComponent component;
- screen.Loop(&component);
+ screen.Loop(component);
return 0;
}
diff --git a/examples/component/gallery.cpp b/examples/component/gallery.cpp
index d819c54..99f5af4 100644
--- a/examples/component/gallery.cpp
+++ b/examples/component/gallery.cpp
@@ -1,130 +1,126 @@
#include // for function
-#include // for allocator, unique_ptr
-#include // for wstring
+#include // for shared_ptr, allocator, __shared_ptr_access
+#include // for wstring, basic_string
#include // for vector
-#include "ftxui/component/button.hpp" // for Button
-#include "ftxui/component/checkbox.hpp" // for CheckBox
-#include "ftxui/component/component.hpp" // for Component, Compone...
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/input.hpp" // for Input
-#include "ftxui/component/menu.hpp" // for Menu
-#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
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Slider, Checkbox, Vertical, Renderer, Button, Input, Menu, Radiobox, Toggle
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
+#include "ftxui/dom/elements.hpp" // for separator, Element, operator|, size, xflex, text, WIDTH, hbox, vbox, EQUAL, border, GREATER_THAN
using namespace ftxui;
-class MyComponent : public Component {
- Container container = Container::Vertical();
- Menu menu;
- Toggle toggle;
- Container checkbox_container = Container::Vertical();
- CheckBox checkbox1;
- CheckBox checkbox2;
- RadioBox radiobox;
- Input input;
- Button button;
-
- int slider_value_1_ = 12;
- int slider_value_2_ = 56;
- int slider_value_3_ = 128;
- ComponentPtr slider_1_ = Slider(L"R:", &slider_value_1_, 0, 256, 1);
- ComponentPtr slider_2_ = Slider(L"G:", &slider_value_2_, 0, 256, 1);
- ComponentPtr slider_3_ = Slider(L"B:", &slider_value_3_, 0, 256, 1);
-
- public:
- MyComponent() {
- Add(&container);
- menu.entries = {
- L"Menu 1",
- L"Menu 2",
- L"Menu 3",
- L"Menu 4",
- };
- container.Add(&menu);
-
- 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) {
+// Display a component nicely with a title on the left.
+Component Wrap(std::wstring name, Component component) {
+ return Renderer(component, [name, component] {
return hbox({
text(name) | size(WIDTH, EQUAL, 8),
separator(),
- element | xflex,
+ component->Render() | xflex,
}) |
xflex;
- }
-
- Element Render(std::wstring name, Component& component) {
- return Render(name, component.Render());
- }
-
- Element Render() override {
- return //
- vbox({
- Render(L"menu", menu),
- separator(),
- Render(L"toggle", toggle),
- separator(),
- Render(L"checkbox", checkbox_container),
- separator(),
- Render(L"radiobox", radiobox),
- separator(),
- Render(L"input", input) | size(WIDTH, LESS_THAN, 50),
- separator(),
- Render(L"slider", //
- vbox({
- slider_1_->Render(),
- slider_2_->Render(),
- slider_3_->Render(),
- })),
- separator(),
- Render(L"button", button),
- }) |
- xflex | size(WIDTH, GREATER_THAN, 40) | border;
- }
-
- std::function on_quit = [] {};
-};
+ });
+}
int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::FitComponent();
- MyComponent component;
- component.on_quit = screen.ExitLoopClosure();
- screen.Loop(&component);
+
+ // -- Menu
+ // ----------------------------------------------------------------------
+ const std::vector menu_entries = {
+ L"Menu 1",
+ L"Menu 2",
+ L"Menu 3",
+ L"Menu 4",
+ };
+ int menu_selected = 0;
+ auto menu = Menu(&menu_entries, &menu_selected);
+ menu = Wrap(L"Menu", menu);
+
+ // -- Toggle------------------------------------------------------------------
+ int toggle_selected = 0;
+ std::vector toggle_entries = {
+ L"Toggle_1",
+ L"Toggle_2",
+ };
+ auto toggle = Toggle(&toggle_entries, &toggle_selected);
+ toggle = Wrap(L"Toggle", toggle);
+
+ // -- Checkbox ---------------------------------------------------------------
+ bool checkbox_1_selected = false;
+ bool checkbox_2_selected = false;
+
+ auto checkboxes = Container::Vertical({
+ Checkbox("checkbox1", &checkbox_1_selected),
+ Checkbox("checkbox2", &checkbox_2_selected),
+ });
+ checkboxes = Wrap(L"Checkbox", checkboxes);
+
+ // -- Radiobox ---------------------------------------------------------------
+ int radiobox_selected = 0;
+ std::vector radiobox_entries = {
+ L"Radiobox 1",
+ L"Radiobox 2",
+ L"Radiobox 3",
+ L"Radiobox 4",
+ };
+ auto radiobox = Radiobox(&radiobox_entries, &radiobox_selected);
+ radiobox = Wrap(L"Radiobox", radiobox);
+
+ // -- Input ------------------------------------------------------------------
+ std::wstring input_label;
+ auto input = Input(&input_label, L"placeholder");
+ input = Wrap(L"Input", input);
+
+ // -- Button -----------------------------------------------------------------
+ std::wstring button_label = L"Quit";
+ std::function on_button_clicked_;
+ auto button = Button(&button_label, screen.ExitLoopClosure());
+ button = Wrap(L"Button", button);
+
+ // -- Slider -----------------------------------------------------------------
+ int slider_value_1 = 12;
+ int slider_value_2 = 56;
+ int slider_value_3 = 128;
+ auto sliders = Container::Vertical({
+ Slider(L"R:", &slider_value_1, 0, 256, 1),
+ Slider(L"G:", &slider_value_2, 0, 256, 1),
+ Slider(L"B:", &slider_value_3, 0, 256, 1),
+ });
+ sliders = Wrap(L"Slider", sliders);
+
+ // -- Layout -----------------------------------------------------------------
+ auto layout = Container::Vertical({
+ menu,
+ toggle,
+ checkboxes,
+ radiobox,
+ input,
+ sliders,
+ button,
+ });
+
+ auto component = Renderer(layout, [&] {
+ return vbox({
+ menu->Render(),
+ separator(),
+ toggle->Render(),
+ separator(),
+ checkboxes->Render(),
+ separator(),
+ radiobox->Render(),
+ separator(),
+ input->Render(),
+ separator(),
+ sliders->Render(),
+ separator(),
+ button->Render(),
+ }) |
+ xflex | size(WIDTH, GREATER_THAN, 40) | border;
+ });
+
+ screen.Loop(component);
return 0;
}
diff --git a/examples/component/homescreen.cpp b/examples/component/homescreen.cpp
index b6c49c7..6758e24 100644
--- a/examples/component/homescreen.cpp
+++ b/examples/component/homescreen.cpp
@@ -1,52 +1,50 @@
-#include // for operator""s, chron...
+#include // for array
+#include // for operator""s, chrono_literals
#include // for sin
-#include // for ref, reference_wra...
-#include // for allocator, wstring
+#include // for ref, reference_wrapper, function
+#include // for allocator, shared_ptr, __shared_ptr_access
+#include // for wstring, basic_string, operator+, to_wstring
#include // for sleep_for, thread
#include // for move
#include // for vector
-#include "ftxui/component/checkbox.hpp" // for CheckBox
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/event.hpp" // for Event, Event::Custom
-#include "ftxui/component/input.hpp" // for Input
-#include "ftxui/component/menu.hpp" // for Menu
-#include "ftxui/component/radiobox.hpp" // for RadioBox
-#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/component/toggle.hpp" // for Toggle
-#include "ftxui/dom/elements.hpp" // for text, operator|
-#include "ftxui/screen/box.hpp" // for ftxui
-#include "ftxui/screen/color.hpp" // for Color, Color::Blue...
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Horizontal, Vertical, Input, Menu, Radiobox, Tab, Toggle
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/event.hpp" // for Event, Event::Custom
+#include "ftxui/component/input.hpp" // for InputBase
+#include "ftxui/component/screen_interactive.hpp" // for Component, 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, HEIGHT, Elements, hflow, flex_grow, frame, gauge, LESS_THAN, spinner, dim, GREATER_THAN
+#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
using namespace ftxui;
-int shift = 0;
-class Graph {
- public:
- std::vector operator()(int width, int height) {
- std::vector output(width);
- for (int i = 0; i < width; ++i) {
- float v = 0;
- v += 0.1f * sin((i + shift) * 0.1f);
- v += 0.2f * sin((i + shift + 10) * 0.15f);
- v += 0.1f * sin((i + shift) * 0.03f);
- v *= height;
- v += 0.5f * height;
- output[i] = (int)v;
+int main(int argc, const char* argv[]) {
+ auto screen = ScreenInteractive::Fullscreen();
+
+ int shift = 0;
+
+ class Graph {
+ public:
+ Graph(int* shift) : shift_(shift) {}
+ std::vector operator()(int width, int height) {
+ std::vector output(width);
+ for (int i = 0; i < width; ++i) {
+ float v = 0;
+ v += 0.1f * sin((i + *shift_) * 0.1f);
+ v += 0.2f * sin((i + *shift_ + 10) * 0.15f);
+ v += 0.1f * sin((i + *shift_) * 0.03f);
+ v *= height;
+ v += 0.5f * height;
+ output[i] = (int)v;
+ }
+ return output;
}
- return output;
- }
-};
+ int* shift_;
+ };
-class HTopComponent : public Component {
- Graph my_graph;
-
- public:
- HTopComponent() {}
- ~HTopComponent() override {}
-
- Element Render() override {
+ Graph my_graph(&shift);
+ auto htop = Renderer([&] {
auto frequency = vbox({
text(L"Frequency [Mhz]") | hcenter,
hbox({
@@ -99,113 +97,140 @@ class HTopComponent : public Component {
ram | flex,
}) |
flex | border;
- }
-};
+ });
-class CompilerComponent : public Component {
- Container container = Container::Horizontal();
- RadioBox compiler;
- Container flag = Container::Vertical();
- CheckBox flag_checkbox[4];
- Container subcontainer = Container::Vertical();
- Container input_container = Container::Horizontal();
- Input input_add;
- Menu input;
- Input executable;
+ const std::vector compiler_entries = {
+ L"gcc",
+ 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",
+ };
- public:
- ~CompilerComponent() override {}
- CompilerComponent() {
- Add(&container);
+ int compiler_selected = 0;
+ Component compiler = Radiobox(&compiler_entries, &compiler_selected);
- // Compiler ----------------------------------------------------------------
- compiler.entries = {
- L"gcc",
- 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);
+ std::array options_label = {
+ L"-Wall",
+ L"-Werror",
+ L"-lpthread",
+ L"-O3",
+ };
+ std::array options_state = {
+ false,
+ false,
+ false,
+ false,
+ };
+ std::wstring input_add_content;
+ Component input_add = Input(&input_add_content, "input files");
- // 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);
+ std::vector input_entries;
+ int input_selected = 0;
+ Component input = Menu(&input_entries, &input_selected);
- container.Add(&subcontainer);
+ std::wstring executable_content_ = L"";
+ Component executable_ = Input(&executable_content_, "executable");
+
+ 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]),
+ });
+
+ auto compiler_component = Container::Horizontal({
+ compiler,
+ flags,
+ Container::Vertical({
+ executable_,
+ Container::Horizontal({
+ input_add,
+ input,
+ }),
+ }),
+ });
+
+ InputBase::From(input_add)->on_enter = [&] {
+ input_entries.push_back(input_add_content);
+ input_add_content = L"";
+ };
+
+ auto render_command = [&] {
+ Elements line;
+ // Compiler
+ line.push_back(text(compiler_entries[compiler_selected]) | bold);
+ // flags
+ for (int i = 0; i < 4; ++i) {
+ if (options_state[i]) {
+ line.push_back(text(L" "));
+ line.push_back(text(options_label[i]) | dim);
+ }
+ }
// Executable
- // ----------------------------------------------------------------
- executable.placeholder = L"executable";
- subcontainer.Add(&executable);
+ if (!executable_content_.empty()) {
+ line.push_back(text(L" -O ") | bold);
+ line.push_back(text(executable_content_) | color(Color::BlueLight) |
+ bold);
+ }
+ // Input
+ for (auto& it : input_entries) {
+ line.push_back(text(L" " + it) | color(Color::RedLight));
+ }
+ return line;
+ };
- // 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 {
- auto compiler_win = window(text(L"Compiler"), compiler.Render() | frame);
- auto flags_win = window(text(L"Flags"), flag.Render());
- auto executable_win = window(text(L"Executable:"), executable.Render());
+ auto compiler_renderer = Renderer(compiler_component, [&] {
+ auto compiler_win = window(text(L"Compiler"), compiler->Render() | frame);
+ auto flags_win = window(text(L"Flags"), flags->Render());
+ auto executable_win = window(text(L"Executable:"), executable_->Render());
auto input_win =
window(text(L"Input"),
hbox({
vbox({
hbox({
text(L"Add: "),
- input_add.Render(),
+ input_add->Render(),
}) | size(WIDTH, EQUAL, 20) |
size(HEIGHT, EQUAL, 1),
filler(),
}),
separator(),
- input.Render() | frame | size(HEIGHT, EQUAL, 3) | flex,
+ input->Render() | frame | size(HEIGHT, EQUAL, 3) | flex,
}));
return vbox({
hbox({
@@ -217,49 +242,21 @@ class CompilerComponent : public Component {
}),
filler(),
}),
- hflow(RenderCommandLine()) | flex_grow,
+ hflow(render_command()) | flex_grow,
}) |
flex_grow | border;
- }
+ });
- Elements RenderCommandLine() {
- Elements line;
- // Compiler
- line.push_back(text(compiler.entries[compiler.selected]) | bold);
- // flags
- for (auto& it : flag_checkbox) {
- if (it.state) {
- line.push_back(text(L" "));
- line.push_back(text(it.label) | dim);
- }
- }
- // Executable
- if (!executable.content.empty()) {
- line.push_back(text(L" -O ") | bold);
- line.push_back(text(executable.content) | color(Color::BlueLight) | bold);
- }
- // Input
- for (auto& it : input.entries) {
- line.push_back(text(L" " + it) | color(Color::RedLight));
- }
- return line;
- }
-};
-
-class SpinnerComponent : public Component {
- Element Render() override {
+ auto spinner_tab_renderer = Renderer([&] {
Elements entries;
for (int i = 0; i < 22; ++i) {
- if (i != 0)
- entries.push_back(spinner(i, shift / 2) | bold |
- size(WIDTH, GREATER_THAN, 2) | border);
+ entries.push_back(spinner(i, shift / 2) | bold |
+ size(WIDTH, GREATER_THAN, 2) | border);
}
return hflow(std::move(entries)) | border;
- }
-};
+ });
-class ColorComponent : public Component {
- Element Render() override {
+ auto color_tab_renderer = Renderer([] {
return hbox({
vbox({
color(Color::Default, text(L"Default")),
@@ -301,82 +298,67 @@ class ColorComponent : public Component {
}),
}) |
hcenter | border;
- }
-};
+ });
-class GaugeComponent : public Component {
- Element RenderGauge(int delta) {
+ auto render_gauge = [&shift](int delta) {
float progress = (shift + delta) % 1000 / 1000.f;
return hbox({
text(std::to_wstring(int(progress * 100)) + L"% ") |
size(WIDTH, EQUAL, 5),
gauge(progress),
});
- }
- Element Render() override {
+ };
+
+ auto gauge_component = Renderer([render_gauge] {
return vbox({
- RenderGauge(0) | color(Color::Black),
- RenderGauge(100) | color(Color::GrayDark),
- RenderGauge(50) | color(Color::GrayLight),
- RenderGauge(6894) | color(Color::White),
+ render_gauge(0) | color(Color::Black),
+ render_gauge(100) | color(Color::GrayDark),
+ render_gauge(50) | color(Color::GrayLight),
+ render_gauge(6894) | color(Color::White),
separator(),
- RenderGauge(6841) | color(Color::Blue),
- RenderGauge(9813) | color(Color::BlueLight),
- RenderGauge(98765) | color(Color::Cyan),
- RenderGauge(98) | color(Color::CyanLight),
- RenderGauge(9846) | color(Color::Green),
- RenderGauge(1122) | color(Color::GreenLight),
- RenderGauge(84) | color(Color::Magenta),
- RenderGauge(645) | color(Color::MagentaLight),
- RenderGauge(568) | color(Color::Red),
- RenderGauge(2222) | color(Color::RedLight),
- RenderGauge(220) | color(Color::Yellow),
- RenderGauge(348) | color(Color::YellowLight),
+ render_gauge(6841) | color(Color::Blue),
+ render_gauge(9813) | color(Color::BlueLight),
+ render_gauge(98765) | color(Color::Cyan),
+ render_gauge(98) | color(Color::CyanLight),
+ render_gauge(9846) | color(Color::Green),
+ render_gauge(1122) | color(Color::GreenLight),
+ render_gauge(84) | color(Color::Magenta),
+ render_gauge(645) | color(Color::MagentaLight),
+ render_gauge(568) | color(Color::Red),
+ render_gauge(2222) | color(Color::RedLight),
+ render_gauge(220) | color(Color::Yellow),
+ render_gauge(348) | color(Color::YellowLight),
}) |
border;
+ });
+
+ int tab_index = 0;
+ std::vector tab_entries = {
+ L"htop", L"color", L"spinner", L"gauge", L"compiler",
};
-};
+ auto tab_selection = Toggle(&tab_entries, &tab_index);
+ auto tab_content = Container::Tab(&tab_index, {
+ htop,
+ color_tab_renderer,
+ spinner_tab_renderer,
+ gauge_component,
+ compiler_renderer,
+ });
-class Tab : public Component {
- public:
- Container main_container = Container::Vertical();
+ auto main_container = Container::Vertical({
+ tab_selection,
+ tab_content,
+ });
- Toggle tab_selection;
- Container container = Container::Tab(&tab_selection.selected);
-
- HTopComponent htop_component;
- 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 {
+ auto main_renderer = Renderer(main_container, [&] {
return vbox({
text(L"FTXUI Demo") | bold | hcenter,
- tab_selection.Render() | hcenter,
- container.Render() | flex,
+ tab_selection->Render() | hcenter,
+ tab_content->Render() | flex,
});
- }
-};
+ });
-int main(int argc, const char* argv[]) {
- auto screen = ScreenInteractive::Fullscreen();
-
- std::thread update([&screen]() {
+ std::thread update([&screen, &shift]() {
for (;;) {
using namespace std::chrono_literals;
std::this_thread::sleep_for(0.05s);
@@ -385,8 +367,7 @@ int main(int argc, const char* argv[]) {
}
});
- Tab tab;
- screen.Loop(&tab);
+ screen.Loop(main_renderer);
return 0;
}
diff --git a/examples/component/input.cpp b/examples/component/input.cpp
index 3fc69e1..c5a31c2 100644
--- a/examples/component/input.cpp
+++ b/examples/component/input.cpp
@@ -1,44 +1,38 @@
-#include "ftxui/component/input.hpp"
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
+#include // for allocator, __shared_ptr_access
+#include // for operator+, char_traits, wstring
-using namespace ftxui;
-
-class MyComponent : public Component {
- 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 on_enter = []() {};
-
- private:
- Container container = Container::Vertical();
- Input input_1;
- Input input_2;
- Input input_3;
-
- Element Render() override {
- return border(vbox({
- hbox({text(L" input_1 : "), input_1.Render()}),
- hbox({text(L" input_2 : "), input_2.Render()}),
- hbox({text(L" input_3 : "), input_3.Render()}),
- }));
- }
-};
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Input, Renderer, Vertical
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
+#include "ftxui/dom/elements.hpp" // for text, hbox, Element, separator, operator|, vbox, border
int main(int argc, const char* argv[]) {
+ using namespace ftxui;
+
+ std::wstring first_name_;
+ std::wstring last_name_;
+
+ Component input_first_name_ = Input(&first_name_, "first name");
+ Component input_last_name_ = Input(&last_name_, "last name");
+
+ auto component = Container::Vertical({
+ input_first_name_,
+ input_last_name_,
+ });
+
+ auto renderer = Renderer(component, [&] {
+ return vbox({
+ text(L"Hello " + first_name_ + L" " + last_name_),
+ separator(),
+ hbox({text(L" First name : "), input_first_name_->Render()}),
+ hbox({text(L" Last name : "), input_last_name_->Render()}),
+ }) |
+ border;
+ });
+
auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- component.on_enter = screen.ExitLoopClosure();
- screen.Loop(&component);
+ screen.Loop(renderer);
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
diff --git a/examples/component/menu.cpp b/examples/component/menu.cpp
index 41860fe..f68e265 100644
--- a/examples/component/menu.cpp
+++ b/examples/component/menu.cpp
@@ -1,24 +1,30 @@
#include // for function
-#include // for basic_ostream::ope...
-#include // for wstring, allocator
-#include // for vector
+#include // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream
+#include // for wstring, allocator, basic_string
+#include // 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/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
auto screen = ScreenInteractive::TerminalOutput();
- Menu menu;
- menu.entries = {L"entry 1", L"entry 2", L"entry 3"};
- menu.selected = 0;
- menu.on_enter = screen.ExitLoopClosure();
+ std::vector entries = {
+ L"entry 1",
+ L"entry 2",
+ 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.
diff --git a/examples/component/menu2.cpp b/examples/component/menu2.cpp
index 91aacf8..82f7121 100644
--- a/examples/component/menu2.cpp
+++ b/examples/component/menu2.cpp
@@ -1,84 +1,77 @@
#include // for function
-#include // for wstring, allocator
+#include // for allocator, __shared_ptr_access
+#include // for wstring, operator+, to_string, basic_string
#include // for vector
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/menu.hpp" // for Menu
-#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/dom/elements.hpp" // for text, separator, bold
-#include "ftxui/screen/box.hpp" // for ftxui
-#include "ftxui/screen/string.hpp" // for to_wstring
-
-using namespace ftxui;
-
-class MyComponent : public Component {
- 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 on_enter = []() {};
-
- private:
- Container container = Container::Horizontal();
- Menu left_menu;
- Menu right_menu;
-
- Element Render() override {
- int sum = left_menu.selected * 10 + right_menu.selected;
- return border(vbox({
- // -------- Top panel --------------
- hbox({
- // -------- Left Menu --------------
- vbox({
- hcenter(bold(text(L"Percentage by 10%"))),
- separator(),
- left_menu.Render(),
- }) | flex,
- // -------- Right Menu --------------
- vbox({
- hcenter(bold(text(L"Percentage by 1%"))),
- separator(),
- right_menu.Render(),
- }) | flex,
- filler(),
- }),
- separator(),
- // -------- Bottom panel --------------
- vbox({
- hbox({
- text(L" gauge : "),
- gauge(sum / 100.0),
- }),
- hbox({
- text(L" text : "),
- text(to_wstring(std::to_string(sum) + " %")),
- }),
- }) | flex,
- }));
- }
-};
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Menu, Horizontal, Renderer
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/menu.hpp" // for MenuBase
+#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
+#include "ftxui/dom/elements.hpp" // for text, separator, bold, hcenter, vbox, hbox, gauge, Element, operator|, border
+#include "ftxui/screen/string.hpp" // for to_wstring
int main(int argc, const char* argv[]) {
+ using namespace ftxui;
+
+ std::vector left_menu_entries = {
+ L"0%", L"10%", L"20%", L"30%", L"40%",
+ L"50%", L"60%", L"70%", L"80%", L"90%",
+ };
+ std::vector 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_,
+ });
+
+ auto renderer = Renderer(container, [&] {
+ int sum = left_menu_selected * 10 + right_menu_selected;
+ return vbox({
+ // -------- Top panel --------------
+ hbox({
+ // -------- Left Menu --------------
+ vbox({
+ hcenter(bold(text(L"Percentage by 10%"))),
+ separator(),
+ left_menu_->Render(),
+ }),
+ separator(),
+ // -------- Right Menu --------------
+ vbox({
+ hcenter(bold(text(L"Percentage by 1%"))),
+ separator(),
+ right_menu_->Render(),
+ }),
+ separator(),
+ }),
+ separator(),
+ // -------- Bottom panel --------------
+ vbox({
+ hbox({
+ text(L" gauge : "),
+ gauge(sum / 100.0),
+ }),
+ hbox({
+ text(L" text : "),
+ text(to_wstring(std::to_string(sum) + " %")),
+ }),
+ }),
+ }) |
+ border;
+ });
+
auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- component.on_enter = screen.ExitLoopClosure();
- screen.Loop(&component);
+ MenuBase::From(left_menu_)->on_enter = screen.ExitLoopClosure();
+ MenuBase::From(right_menu_)->on_enter = screen.ExitLoopClosure();
+ screen.Loop(renderer);
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
diff --git a/examples/component/menu_style.cpp b/examples/component/menu_style.cpp
index 3fc8879..4be8f08 100644
--- a/examples/component/menu_style.cpp
+++ b/examples/component/menu_style.cpp
@@ -1,92 +1,83 @@
#include // for function
#include // for initializer_list
-#include // for wstring, allocator
+#include // for __shared_ptr_access, shared_ptr, allocator
+#include // for wstring, basic_string
#include // for vector
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/menu.hpp" // for Menu
-#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/dom/elements.hpp" // for operator|, Element
-#include "ftxui/screen/box.hpp" // for ftxui
-#include "ftxui/screen/color.hpp" // for Color, Color::Blue
-
-using namespace ftxui;
-
-class MyComponent : public Component {
- public:
- MyComponent() {
- Add(&container);
-
- for (Menu* menu : {
- &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);
- menu_2.selected_style = color(Color::Blue);
- menu_2.selected_focused_style = bold | color(Color::Blue);
-
- menu_3.selected_style = color(Color::Blue);
- menu_3.focused_style = bgcolor(Color::Blue);
- menu_3.selected_focused_style = bgcolor(Color::Blue);
-
- menu_4.selected_style = bgcolor(Color::Blue);
- menu_4.focused_style = bgcolor(Color::BlueLight);
- menu_4.selected_focused_style = bgcolor(Color::BlueLight);
-
- menu_5.normal_style = bgcolor(Color::Blue);
- menu_5.selected_style = bgcolor(Color::Yellow);
- menu_5.focused_style = bgcolor(Color::Red);
- menu_5.selected_focused_style = bgcolor(Color::Red);
-
- menu_6.normal_style = dim | color(Color::Blue);
- menu_6.selected_style = color(Color::Blue);
- menu_6.focused_style = bold | color(Color::Blue);
- menu_6.selected_focused_style = bold | color(Color::Blue);
- }
-
- std::function on_enter = []() {};
-
- private:
- Container container = Container::Horizontal();
- Menu menu_1;
- Menu menu_2;
- Menu menu_3;
- Menu menu_4;
- Menu menu_5;
- Menu menu_6;
-
- // clang-format off
- Element Render() override {
- return
- hbox({
- menu_1.Render() | flex, separator(),
- menu_2.Render() | flex, separator(),
- menu_3.Render() | flex, separator(),
- menu_4.Render() | flex, separator(),
- menu_5.Render() | flex, separator(),
- menu_6.Render() | flex,
- }) | border;
- }
- // clang-format on
-};
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Menu, Horizontal, Renderer
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/menu.hpp" // for MenuBase
+#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive, Component
+#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
int main(int argc, const char* argv[]) {
+ using namespace ftxui;
+ std::vector entries = {
+ L"Monkey", L"Dog", L"Cat", L"Bird", L"Elephant",
+ };
+ int menu_1_selected_ = 0;
+ int menu_2_selected_ = 0;
+ int menu_3_selected_ = 0;
+ int menu_4_selected_ = 0;
+ int menu_5_selected_ = 0;
+ int menu_6_selected_ = 0;
+ auto menu_1_ = Menu(&entries, &menu_1_selected_);
+ auto menu_2_ = Menu(&entries, &menu_2_selected_);
+ auto menu_3_ = Menu(&entries, &menu_3_selected_);
+ auto menu_4_ = Menu(&entries, &menu_4_selected_);
+ auto menu_5_ = Menu(&entries, &menu_5_selected_);
+ auto menu_6_ = Menu(&entries, &menu_6_selected_);
+ auto container = Container::Horizontal({
+ menu_1_,
+ menu_2_,
+ menu_3_,
+ menu_4_,
+ menu_5_,
+ menu_6_,
+ });
+
+ // clang-format off
+ auto renderer = Renderer(container, [&] {
+ return
+ hbox({
+ menu_1_->Render() | flex, separator(),
+ menu_2_->Render() | flex, separator(),
+ menu_3_->Render() | flex, separator(),
+ menu_4_->Render() | flex, separator(),
+ menu_5_->Render() | flex, separator(),
+ menu_6_->Render() | flex,
+ }) | border;
+ });
+ // clang-format on
auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- component.on_enter = screen.ExitLoopClosure();
- screen.Loop(&component);
+ for (Component menu : {menu_1_, menu_2_, menu_3_, menu_4_, menu_5_, menu_6_})
+ MenuBase::From(menu)->on_enter = screen.ExitLoopClosure();
+
+ MenuBase::From(menu_2_)->focused_style = bold | color(Color::Blue);
+ MenuBase::From(menu_2_)->selected_style = color(Color::Blue);
+ MenuBase::From(menu_2_)->selected_focused_style = bold | color(Color::Blue);
+
+ MenuBase::From(menu_3_)->selected_style = color(Color::Blue);
+ MenuBase::From(menu_3_)->focused_style = bgcolor(Color::Blue);
+ MenuBase::From(menu_3_)->selected_focused_style = bgcolor(Color::Blue);
+
+ MenuBase::From(menu_4_)->selected_style = bgcolor(Color::Blue);
+ MenuBase::From(menu_4_)->focused_style = bgcolor(Color::BlueLight);
+ MenuBase::From(menu_4_)->selected_focused_style = bgcolor(Color::BlueLight);
+
+ MenuBase::From(menu_5_)->normal_style = bgcolor(Color::Blue);
+ MenuBase::From(menu_5_)->selected_style = bgcolor(Color::Yellow);
+ MenuBase::From(menu_5_)->focused_style = bgcolor(Color::Red);
+ 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);
+
+ screen.Loop(renderer);
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
diff --git a/examples/component/modal_dialog.cpp b/examples/component/modal_dialog.cpp
index d325e49..7db3758 100644
--- a/examples/component/modal_dialog.cpp
+++ b/examples/component/modal_dialog.cpp
@@ -1,132 +1,89 @@
-#include // for function
-#include // for allocator_traits<>...
-#include // for operator+, wstring
-#include // for vector
+#include // for allocator, __shared_ptr_access, shared_ptr
+#include // for wstring, operator+, basic_string, char_traits
+#include // for vector
-#include "ftxui/component/button.hpp" // for Button
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Button, Renderer, Horizontal, Tab
+#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/dom/elements.hpp" // for Element, operator|
-#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;
+int main(int argc, const char* argv[]) {
+ using namespace ftxui;
+ auto screen = ScreenInteractive::TerminalOutput();
-// The main screen, at depth 0. It display the main content.
-class Content : public Component {
- public:
- std::function on_rate_ftxui = [] {};
- std::function on_quit = [] {};
- std::wstring rating_ = L"3/5 stars";
- 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(); };
- }
+ // There are two layers. One at depth = 0 and the modal window at depth = 1;
+ int depth = 0;
- Element Render() final {
- auto button_elements = hbox({
- button_rate_ftxui.Render(),
- filler(),
- button_quit_.Render(),
- });
+ // The current rating of FTXUI.
+ std::wstring rating = L"3/5 stars";
- auto document = //
- vbox({
- text(L"Modal dialog example"),
- separator(),
- text(L"☆☆☆ FTXUI:" + rating_ + L" ☆☆☆") | bold,
- filler(),
- button_elements,
- }) |
- border;
+ // At depth=0, two buttons. One for rating FTXUI and one for quitting.
+ auto button_rate_ftxui = Button("Rate FTXUI", [&] { depth = 1; });
+ auto button_quit = Button("Quit", screen.ExitLoopClosure());
- return document | size(HEIGHT, GREATER_THAN, 18) | center;
- }
+ auto depth_0_container = Container::Horizontal({
+ button_rate_ftxui,
+ button_quit,
+ });
+ auto depth_0_renderer = Renderer(depth_0_container, [&] {
+ return vbox({
+ text(L"Modal dialog example"),
+ separator(),
+ text(L"☆☆☆ FTXUI:" + rating + L" ☆☆☆") | bold,
+ filler(),
+ hbox({
+ button_rate_ftxui->Render(),
+ filler(),
+ button_quit->Render(),
+ }),
+ }) |
+ border | size(HEIGHT, GREATER_THAN, 18) | center;
+ });
- private:
- Container container_ = Container::Horizontal();
- Button button_rate_ftxui = Button(L"Rate FTXUI");
- Button button_quit_ = Button(L"Quit");
-};
+ // At depth=1, The "modal" window.
+ std::vector rating_labels = {
+ L"1/5 stars", L"2/5 stars", L"3/5 stars", L"4/5 stars", L"5/5 stars",
+ };
+ auto on_rating = [&](std::wstring new_rating) {
+ rating = new_rating;
+ depth = 0;
+ };
+ auto depth_1_container = Container::Horizontal({
+ Button(&rating_labels[0], [&] { on_rating(rating_labels[0]); }),
+ Button(&rating_labels[1], [&] { on_rating(rating_labels[1]); }),
+ Button(&rating_labels[2], [&] { on_rating(rating_labels[2]); }),
+ Button(&rating_labels[3], [&] { on_rating(rating_labels[3]); }),
+ Button(&rating_labels[4], [&] { on_rating(rating_labels[4]); }),
+ });
-// The "modal" screen, at depth 1. It display the modal dialog.
-class Modal : public Component {
- public:
- std::function on_click;
-
- Modal() {
- 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 {
+ auto depth_1_renderer = Renderer(depth_1_container, [&] {
return vbox({
text(L"Do you like FTXUI?"),
separator(),
- hbox({
- buttons_[0].Render(),
- buttons_[1].Render(),
- buttons_[2].Render(),
- buttons_[3].Render(),
- buttons_[4].Render(),
- }),
+ hbox(depth_1_container->Render()),
}) |
border;
- }
+ });
- private:
- Container container_ = Container::Horizontal();
- std::vector buttons_;
-};
+ auto main_container = Container::Tab(&depth, {
+ depth_0_renderer,
+ depth_1_renderer,
+ });
-class MyComponent : public Component {
- public:
- std::function on_quit = [] {};
+ auto main_renderer = Renderer(main_container, [&] {
+ Element document = depth_0_renderer->Render();
- MyComponent() {
- Add(&container_);
- container_.Add(&content_);
- container_.Add(&modal_);
-
- 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 document = content_.Render();
- if (modal_.Focused()) {
+ if (depth == 1) {
document = dbox({
document,
- modal_.Render() | clear_under | center,
+ depth_1_renderer->Render() | clear_under | center,
});
}
return document;
- }
+ });
- private:
- Container container_ = Container::Tab(nullptr);
- Content content_;
- Modal modal_;
-};
-
-int main(int argc, const char* argv[]) {
- auto screen = ScreenInteractive::TerminalOutput();
- MyComponent my_component;
- my_component.on_quit = screen.ExitLoopClosure();
- screen.Loop(&my_component);
+ screen.Loop(main_renderer);
return 0;
}
diff --git a/examples/component/radiobox.cpp b/examples/component/radiobox.cpp
index 0a3a650..07cbb67 100644
--- a/examples/component/radiobox.cpp
+++ b/examples/component/radiobox.cpp
@@ -1,18 +1,23 @@
-#include "ftxui/component/radiobox.hpp"
+#include // for wstring, allocator, basic_string
+#include // 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
using namespace ftxui;
int main(int argc, const char* argv[]) {
- auto screen = ScreenInteractive::TerminalOutput();
- RadioBox radiobox;
- radiobox.entries = {
+ std::vector radiobox_list = {
L"Use gcc",
L"Use clang",
L"Use emscripten",
L"Use tcc",
};
- screen.Loop(&radiobox);
+ int selected = 0;
+
+ auto screen = ScreenInteractive::TerminalOutput();
+ screen.Loop(Radiobox(&radiobox_list, &selected));
return 0;
}
diff --git a/examples/component/radiobox_in_frame.cpp b/examples/component/radiobox_in_frame.cpp
index 09c8644..b62d0d3 100644
--- a/examples/component/radiobox_in_frame.cpp
+++ b/examples/component/radiobox_in_frame.cpp
@@ -1,35 +1,29 @@
+#include // for __shared_ptr_access, shared_ptr
#include // for wstring, operator+
#include // for vector
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/radiobox.hpp" // for RadioBox
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Radiobox, Renderer
+#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/dom/elements.hpp" // for Element, operator|
-#include "ftxui/screen/box.hpp" // for ftxui
-#include "ftxui/screen/string.hpp" // for to_wstring
+#include "ftxui/dom/elements.hpp" // for Element, operator|, size, border, frame, HEIGHT, LESS_THAN
+#include "ftxui/screen/string.hpp" // for to_wstring
using namespace ftxui;
-class MyComponent : public Component {
- RadioBox radiobox;
-
- public:
- MyComponent() {
- for (int i = 0; i < 30; ++i) {
- radiobox.entries.push_back(L"RadioBox " + to_wstring(i));
- }
- Add(&radiobox);
- }
-
- Element Render() override {
- return radiobox.Render() | frame | size(HEIGHT, LESS_THAN, 10) | border;
- }
-};
-
int main(int argc, const char* argv[]) {
+ std::vector entries;
+ int selected = 0;
+
+ for (int i = 0; i < 30; ++i)
+ entries.push_back(L"RadioBox " + to_wstring(i));
+ auto radiobox = Radiobox(&entries, &selected);
+ auto renderer = Renderer(radiobox, [&] {
+ return radiobox->Render() | frame | size(HEIGHT, LESS_THAN, 10) | border;
+ });
+
auto screen = ScreenInteractive::FitComponent();
- MyComponent component;
- screen.Loop(&component);
+ screen.Loop(renderer);
return 0;
}
diff --git a/examples/component/slider.cpp b/examples/component/slider.cpp
index 9e7b6f1..c4b41b6 100644
--- a/examples/component/slider.cpp
+++ b/examples/component/slider.cpp
@@ -1,82 +1,14 @@
-#include // for function
-#include // for allocator, unique_ptr
-#include // for operator+, to_wstring
-
-#include "ftxui/component/component.hpp" // for Component, Compone...
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/event.hpp" // for Event, Event::Escape
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Slider
#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;
-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 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 quit_;
-};
-
int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput();
- int red = 128;
- int green = 25;
- int blue = 100;
- auto component = MyComponent(&red, &green, &blue, screen.ExitLoopClosure());
- screen.Loop(&component);
+ int value = 50;
+ auto slider = Slider(L"Value:", &value, 0, 100, 1);
+ screen.Loop(slider);
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
diff --git a/examples/component/slider_rgb.cpp b/examples/component/slider_rgb.cpp
new file mode 100644
index 0000000..3eb10e6
--- /dev/null
+++ b/examples/component/slider_rgb.cpp
@@ -0,0 +1,62 @@
+#include // for allocator, __shared_ptr_access, shared_ptr
+#include // for operator+, to_wstring, char_traits
+
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Slider, Renderer, Vertical
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
+#include "ftxui/dom/elements.hpp" // for separator, Element, operator|, size, text, vbox, xflex, bgcolor, hbox, GREATER_THAN, WIDTH, border, HEIGHT, LESS_THAN
+#include "ftxui/screen/color.hpp" // for Color
+
+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")" //
+ );
+}
+
+int main(int argc, const char* argv[]) {
+ int red = 128;
+ int green = 25;
+ int blue = 100;
+ auto slider_red = Slider(L"Red :", &red, 0, 255, 1);
+ auto slider_green = Slider(L"Green:", &green, 0, 255, 1);
+ auto slider_blue = Slider(L"Blue :", &blue, 0, 255, 1);
+
+ auto container = Container::Vertical({
+ slider_red,
+ slider_green,
+ slider_blue,
+ });
+
+ auto renderer = Renderer(container, [&] {
+ 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);
+ });
+ auto screen = ScreenInteractive::TerminalOutput();
+ screen.Loop(renderer);
+}
+
+// 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.
diff --git a/examples/component/tab_horizontal.cpp b/examples/component/tab_horizontal.cpp
index 8d4b822..578dff2 100644
--- a/examples/component/tab_horizontal.cpp
+++ b/examples/component/tab_horizontal.cpp
@@ -1,71 +1,68 @@
-#include // for function
-#include // for wstring, allocator
-#include // for vector
+#include // for allocator, __shared_ptr_access, shared_ptr
+#include // for wstring, basic_string
+#include // for vector
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/radiobox.hpp" // for RadioBox
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Radiobox, Renderer, Tab, Toggle, Vertical
+#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/component/toggle.hpp" // for Toggle
-#include "ftxui/dom/elements.hpp" // for Element, operator|
-#include "ftxui/screen/box.hpp" // for ftxui
+#include "ftxui/dom/elements.hpp" // for Element, separator, operator|, vbox, border
using namespace ftxui;
-class MyComponent : public Component {
- public:
- MyComponent() {
- 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 on_enter = []() {};
-
- Element Render() {
- return vbox(toggle_.Render(), separator(), tab_container_.Render()) |
- 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[]) {
+ std::vector tab_values{
+ L"tab_1",
+ L"tab_2",
+ L"tab_3",
+ };
+ int tab_selected = 0;
+ auto tab_toggle = Toggle(&tab_values, &tab_selected);
+
+ std::vector tab_1_entries{
+ L"Forest",
+ L"Water",
+ L"I don't know",
+ };
+ int tab_1_selected = 0;
+
+ std::vector tab_2_entries{
+ L"Hello",
+ L"Hi",
+ L"Hay",
+ };
+ int tab_2_selected = 0;
+
+ std::vector tab_3_entries{
+ L"Table",
+ L"Nothing",
+ L"Is",
+ L"Empty",
+ };
+ int tab_3_selected = 0;
+ auto 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),
+ });
+
+ auto container = Container::Vertical({
+ tab_toggle,
+ tab_container,
+ });
+
+ auto renderer = Renderer(container, [&] {
+ return vbox({
+ tab_toggle->Render(),
+ separator(),
+ tab_container->Render(),
+ }) |
+ border;
+ });
+
auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- component.on_enter = screen.ExitLoopClosure();
- screen.Loop(&component);
+ screen.Loop(renderer);
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
diff --git a/examples/component/tab_vertical.cpp b/examples/component/tab_vertical.cpp
index 398be13..ad454d7 100644
--- a/examples/component/tab_vertical.cpp
+++ b/examples/component/tab_vertical.cpp
@@ -1,64 +1,68 @@
-#include // for function
-#include // for wstring, allocator
-#include // for vector
+#include // for allocator, __shared_ptr_access, shared_ptr
+#include // for wstring, basic_string
+#include // for vector
-#include "ftxui/component/component.hpp" // for Component
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/menu.hpp" // for Menu
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Radiobox, Horizontal, Menu, Renderer, Tab
+#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
-#include "ftxui/screen/box.hpp" // for ftxui
+#include "ftxui/dom/elements.hpp" // for Element, separator, hbox, operator|, border
using namespace ftxui;
-class MyComponent : public Component {
- 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 on_enter = []() {};
-
- private:
- Menu menu_;
- Container container_ = Container::Horizontal();
- Container tab_container_ = Container::Tab(&(menu_.selected));
- Menu menu_1_;
- Menu menu_2_;
- Menu menu_3_;
-};
-
int main(int argc, const char* argv[]) {
+ std::vector tab_values{
+ L"tab_1",
+ L"tab_2",
+ L"tab_3",
+ };
+ int tab_selected = 0;
+ auto tab_menu = Menu(&tab_values, &tab_selected);
+
+ std::vector tab_1_entries{
+ L"Forest",
+ L"Water",
+ L"I don't know",
+ };
+ int tab_1_selected = 0;
+
+ std::vector tab_2_entries{
+ L"Hello",
+ L"Hi",
+ L"Hay",
+ };
+ int tab_2_selected = 0;
+
+ std::vector tab_3_entries{
+ L"Table",
+ L"Nothing",
+ L"Is",
+ L"Empty",
+ };
+ int tab_3_selected = 0;
+ auto 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),
+ });
+
+ auto container = Container::Horizontal({
+ tab_menu,
+ tab_container,
+ });
+
+ auto renderer = Renderer(container, [&] {
+ return hbox({
+ tab_menu->Render(),
+ separator(),
+ tab_container->Render(),
+ }) |
+ border;
+ });
+
auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- component.on_enter = screen.ExitLoopClosure();
- screen.Loop(&component);
+ screen.Loop(renderer);
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
diff --git a/examples/component/toggle.cpp b/examples/component/toggle.cpp
index 5ecf092..b56f211 100644
--- a/examples/component/toggle.cpp
+++ b/examples/component/toggle.cpp
@@ -1,59 +1,63 @@
-#include "ftxui/component/toggle.hpp"
-#include "ftxui/component/container.hpp" // for Container
-#include "ftxui/component/event.hpp" // for Event, Event::Return
-#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
+#include // for allocator, __shared_ptr_access
+#include // for wstring, basic_string
+#include // for vector
+
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component.hpp" // for Toggle, Renderer, Vertical
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
+#include "ftxui/dom/elements.hpp" // for text, hbox, vbox, Element
using namespace ftxui;
-class MyComponent : public Component {
- public:
- MyComponent() {
- Add(&container_);
- container_.Add(&toggle_1_);
- container_.Add(&toggle_2_);
- container_.Add(&toggle_3_);
- container_.Add(&toggle_4_);
+int main(int argc, const char* argv[]) {
+ std::vector toggle_1_entries = {
+ L"On",
+ L"Off",
+ };
+ std::vector toggle_2_entries = {
+ L"Enabled",
+ L"Disabled",
+ };
+ std::vector toggle_3_entries = {
+ L"10€",
+ L"0€",
+ };
+ std::vector toggle_4_entries = {
+ L"Nothing",
+ L"One element",
+ L"Several elements",
+ };
- 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"};
- }
+ 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 on_enter = []() {};
+ auto container = Container::Vertical({
+ toggle_1,
+ toggle_2,
+ toggle_3,
+ toggle_4,
+ });
- private:
- Container container_ = Container::Vertical();
- Toggle toggle_1_;
- Toggle toggle_2_;
- Toggle toggle_3_;
- Toggle toggle_4_;
-
- Element Render() override {
+ auto renderer = Renderer(container, [&] {
return vbox({
text(L"Choose your options:"),
text(L""),
- hbox(text(L" * Poweroff on startup : "), toggle_1_.Render()),
- hbox(text(L" * Out of process : "), toggle_2_.Render()),
- hbox(text(L" * Price of the information : "), toggle_3_.Render()),
- hbox(text(L" * Number of elements : "), toggle_4_.Render()),
+ hbox(text(L" * Poweroff on startup : "), toggle_1->Render()),
+ hbox(text(L" * Out of process : "), toggle_2->Render()),
+ hbox(text(L" * Price of the information : "), toggle_3->Render()),
+ hbox(text(L" * Number of elements : "), toggle_4->Render()),
});
- }
+ });
- bool OnEvent(Event event) override {
- if (event == Event::Return) {
- on_enter();
- return true;
- }
- return Component::OnEvent(event);
- }
-};
-
-int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput();
- MyComponent component;
- component.on_enter = screen.ExitLoopClosure();
- screen.Loop(&component);
+ screen.Loop(renderer);
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
diff --git a/examples/dom/hflow.cpp b/examples/dom/hflow.cpp
index 6d2cb9d..02b9a71 100644
--- a/examples/dom/hflow.cpp
+++ b/examples/dom/hflow.cpp
@@ -1,11 +1,12 @@
-#include
-#include
-#include
-#include
-#include
+#include // for size_t
+#include // for operator|, size, Element, text, hcenter, Decorator, WIDTH, hflow, window, EQUAL, GREATER_THAN, HEIGHT, bold, border, dim, LESS_THAN
+#include // for Dimension, Screen
+#include // for to_wstring
+#include // for shared_ptr
+#include // for allocator, operator+, char_traits, wstring
-#include "ftxui/dom/node.hpp"
-#include "ftxui/screen/box.hpp"
+#include "ftxui/dom/node.hpp" // for Render
+#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;
diff --git a/examples/dom/html_like.cpp b/examples/dom/html_like.cpp
index 4f60287..c125267 100644
--- a/examples/dom/html_like.cpp
+++ b/examples/dom/html_like.cpp
@@ -1,13 +1,14 @@
-#include
-#include
-#include
-#include
-#include
-#include
+#include // for operator""s, chrono_literals
+#include // for paragraph, text, operator|, Element, border, color, hflow, spinner, vbox, bold, dim, underlined
+#include // for Screen, Dimension
+#include // for cout, ostream
+#include // for shared_ptr
+#include // for allocator, operator<<, string
+#include // for sleep_for
-#include "ftxui/dom/node.hpp"
-#include "ftxui/screen/box.hpp"
-#include "ftxui/screen/color.hpp"
+#include "ftxui/dom/node.hpp" // for Render
+#include "ftxui/screen/box.hpp" // for ftxui
+#include "ftxui/screen/color.hpp" // for Color, Color::Red
int main(int argc, const char* argv[]) {
using namespace ftxui;
diff --git a/examples/index.html b/examples/index.html
index 4fd3e5c..a4a427d 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -33,15 +33,18 @@
"./component/menu.js",
"./component/menu2.js",
"./component/menu_style.js",
+ "./component/modal_dialog.js",
"./component/radiobox.js",
"./component/radiobox_in_frame.js",
+ "./component/slider.js",
"./component/tab_horizontal.js",
"./component/tab_vertical.js",
"./component/toggle.js",
- "./component/modal_dialog.js",
-
"./dom/border.js",
"./dom/color_gallery.js",
+ "./dom/color_info_palette256.js",
+ "./dom/color_truecolor_HSV.js",
+ "./dom/color_truecolor_RGB.js",
"./dom/dbox.js",
"./dom/gauge.js",
"./dom/graph.js",
@@ -55,16 +58,12 @@
"./dom/style_blink.js",
"./dom/style_bold.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_gallery.js",
"./dom/style_inverted.js",
"./dom/style_underlined.js",
"./dom/vbox_hbox.js",
"./dom/window.js",
-
"./util/print_key_press.js",
];
diff --git a/examples/util/print_key_press.cpp b/examples/util/print_key_press.cpp
index 3f255b5..02a13b3 100644
--- a/examples/util/print_key_press.cpp
+++ b/examples/util/print_key_press.cpp
@@ -4,16 +4,17 @@
#include // for size_t
#include // for max
-#include // for Component
+#include // for Make
#include // for ScreenInteractive
-#include // for allocator, operator+
-#include // for move
-#include // for vector
+#include // for allocator, operator+, wstring, char_traits, to_wstring, string
+#include // for move
+#include // for vector
-#include "ftxui/component/event.hpp" // for Event
-#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left
-#include "ftxui/dom/elements.hpp" // for text, vbox, window
-#include "ftxui/screen/box.hpp" // for ftxui
+#include "ftxui/component/captured_mouse.hpp" // for ftxui
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/event.hpp" // for Event
+#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;
@@ -71,7 +72,7 @@ std::wstring Stringify(Event event) {
return out;
}
-class DrawKey : public Component {
+class DrawKey : public ComponentBase {
public:
~DrawKey() override = default;
@@ -94,6 +95,5 @@ class DrawKey : public Component {
int main(int argc, const char* argv[]) {
auto screen = ScreenInteractive::TerminalOutput();
- DrawKey draw_key;
- screen.Loop(&draw_key);
+ screen.Loop(Make());
}
diff --git a/include/ftxui/component/button.hpp b/include/ftxui/component/button.hpp
index e7b190c..8638823 100644
--- a/include/ftxui/component/button.hpp
+++ b/include/ftxui/component/button.hpp
@@ -1,36 +1,36 @@
#ifndef FTXUI_COMPONENT_BUTTON_HPP
#define FTXUI_COMPONENT_BUTTON_HPP
-#include
-#include
+#include // for function
+#include // for wstring
-#include "ftxui/component/component.hpp"
-#include "ftxui/dom/elements.hpp"
-#include "ftxui/screen/box.hpp"
+#include "ftxui/component/component.hpp" // for Component
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/dom/elements.hpp" // for Element
+#include "ftxui/screen/box.hpp" // for Box
+#include "ftxui/screen/string.hpp" // for ConstStringRef
namespace ftxui {
struct Event;
/// @brief A button. An action is associated to the click event.
/// @ingroup dom
-class Button : public Component {
+class ButtonBase : public ComponentBase {
public:
+ // Access this interface from a Component
+ static ButtonBase* From(Component);
+
// Constructor.
- Button() = default;
- Button(std::wstring label) : label(label) {}
- ~Button() override = default;
-
- /// The Button label.
- std::wstring label = L"button";
-
- /// Called when the user press the "enter" button.
- std::function on_click = [] {};
+ ButtonBase(ConstStringRef label, std::function on_click);
+ ~ButtonBase() override = default;
// Component implementation.
Element Render() override;
bool OnEvent(Event) override;
private:
+ ConstStringRef label_;
+ std::function on_click_;
Box box_;
};
diff --git a/include/ftxui/component/checkbox.hpp b/include/ftxui/component/checkbox.hpp
index 214ce52..9cd1db4 100644
--- a/include/ftxui/component/checkbox.hpp
+++ b/include/ftxui/component/checkbox.hpp
@@ -1,10 +1,14 @@
#ifndef FTXUI_COMPONENT_CHECKBOX_HPP
#define FTXUI_COMPONENT_CHECKBOX_HPP
-#include
+#include // for function
+#include // for allocator, wstring
-#include "ftxui/component/component.hpp"
-#include "ftxui/screen/box.hpp"
+#include "ftxui/component/component.hpp" // for Component
+#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
+#include "ftxui/screen/string.hpp" // for ConstStringRef
namespace ftxui {
struct Event;
@@ -12,14 +16,14 @@ struct Event;
/// @brief A Checkbox. It can be checked or unchecked.Display an element on a
/// ftxui::Screen.
/// @ingroup dom
-class CheckBox : public Component {
+class CheckboxBase : public ComponentBase {
public:
- // Constructor.
- CheckBox() = default;
- ~CheckBox() override = default;
+ // Access this interface from a Component
+ static CheckboxBase* From(Component component);
- bool state = false; // The current state. true=checked, false:unchecked.
- std::wstring label = L"label"; // The CheckBox label.
+ // Constructor.
+ CheckboxBase(ConstStringRef label, bool* state);
+ ~CheckboxBase() override = default;
#if defined(_WIN32)
std::wstring checked = L"[X] "; /// Prefix for a "checked" state.
@@ -32,7 +36,7 @@ class CheckBox : public Component {
Decorator focused_style = inverted; /// Decorator used when focused.
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 on_change = []() {};
// Component implementation.
@@ -42,6 +46,8 @@ class CheckBox : public Component {
private:
bool OnMouseEvent(Event event);
+ ConstStringRef label_;
+ bool* const state_;
int cursor_position = 0;
Box box_;
};
diff --git a/include/ftxui/component/component.hpp b/include/ftxui/component/component.hpp
index 9003f1c..11abf6d 100644
--- a/include/ftxui/component/component.hpp
+++ b/include/ftxui/component/component.hpp
@@ -1,77 +1,48 @@
-#ifndef FTXUI_COMPONENT_COMPONENT_HPP
-#define FTXUI_COMPONENT_COMPONENT_HPP
+#ifndef FTXUI_COMPONENT_HPP
+#define FTXUI_COMPONENT_HPP
-#include // for unique_ptr
-#include // for vector
+#include // for function
+#include // for shared_ptr, make_shared
+#include // for wstring
+#include // for vector
-#include "ftxui/component/captured_mouse.hpp" // for CaptureMouse
-#include "ftxui/dom/elements.hpp" // for Element
+#include "ftxui/component/component_base.hpp"
+#include "ftxui/dom/elements.hpp" // for Element
+#include "ftxui/screen/string.hpp" // for ConstStringRef, StringRef
namespace ftxui {
-class Delegate;
-class Focus;
-struct Event;
+class ComponentBase;
-/// @brief It implement rendering itself as ftxui::Element. It implement
-/// keyboard navigation by responding to ftxui::Event.
-/// @ingroup component
-class Component {
- public:
- // Constructor/Destructor.
- Component() = default;
- virtual ~Component();
+using Component = std::shared_ptr;
+using Components = std::vector;
- // Component hierarchy.
- Component* Parent();
- void Add(Component* children);
+template
+std::shared_ptr Make(Args&&... args) {
+ return std::make_shared(args...);
+}
- // Renders the component.
- virtual Element Render();
+Component Button(ConstStringRef label, std::function on_click);
+Component Checkbox(ConstStringRef label, bool* checked);
+Component Input(StringRef content, ConstStringRef placeholder);
+Component Menu(const std::vector* entries, int* selected_);
+Component Radiobox(const std::vector* entries, int* selected_);
+Component Toggle(const std::vector* entries, int* selected);
+Component Renderer(Component child, std::function);
+Component Renderer(std::function);
+template // T = {int, float}
+Component Slider(StringRef label, T* value, T min, T max, T increment);
- // 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(Component* child);
-
- // Configure all the ancestors to give focus to this component.
- void TakeFocus();
-
- protected:
- CapturedMouse CaptureMouse(const Event& event);
-
- std::vector children_;
-
- private:
- Component* parent_ = nullptr;
- void Detach();
- void Attach(Component* parent);
-};
-
-using ComponentPtr = std::unique_ptr;
+namespace Container {
+Component Vertical(Components children);
+Component Horizontal(Components children);
+Component Tab(int* selector, Components children);
+} // namespace Container
} // namespace ftxui
-#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_HPP */
+#endif /* end of include guard: FTXUI_COMPONENT_HPP */
-// 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
// the LICENSE file.
diff --git a/include/ftxui/component/component_base.hpp b/include/ftxui/component/component_base.hpp
new file mode 100644
index 0000000..4e8fd63
--- /dev/null
+++ b/include/ftxui/component/component_base.hpp
@@ -0,0 +1,81 @@
+#ifndef FTXUI_COMPONENT_BASE_HPP
+#define FTXUI_COMPONENT_BASE_HPP
+
+#include // for unique_ptr
+#include // 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;
+using Components = std::vector;
+
+/// @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 children_;
+
+ private:
+ ComponentBase* parent_ = nullptr;
+ void Detach();
+};
+
+using Component = std::shared_ptr;
+
+} // 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.
diff --git a/include/ftxui/component/container.hpp b/include/ftxui/component/container.hpp
index 3f78798..f15b65f 100644
--- a/include/ftxui/component/container.hpp
+++ b/include/ftxui/component/container.hpp
@@ -1,36 +1,42 @@
#ifndef FTXUI_COMPONENT_CONTAINER_HPP
#define FTXUI_COMPONENT_CONTAINER_HPP
-#include "ftxui/component/component.hpp"
-#include "ftxui/component/event.hpp"
-#include "ftxui/dom/elements.hpp"
+#include "ftxui/component/component.hpp" // for Component, Components
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/component/event.hpp" // for Event
+#include "ftxui/dom/elements.hpp" // for Element
namespace ftxui {
/// @brief A component where focus and events are automatically handled for you.
-class Container : public Component {
+class ContainerBase : public ComponentBase {
public:
- static Container Vertical();
- static Container Horizontal();
- static Container Tab(int* selector);
+ static Component Vertical();
+ static Component Vertical(Components children);
- ~Container() override = default;
+ static Component Horizontal();
+ static Component Horizontal(Components children);
+
+ static Component Tab(int* selector);
+ static Component Tab(int* selector, Components children);
+
+ ~ContainerBase() override = default;
// Component override.
bool OnEvent(Event event) override;
Element Render() override;
- Component* ActiveChild() override;
- virtual void SetActiveChild(Component*) override;
+ Component ActiveChild() override;
+ virtual void SetActiveChild(ComponentBase*) override;
protected:
// Handlers
- using EventHandler = bool (Container::*)(Event);
+ using EventHandler = bool (ContainerBase::*)(Event);
bool VerticalEvent(Event event);
bool HorizontalEvent(Event event);
bool TabEvent(Event) { return false; }
EventHandler event_handler_;
- using RenderHandler = Element (Container::*)();
+ using RenderHandler = Element (ContainerBase::*)();
Element VerticalRender();
Element HorizontalRender();
Element TabRender();
diff --git a/include/ftxui/component/event.hpp b/include/ftxui/component/event.hpp
index e77feae..3096a86 100644
--- a/include/ftxui/component/event.hpp
+++ b/include/ftxui/component/event.hpp
@@ -8,7 +8,7 @@
namespace ftxui {
class ScreenInteractive;
-class Component;
+class ComponentBase;
/// @brief Represent an event. It can be key press event, a terminal resize, or
/// more ...
@@ -76,7 +76,7 @@ struct Event {
//--- State section ----------------------------------------------------------
private:
- friend Component;
+ friend ComponentBase;
friend ScreenInteractive;
enum class Type {
Unknown,
diff --git a/include/ftxui/component/input.hpp b/include/ftxui/component/input.hpp
index fedeacb..605db99 100644
--- a/include/ftxui/component/input.hpp
+++ b/include/ftxui/component/input.hpp
@@ -1,27 +1,30 @@
#ifndef FTXUI_COMPONENT_INPUT_H_
#define FTXUI_COMPONENT_INPUT_H_
-#include
-#include
+#include // for function
+#include // for wstring
-#include "ftxui/component/component.hpp"
-#include "ftxui/dom/elements.hpp"
-#include "ftxui/screen/box.hpp"
+#include "ftxui/component/component.hpp" // for Component
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/dom/elements.hpp" // for Element
+#include "ftxui/screen/box.hpp" // for Box
+#include "ftxui/screen/string.hpp" // for ConstStringRef, StringRef
namespace ftxui {
struct Event;
/// @brief An input box. The user can type text into it.
/// @ingroup component.
-class Input : public Component {
+class InputBase : public ComponentBase {
public:
+ // Access this interface from a Component
+ static InputBase* From(Component component);
+
// Constructor.
- Input() = default;
- ~Input() override = default;
+ InputBase(StringRef content, ConstStringRef placeholder);
+ ~InputBase() override = default;
// State.
- std::wstring content;
- std::wstring placeholder;
int cursor_position = 0;
// State update callback.
@@ -33,6 +36,9 @@ class Input : public Component {
bool OnEvent(Event) override;
private:
+ StringRef content_;
+ ConstStringRef placeholder_;
+
bool OnMouseEvent(Event);
Box input_box_;
Box cursor_box_;
diff --git a/include/ftxui/component/menu.hpp b/include/ftxui/component/menu.hpp
index 8e3f2b1..3f30839 100644
--- a/include/ftxui/component/menu.hpp
+++ b/include/ftxui/component/menu.hpp
@@ -1,28 +1,30 @@
#ifndef FTXUI_COMPONENT_MENU
#define FTXUI_COMPONENT_MENU
-#include
-#include
-#include
+#include // for function
+#include // for wstring
+#include // for vector
-#include "ftxui/component/component.hpp"
-#include "ftxui/dom/elements.hpp"
-#include "ftxui/screen/box.hpp"
+#include "ftxui/component/component.hpp" // for Component
+#include "ftxui/component/component_base.hpp" // for ComponentBase
+#include "ftxui/dom/elements.hpp" // for Element, Decorator, operator|, bold, inverted, nothing
+#include "ftxui/screen/box.hpp" // for Box
namespace ftxui {
struct Event;
/// @brief A list of items. The user can navigate through them.
/// @ingroup component
-class Menu : public Component {
+class MenuBase : public ComponentBase {
public:
+ // Access this interface from a Component
+ static MenuBase* From(Component component);
+
// Constructor.
- Menu() = default;
- ~Menu() override = default;
+ MenuBase(const std::vector* entries, int* selected_);
+ ~MenuBase() override = default;
// State.
- std::vector entries = {};
- int selected = 0;
int focused = 0;
Decorator normal_style = nothing;
@@ -38,7 +40,10 @@ class Menu : public Component {
Element Render() override;
bool OnEvent(Event) override;
- private:
+ protected:
+ const std::vector* const entries_;
+ int* selected_ = 0;
+
bool OnMouseEvent(Event);
std::vector boxes_;
diff --git a/include/ftxui/component/radiobox.hpp b/include/ftxui/component/radiobox.hpp
index 7493245..8df7a32 100644
--- a/include/ftxui/component/radiobox.hpp
+++ b/include/ftxui/component/radiobox.hpp
@@ -1,12 +1,14 @@
#ifndef FTXUI_COMPONENT_RADIOBOX_HPP
#define FTXUI_COMPONENT_RADIOBOX_HPP
-#include
-#include
+#include // for function
+#include // for wstring, allocator
+#include // for vector
-#include "ftxui/component/component.hpp"
-#include "ftxui/dom/elements.hpp"
-#include "ftxui/screen/box.hpp"
+#include "ftxui/component/component.hpp" // for Component
+#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 {
struct Event;
@@ -14,15 +16,16 @@ struct Event;
/// @brief A list of selectable element. One and only one can be selected at
/// the same time.
/// @ingroup component
-class RadioBox : public Component {
+class RadioboxBase : public ComponentBase {
public:
- // Constructor.
- RadioBox() = default;
- ~RadioBox() override = default;
+ // Access this interface from a Component
+ static RadioboxBase* From(Component component);
+
+ // Constructor.
+ RadioboxBase(const std::vector* entries, int* selected);
+ ~RadioboxBase() override = default;
- int selected = 0;
int focused = 0;
- std::vector entries;
#if defined(_WIN32)
std::wstring checked = L"(*) ";
@@ -43,6 +46,9 @@ class RadioBox : public Component {
bool OnEvent(Event) override;
private:
+ const std::vector* const entries_;
+ int* const selected_;
+
bool OnMouseEvent(Event event);
int cursor_position = 0;
std::vector boxes_;
diff --git a/include/ftxui/component/receiver.hpp b/include/ftxui/component/receiver.hpp
index 8b236c3..2f35f44 100644
--- a/include/ftxui/component/receiver.hpp
+++ b/include/ftxui/component/receiver.hpp
@@ -1,13 +1,15 @@
#ifndef FTXUI_COMPONENT_RECEIVER_HPP_
#define FTXUI_COMPONENT_RECEIVER_HPP_
-#include // for atomic
+#include // for copy, max
+#include // for atomic, __atomic_base
#include // for condition_variable
#include
#include
-#include // for unique_ptr, make_unique
-#include // for mutex, unique_lock
-#include // for queue
+#include // for unique_ptr, make_unique
+#include // for mutex, unique_lock
+#include // for queue
+#include // for move
namespace ftxui {
diff --git a/include/ftxui/component/screen_interactive.hpp b/include/ftxui/component/screen_interactive.hpp
index c3a3251..827602f 100644
--- a/include/ftxui/component/screen_interactive.hpp
+++ b/include/ftxui/component/screen_interactive.hpp
@@ -1,17 +1,20 @@
#ifndef FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
#define FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
-#include // for atomic
-#include
-#include // for unique_ptr
-#include // for string
+#include // for atomic
+#include // for Receiver, Sender
+#include // for function
+#include // for shared_ptr
+#include