From fc92f52b4c30ecdf7e2723ad9fcc2a84a26af1ab Mon Sep 17 00:00:00 2001 From: Arthur Sonzogni Date: Sun, 2 Jan 2022 15:48:56 +0100 Subject: [PATCH] The collapsible element. (#294) --- CHANGELOG.md | 5 +-- CMakeLists.txt | 1 + examples/component/CMakeLists.txt | 1 + examples/component/collapsible.cpp | 60 +++++++++++++++++++++++++++ include/ftxui/component/component.hpp | 23 +++++----- src/ftxui/component/collapsible.cpp | 55 ++++++++++++++++++++++++ src/ftxui/component/maybe.cpp | 6 +-- 7 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 examples/component/collapsible.cpp create mode 100644 src/ftxui/component/collapsible.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index df59715..28a6e38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,11 +21,8 @@ unreleased (development) - Add the helper elements based on `flexbox`: `hflow()`, `vflow()`. - Add: `focusPositionRelative` and `focusPosition` -### Bug - #### Component -- `Input` shouldn't take focus when hovered by the mouse. -- Modifying `Input`'s during on_enter/on_change event is now working correctly. +- Add the `collapsible` component. ### Bug diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a672bd..cb7cb13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,7 @@ add_library(component src/ftxui/component/button.cpp src/ftxui/component/catch_event.cpp src/ftxui/component/checkbox.cpp + src/ftxui/component/collapsible.cpp src/ftxui/component/component.cpp src/ftxui/component/container.cpp src/ftxui/component/dropdown.cpp diff --git a/examples/component/CMakeLists.txt b/examples/component/CMakeLists.txt index d8a510d..848c55a 100644 --- a/examples/component/CMakeLists.txt +++ b/examples/component/CMakeLists.txt @@ -4,6 +4,7 @@ example(button) example(canvas_animated) example(checkbox) example(checkbox_in_frame) +example(collapsible) example(composition) example(dropdown) example(flexbox_gallery) diff --git a/examples/component/collapsible.cpp b/examples/component/collapsible.cpp new file mode 100644 index 0000000..45e1af0 --- /dev/null +++ b/examples/component/collapsible.cpp @@ -0,0 +1,60 @@ +#include // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream +#include // for shared_ptr, __shared_ptr_access +#include // for to_string, allocator + +#include "ftxui/component/captured_mouse.hpp" // for ftxui +#include "ftxui/component/component.hpp" // for MenuEntry, Renderer, Vertical +#include "ftxui/component/component_base.hpp" // for ComponentBase +#include "ftxui/component/component_options.hpp" // for MenuEntryOption +#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive +#include "ftxui/dom/elements.hpp" // for operator|, separator, Element, Decorator, color, text, hbox, size, bold, frame, inverted, vbox, HEIGHT, LESS_THAN, border +#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::Cyan, Color::Green, Color::Red, Color::Yellow + +using namespace ftxui; + +// Take a list of component, display them vertically, one column shifted to the +// right. +Component Inner(std::vector children) { + Component vlist = Container::Vertical(std::move(children)); + return Renderer(vlist, [vlist] { + return hbox({ + text(" "), + vlist->Render(), + }); + }); +} + +Component Empty() { + return std::make_shared(); +} + +int main(int argc, const char* argv[]) { + auto component = + Collapsible("Collapsible 1", + Inner({ + Collapsible("Collapsible 1.1", + Inner({ + Collapsible("Collapsible 1.1.1", Empty()), + Collapsible("Collapsible 1.1.2", Empty()), + Collapsible("Collapsible 1.1.3", Empty()), + })), + Collapsible("Collapsible 1.2", + Inner({ + Collapsible("Collapsible 1.2.1", Empty()), + Collapsible("Collapsible 1.2.2", Empty()), + Collapsible("Collapsible 1.2.3", Empty()), + })), + Collapsible("Collapsible 1.3", + Inner({ + Collapsible("Collapsible 1.3.1", Empty()), + Collapsible("Collapsible 1.3.2", Empty()), + Collapsible("Collapsible 1.3.3", Empty()), + })), + })); + + ScreenInteractive::FitComponent().Loop(component); +} + +// 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/component.hpp b/include/ftxui/component/component.hpp index 711ac8f..1582e3b 100644 --- a/include/ftxui/component/component.hpp +++ b/include/ftxui/component/component.hpp @@ -26,6 +26,15 @@ std::shared_ptr Make(Args&&... args) { return std::make_shared(args...); } +namespace Container { +Component Vertical(Components children); +Component Vertical(Components children, int* selector); +Component Horizontal(Components children); +Component Horizontal(Components children, int* selector); +Component Tab(Components children, int* selector); + +} // namespace Container + Component Button(ConstStringRef label, std::function on_click, Ref = {}); @@ -56,16 +65,10 @@ Component Renderer(Component child, std::function); Component Renderer(std::function); Component Renderer(std::function); Component CatchEvent(Component child, std::function); -Component Maybe(Component, bool* show); - -namespace Container { -Component Vertical(Components children); -Component Vertical(Components children, int* selector); -Component Horizontal(Components children); -Component Horizontal(Components children, int* selector); -Component Tab(Components children, int* selector); - -} // namespace Container +Component Maybe(Component, const bool* show); +Component Collapsible(ConstStringRef label, + Component child, + Ref show = false); } // namespace ftxui diff --git a/src/ftxui/component/collapsible.cpp b/src/ftxui/component/collapsible.cpp new file mode 100644 index 0000000..c7b74ec --- /dev/null +++ b/src/ftxui/component/collapsible.cpp @@ -0,0 +1,55 @@ +#include // for make_unique, __shared_ptr_access, __shared_ptr_access<>::element_type, shared_ptr +#include // for move + +#include "ftxui/component/component.hpp" // for Make, Collapsible +#include "ftxui/component/component_base.hpp" // for ComponentBase, Component +#include "ftxui/component/event.hpp" // for Event +#include "ftxui/dom/elements.hpp" // for Element +#include "ftxui/dom/node.hpp" // for Node + +namespace ftxui { + +/// @brief A collapsible component. It display a checkbox with an arrow. Once +/// activated, the children is displayed. +/// @params label The label of the checkbox. +/// @params child The children to display. +/// @params show Hold the state about whether the children is displayed or not. +/// +/// ### Example +/// ```cpp +/// auto component = Collapsible("Show details", details); +/// ``` +/// +/// ### Output +/// ``` +/// +/// ▼ Show details +///
+/// ``` +Component Collapsible(ConstStringRef label, + Component child, + Ref show) { + class Impl : public ComponentBase { + public: + Impl(ConstStringRef label, Component child, Ref show) + : label_(label), show_(std::move(show)) { + CheckboxOption opt; + opt.style_checked = "▼ "; + opt.style_unchecked = "▶ "; + Add(Container::Vertical({ + Checkbox(label_, show_.operator->(), opt), + Maybe(std::move(child), show_.operator->()), + })); + } + ConstStringRef label_; + Ref show_; + }; + + return Make(label, std::move(child), std::move(show)); +} + +} // namespace ftxui + +// 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/src/ftxui/component/maybe.cpp b/src/ftxui/component/maybe.cpp index ed8f029..838e3ca 100644 --- a/src/ftxui/component/maybe.cpp +++ b/src/ftxui/component/maybe.cpp @@ -9,10 +9,10 @@ namespace ftxui { -Component Maybe(Component child, bool* show) { +Component Maybe(Component child, const bool* show) { class Impl : public ComponentBase { public: - Impl(bool* show) : show_(show) {} + Impl(const bool* show) : show_(show) {} private: Element Render() override { @@ -25,7 +25,7 @@ Component Maybe(Component child, bool* show) { return *show_ && ComponentBase::OnEvent(event); } - bool* show_; + const bool* show_; }; auto maybe = Make(show);