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