#include // for function #include // for __shared_ptr_access, shared_ptr #include // for move #include "ftxui/component/captured_mouse.hpp" // for CapturedMouse #include "ftxui/component/component.hpp" // for Make, Renderer #include "ftxui/component/component_base.hpp" // for Component, ComponentBase #include "ftxui/component/event.hpp" // for Event #include "ftxui/component/mouse.hpp" // for Mouse #include "ftxui/dom/elements.hpp" // for Element, operator|, reflect #include "ftxui/screen/box.hpp" // for Box namespace ftxui { /// @brief Return a component, using |render| to render its interface. /// @param render The function drawing the interface. /// @ingroup component /// /// ### Example /// /// ```cpp /// auto screen = ScreenInteractive::TerminalOutput(); /// auto renderer = Renderer([] { /// return text("My interface"); /// }); /// screen.Loop(renderer); /// ``` Component Renderer(std::function render) { class Impl : public ComponentBase { public: Impl(std::function render) : render_(std::move(render)) {} Element Render() override { return render_(); } std::function render_; }; return Make(std::move(render)); } /// @brief Return a new Component, similar to |child|, but using |render| as the /// Component::Render() event. /// @param child The component to forward events to. /// @param render The function drawing the interface. /// @ingroup component /// /// ### Example /// /// ```cpp /// auto screen = ScreenInteractive::TerminalOutput(); /// std::string label = "Click to quit"; /// auto button = Button(&label, screen.ExitLoopClosure()); /// auto renderer = Renderer(button, [&] { /// return hbox({ /// text("A button:"), /// button->Render(), /// }); /// }); /// screen.Loop(renderer); /// ``` Component Renderer(Component child, std::function render) { Component renderer = Renderer(std::move(render)); renderer->Add(std::move(child)); return renderer; } /// @brief Return a focusable component, using |render| to render its interface. /// @param render The function drawing the interface, taking a boolean telling /// whether the component is focused or not. /// @ingroup component /// /// ### Example /// /// ```cpp /// auto screen = ScreenInteractive::TerminalOutput(); /// auto renderer = Renderer([] (bool focused) { /// if (focused) /// return text("My interface") | inverted; /// else /// return text("My interface"); /// }); /// screen.Loop(renderer); /// ``` Component Renderer(std::function render) { class Impl : public ComponentBase { public: Impl(std::function render) : render_(std::move(render)) {} private: Element Render() override { return render_(Focused()) | reflect(box_); } bool Focusable() const override { return true; } bool OnEvent(Event event) override { if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) { if (!CaptureMouse(event)) return false; TakeFocus(); } return false; } Box box_; std::function render_; }; return Make(std::move(render)); } /// @brief Decorate a component, by decorating what it renders. /// @param decorator the function modifying the element it renders. /// @ingroup component /// /// ### Example /// /// ```cpp /// auto screen = ScreenInteractive::TerminalOutput(); /// auto renderer = // Renderer([] { return text("Hello");) /// | Renderer(bold) /// | Renderer(inverted); /// screen.Loop(renderer); /// ``` ComponentDecorator Renderer(ElementDecorator decorator) { return [decorator](Component component) { return Renderer(component, [component, decorator] { return component->Render() | decorator; }); }; } } // 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.