FTXUI  5.0.0
C++ functional terminal UI.
util.cpp
Go to the documentation of this file.
1 // Copyright 2020 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 <algorithm> // for min
5 #include <functional> // for function
6 #include <memory> // for __shared_ptr_access, make_unique
7 #include <utility> // for move
8 
9 #include "ftxui/dom/elements.hpp" // for Element, Decorator, Elements, operator|, Fit, emptyElement, nothing, operator|=
10 #include "ftxui/dom/node.hpp" // for Node, Node::Status
11 #include "ftxui/dom/requirement.hpp" // for Requirement
12 #include "ftxui/screen/box.hpp" // for Box
13 #include "ftxui/screen/screen.hpp" // for Full
14 #include "ftxui/screen/terminal.hpp" // for Dimensions
15 
16 namespace ftxui {
17 
18 namespace {
19 Decorator compose(Decorator a, Decorator b) {
20  return [a = std::move(a), b = std::move(b)](Element element) {
21  return b(a(std::move(element)));
22  };
23 }
24 } // namespace
25 
26 /// @brief A decoration doing absolutely nothing.
27 /// @ingroup dom
29  return element;
30 }
31 
32 /// @brief Compose two decorator into one.
33 /// @ingroup dom
34 ///
35 /// ### Example
36 ///
37 /// ```cpp
38 /// auto decorator = bold | blink;
39 /// ```
41  return compose(std::move(a), //
42  std::move(b));
43 }
44 
45 /// @brief From a set of element, apply a decorator to every elements.
46 /// @return the set of decorated element.
47 /// @ingroup dom
48 Elements operator|(Elements elements, Decorator decorator) { // NOLINT
49  Elements output;
50  output.reserve(elements.size());
51  for (auto& it : elements) {
52  output.push_back(std::move(it) | decorator);
53  }
54  return output;
55 }
56 
57 /// @brief From an element, apply a decorator.
58 /// @return the decorated element.
59 /// @ingroup dom
60 ///
61 /// ### Example
62 ///
63 /// Both of these are equivalent:
64 /// ```cpp
65 /// bold(text("Hello"));
66 /// ```
67 /// ```cpp
68 /// text("Hello") | bold;
69 /// ```
70 Element operator|(Element element, Decorator decorator) { // NOLINT
71  return decorator(std::move(element));
72 }
73 
74 /// @brief Apply a decorator to an element.
75 /// @return the decorated element.
76 /// @ingroup dom
77 ///
78 /// ### Example
79 ///
80 /// Both of these are equivalent:
81 /// ```cpp
82 /// auto element = text("Hello");
83 /// element |= bold;
84 /// ```
86  e = e | std::move(d);
87  return e;
88 }
89 
90 /// The minimal dimension that will fit the given element.
91 /// @see Fixed
92 /// @see Full
93 Dimensions Dimension::Fit(Element& e, bool extend_beyond_screen) {
94  const Dimensions fullsize = Dimension::Full();
95  Box box;
96  box.x_min = 0;
97  box.y_min = 0;
98  box.x_max = fullsize.dimx;
99  box.y_max = fullsize.dimy;
100 
101  Node::Status status;
102  e->Check(&status);
103  const int max_iteration = 20;
104  while (status.need_iteration && status.iteration < max_iteration) {
105  e->ComputeRequirement();
106 
107  // Don't give the element more space than it needs:
108  box.x_max = std::min(box.x_max, e->requirement().min_x);
109  box.y_max = e->requirement().min_y;
110  if (!extend_beyond_screen) {
111  box.y_max = std::min(box.y_max, fullsize.dimy);
112  }
113 
114  e->SetBox(box);
115  status.need_iteration = false;
116  status.iteration++;
117  e->Check(&status);
118 
119  if (!status.need_iteration) {
120  break;
121  }
122  // Increase the size of the box until it fits...
123  box.x_max = std::min(e->requirement().min_x, fullsize.dimx);
124  box.y_max = e->requirement().min_y;
125 
126  // ... but don't go beyond the screen size:
127  if (!extend_beyond_screen) {
128  box.y_max = std::min(box.y_max, fullsize.dimy);
129  }
130  }
131 
132  return {
133  box.x_max,
134  box.y_max,
135  };
136 }
137 
138 /// An element of size 0x0 drawing nothing.
139 /// @ingroup dom
141  class Impl : public Node {
142  void ComputeRequirement() override {
143  requirement_.min_x = 0;
144  requirement_.min_y = 0;
145  }
146  };
147  return std::make_unique<Impl>();
148 }
149 
150 } // namespace ftxui
bool need_iteration
Definition: node.hpp:51
Dimensions Fit(Element &, bool extend_beyond_screen=false)
Definition: util.cpp:93
Dimensions Full()
Definition: screen.cpp:376
std::function< Element(Element)> Decorator
Definition: elements.hpp:24
Element nothing(Element element)
A decoration doing absolutely nothing.
Definition: util.cpp:28
std::shared_ptr< Node > Element
Definition: elements.hpp:22
Element emptyElement()
Definition: util.cpp:140
Component operator|(Component component, ComponentDecorator decorator)
Definition: util.cpp:12
std::vector< Element > Elements
Definition: elements.hpp:23
Component & operator|=(Component &component, ComponentDecorator decorator)
Definition: util.cpp:22
int x_max
Definition: box.hpp:11
int y_min
Definition: box.hpp:12
int y_max
Definition: box.hpp:13
int x_min
Definition: box.hpp:10