diff --git a/examples/component/CMakeLists.txt b/examples/component/CMakeLists.txt index 6ed74d9..ef7bf5f 100644 --- a/examples/component/CMakeLists.txt +++ b/examples/component/CMakeLists.txt @@ -4,12 +4,13 @@ function(example name) target_link_libraries(${name} PUBLIC component) endfunction(example) +example(checkbox) example(gallery) example(input) example(menu) example(menu2) example(menu_style) -example(toggle) +example(radiobox) example(tab_horizontal) example(tab_vertical) -example(checkbox) +example(toggle) diff --git a/examples/component/checkbox.cpp b/examples/component/checkbox.cpp index f44366b..467b6c8 100644 --- a/examples/component/checkbox.cpp +++ b/examples/component/checkbox.cpp @@ -20,11 +20,21 @@ class MyComponent : public Component { box_1_.label = L"Build examples"; box_2_.label = L"Build tests"; box_3_.label = L"Use WebAssembly"; + box_3_.state = true; + } + + Element Render() { + return + window(text(L" Checkbox "), + hbox( + container_.Render() + ) + ); } }; int main(int argc, const char *argv[]) { - auto screen = ScreenInteractive::TerminalOutput(); + auto screen = ScreenInteractive::FixedSize(30,5); MyComponent component; screen.Loop(&component); return 0; diff --git a/examples/component/radiobox.cpp b/examples/component/radiobox.cpp new file mode 100644 index 0000000..4d3fc4b --- /dev/null +++ b/examples/component/radiobox.cpp @@ -0,0 +1,19 @@ +#include "ftxui/component/radiobox.hpp" +#include "ftxui/component/component.hpp" +#include "ftxui/component/container.hpp" +#include "ftxui/component/screen_interactive.hpp" + +using namespace ftxui; + +int main(int argc, const char* argv[]) { + auto screen = ScreenInteractive::TerminalOutput(); + RadioBox radiobox; + radiobox.entries = { + L"Use gcc", + L"Use clang", + L"Use emscripten", + L"Use tcc", + }; + screen.Loop(&radiobox); + return 0; +} diff --git a/examples/component/tab_horizontal.cpp b/examples/component/tab_horizontal.cpp index 95b7f55..097cc3b 100644 --- a/examples/component/tab_horizontal.cpp +++ b/examples/component/tab_horizontal.cpp @@ -2,7 +2,7 @@ #include #include "ftxui/component/container.hpp" -#include "ftxui/component/menu.hpp" +#include "ftxui/component/radiobox.hpp" #include "ftxui/component/screen_interactive.hpp" #include "ftxui/component/toggle.hpp" #include "ftxui/screen/string.hpp" @@ -10,55 +10,59 @@ using namespace ftxui; class MyComponent : public Component { - public: - MyComponent() { - Add(&container_); - container_.Add(&toggle_); + public: + MyComponent() { + Add(&container_); + container_.Add(&toggle_); - toggle_.entries = { - L"menu_1", - L"menu_2", - L"menu_3", - }; + toggle_.entries = { + L"tab_1", + L"tab_2", + L"tab_3", + }; - container_.Add(&tab_container_); - - menu_1_.entries = { - L"Forest", - L"Water", - L"I don't know" - }; - tab_container_.Add(&menu_1_); + container_.Add(&tab_container_); - menu_2_.entries = { - L"Hello", - L"Hi", - L"Hay", - }; - tab_container_.Add(&menu_2_); + radiobox_1_.entries = {L"Forest", L"Water", L"I don't know"}; + tab_container_.Add(&radiobox_1_); - menu_3_.entries = { - L"Table", - L"Nothing", - L"Is", - L"Empty", - }; - tab_container_.Add(&menu_3_); - } + radiobox_2_.entries = { + L"Hello", + L"Hi", + L"Hay", + }; + tab_container_.Add(&radiobox_2_); - std::function on_enter = [](){}; - private: - Toggle toggle_; - Container container_ = Container::Vertical(); - Container tab_container_ = Container::Tab(&(toggle_.selected)); - Menu menu_1_; - Menu menu_2_; - Menu menu_3_; + 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() + ) | frame; + } + + private: + Toggle toggle_; + Container container_ = Container::Vertical(); + Container tab_container_ = Container::Tab(&(toggle_.selected)); + RadioBox radiobox_1_; + RadioBox radiobox_2_; + RadioBox radiobox_3_; }; - -int main(int argc, const char *argv[]) -{ +int main(int argc, const char* argv[]) { auto screen = ScreenInteractive::TerminalOutput(); MyComponent component; component.on_enter = screen.ExitLoopClosure(); diff --git a/ftxui/CMakeLists.txt b/ftxui/CMakeLists.txt index 614b7c6..fd8d885 100644 --- a/ftxui/CMakeLists.txt +++ b/ftxui/CMakeLists.txt @@ -36,6 +36,7 @@ add_library(component src/ftxui/component/event.cpp src/ftxui/component/input.cpp src/ftxui/component/menu.cpp + src/ftxui/component/radiobox.cpp src/ftxui/component/screen_interactive.cpp src/ftxui/component/toggle.cpp ) diff --git a/ftxui/include/ftxui/component/checkbox.hpp b/ftxui/include/ftxui/component/checkbox.hpp index f19e209..9a2c325 100644 --- a/ftxui/include/ftxui/component/checkbox.hpp +++ b/ftxui/include/ftxui/component/checkbox.hpp @@ -15,8 +15,10 @@ class CheckBox : public Component { bool state = false; std::wstring label = L"label"; - std::wstring checked = L"[X] "; - std::wstring unchecked = L"[ ] "; + //std::wstring checked = L"[X] "; + //std::wstring unchecked = L"[ ] "; + std::wstring checked = L"☑ "; + std::wstring unchecked = L"☐ "; // State update callback. std::function on_change = [](){}; diff --git a/ftxui/include/ftxui/component/radiobox.hpp b/ftxui/include/ftxui/component/radiobox.hpp new file mode 100644 index 0000000..8a7361e --- /dev/null +++ b/ftxui/include/ftxui/component/radiobox.hpp @@ -0,0 +1,38 @@ +#ifndef FTXUI_COMPONENT_RADIOBOX_HPP +#define FTXUI_COMPONENT_RADIOBOX_HPP + +#include "ftxui/component/component.hpp" +#include + +namespace ftxui { + +class RadioBox : public Component { + public: + // Constructor. + RadioBox() = default; + ~RadioBox() override = default; + + int selected = 0; + int focused = 0; + std::vector entries; + + std::wstring checked = L"◉ "; + std::wstring unchecked = L"○ "; + + Decorator focused_style = inverted; + Decorator unfocused_style = nothing; + + // State update callback. + std::function on_change = [](){}; + + // Component implementation. + Element Render() override; + bool OnEvent(Event) override; + + private: + int cursor_position = 0; +}; + +} // namespace ftxui + +#endif /* end of include guard: FTXUI_COMPONENT_RADIOBOX_HPP */ diff --git a/ftxui/src/ftxui/component/radiobox.cpp b/ftxui/src/ftxui/component/radiobox.cpp new file mode 100644 index 0000000..88b1531 --- /dev/null +++ b/ftxui/src/ftxui/component/radiobox.cpp @@ -0,0 +1,41 @@ +#include "ftxui/component/radiobox.hpp" +#include + +namespace ftxui { + +Element RadioBox::Render() { + std::vector elements; + bool is_focused = Focused(); + for (size_t i = 0; i < entries.size(); ++i) { + auto style = + (focused == int(i) && is_focused) ? focused_style : unfocused_style; + const std::wstring& symbol = selected == int(i) ? checked : unchecked; + elements.push_back(hbox(text(symbol), text(entries[i]) | style)); + } + return vbox(std::move(elements)); +} + +bool RadioBox::OnEvent(Event event) { + if (!Focused()) + return false; + + int new_focused = focused; + if (event == Event::ArrowUp || event == Event::Character('k')) + new_focused--; + if (event == Event::ArrowDown || event == Event::Character('j')) + new_focused++; + new_focused = std::max(0, std::min(int(entries.size()) - 1, new_focused)); + if (focused != new_focused) { + focused = new_focused; + return true; + } + + if (event == Event::Character(' ')) { + selected = focused; + on_change(); + } + + return false; +} + +} // namespace ftxui