FTXUI  5.0.0
C++ functional terminal UI.
renderer.cpp
Go to the documentation of this file.
1 // Copyright 2021 Arthur Sonzogni. All rights reserved.
2 // Use of this source code is governed by the MIT license that can be found in
3 // the LICENSE file.
4 #include <functional> // for function
5 #include <memory> // for __shared_ptr_access, shared_ptr
6 #include <utility> // for move
7 
8 #include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
9 #include "ftxui/component/component.hpp" // for Make, Renderer
10 #include "ftxui/component/component_base.hpp" // for Component, ComponentBase
11 #include "ftxui/component/event.hpp" // for Event
12 #include "ftxui/component/mouse.hpp" // for Mouse
13 #include "ftxui/dom/elements.hpp" // for Element, operator|, reflect
14 #include "ftxui/screen/box.hpp" // for Box
15 
16 namespace ftxui {
17 
18 /// @brief Return a component, using |render| to render its interface.
19 /// @param render The function drawing the interface.
20 /// @ingroup component
21 ///
22 /// ### Example
23 ///
24 /// ```cpp
25 /// auto screen = ScreenInteractive::TerminalOutput();
26 /// auto renderer = Renderer([] {
27 /// return text("My interface");
28 /// });
29 /// screen.Loop(renderer);
30 /// ```
31 Component Renderer(std::function<Element()> render) {
32  class Impl : public ComponentBase {
33  public:
34  explicit Impl(std::function<Element()> render)
35  : render_(std::move(render)) {}
36  Element Render() override { return render_(); }
37  std::function<Element()> render_;
38  };
39 
40  return Make<Impl>(std::move(render));
41 }
42 
43 /// @brief Return a new Component, similar to |child|, but using |render| as the
44 /// Component::Render() event.
45 /// @param child The component to forward events to.
46 /// @param render The function drawing the interface.
47 /// @ingroup component
48 ///
49 /// ### Example
50 ///
51 /// ```cpp
52 /// auto screen = ScreenInteractive::TerminalOutput();
53 /// std::string label = "Click to quit";
54 /// auto button = Button(&label, screen.ExitLoopClosure());
55 /// auto renderer = Renderer(button, [&] {
56 /// return hbox({
57 /// text("A button:"),
58 /// button->Render(),
59 /// });
60 /// });
61 /// screen.Loop(renderer);
62 /// ```
63 Component Renderer(Component child, std::function<Element()> render) {
64  Component renderer = Renderer(std::move(render));
65  renderer->Add(std::move(child));
66  return renderer;
67 }
68 
69 /// @brief Return a focusable component, using |render| to render its interface.
70 /// @param render The function drawing the interface, taking a boolean telling
71 /// whether the component is focused or not.
72 /// @ingroup component
73 ///
74 /// ### Example
75 ///
76 /// ```cpp
77 /// auto screen = ScreenInteractive::TerminalOutput();
78 /// auto renderer = Renderer([] (bool focused) {
79 /// if (focused)
80 /// return text("My interface") | inverted;
81 /// else
82 /// return text("My interface");
83 /// });
84 /// screen.Loop(renderer);
85 /// ```
86 Component Renderer(std::function<Element(bool)> render) {
87  class Impl : public ComponentBase {
88  public:
89  explicit Impl(std::function<Element(bool)> render)
90  : render_(std::move(render)) {}
91 
92  private:
93  Element Render() override { return render_(Focused()) | reflect(box_); }
94  bool Focusable() const override { return true; }
95  bool OnEvent(Event event) override {
96  if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) {
97  if (!CaptureMouse(event)) {
98  return false;
99  }
100 
101  TakeFocus();
102  }
103 
104  return false;
105  }
106  Box box_;
107 
108  std::function<Element(bool)> render_;
109  };
110  return Make<Impl>(std::move(render));
111 }
112 
113 /// @brief Decorate a component, by decorating what it renders.
114 /// @param decorator the function modifying the element it renders.
115 /// @ingroup component
116 ///
117 /// ### Example
118 ///
119 /// ```cpp
120 /// auto screen = ScreenInteractive::TerminalOutput();
121 /// auto renderer =
122 // Renderer([] { return text("Hello");)
123 /// | Renderer(bold)
124 /// | Renderer(inverted);
125 /// screen.Loop(renderer);
126 /// ```
128  return [decorator](Component component) { // NOLINT
129  return Renderer(component, [component, decorator] {
130  return component->Render() | decorator;
131  });
132  };
133 }
134 
135 } // namespace ftxui
It implement rendering itself as ftxui::Element. It implement keyboard navigation by responding to ft...
std::shared_ptr< Node > Element
Definition: elements.hpp:23
std::function< Element(Element)> ElementDecorator
Definition: component.hpp:34
std::shared_ptr< ComponentBase > Component
Component Renderer(Component child, std::function< Element()>)
Return a new Component, similar to |child|, but using |render| as the Component::Render() event.
Definition: renderer.cpp:63
Decorator reflect(Box &box)
Definition: reflect.cpp:44
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Definition: node.cpp:47
std::function< Component(Component)> ComponentDecorator
Definition: component.hpp:33
Represent an event. It can be key press event, a terminal resize, or more ...
Definition: event.hpp:29
bool is_mouse() const
Definition: event.hpp:78
struct Mouse & mouse()
Definition: event.hpp:79