FTXUI 7.0.3
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/dom/gauge.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 <ftxui/dom/direction.hpp> // for Direction, Direction::Down, Direction::Left, Direction::Right, Direction::Up
5#include <memory> // for allocator, make_shared
6#include <string> // for string
7
8#include "ftxui/dom/elements.hpp" // for Element, gauge, gaugeDirection, gaugeDown, gaugeLeft, gaugeRight, gaugeUp
9#include "ftxui/dom/node.hpp" // for Node
10#include "ftxui/dom/requirement.hpp" // for Requirement
11#include "ftxui/screen/box.hpp" // for Box
12#include "ftxui/screen/screen.hpp" // for Screen, Cell
13
14#include "ftxui/screen/terminal.hpp" // for Quirks, GetQuirks
15
16namespace ftxui {
17
18namespace {
19// NOLINTNEXTLINE
20static const std::string charset_horizontal[11] = {
21 " ", " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█",
22 // Un carácter extra en caso de que el fuzzer consiga tener:
23 // int(9 * (limite - limite_int)) = 9
24 "█"};
25
26// NOLINTNEXTLINE
27static const std::string charset_horizontal_microsoft[11] = {
28 " ", " ", " ", " ", "▌", "▌", "▌", "█", "█", "█",
29 // Un carácter extra en caso de que el fuzzer consiga tener:
30 // int(9 * (limite - limite_int)) = 9
31 "█"};
32
33// NOLINTNEXTLINE
34static const std::string charset_vertical[10] = {
35 "█",
36 "▇",
37 "▆",
38 "▅",
39 "▄",
40 "▃",
41 "▂",
42 "▁",
43 " ",
44 // Un carácter extra en caso de que el fuzzer consiga tener:
45 // int(8 * (limite - limite_int)) = 8
46 " ",
47};
48
49class Gauge : public Node {
50 public:
51 Gauge(float progress, Direction direction, std::vector<std::string> charset = {})
52 : progress_(progress),
53 direction_(direction),
54 charset_(std::move(charset)) {
55 // Esto maneja NAN correctamente:
56 if (!(progress_ > 0.F)) {
57 progress_ = 0.F;
58 }
59 if (!(progress_ < 1.F)) {
60 progress_ = 1.F;
61 }
62 }
63
64 void ComputeRequirement() override {
65 switch (direction_) {
67 case Direction::Left:
68 requirement_.flex_grow_x = 1;
69 requirement_.flex_grow_y = 0;
70 requirement_.flex_shrink_x = 1;
71 requirement_.flex_shrink_y = 0;
72 break;
73 case Direction::Up:
74 case Direction::Down:
75 requirement_.flex_grow_x = 0;
76 requirement_.flex_grow_y = 1;
77 requirement_.flex_shrink_x = 0;
78 requirement_.flex_shrink_y = 1;
79 break;
80 }
81 requirement_.min_x = 1;
82 requirement_.min_y = 1;
83 }
84
85 void Render(Screen& screen) override {
86 switch (direction_) {
88 RenderHorizontal(screen, /*invert=*/false);
89 break;
90 case Direction::Up:
91 RenderVertical(screen, /*invert=*/false);
92 break;
93 case Direction::Left:
94 RenderHorizontal(screen, /*invert=*/true);
95 break;
96 case Direction::Down:
97 RenderVertical(screen, /*invert=*/true);
98 break;
99 }
100 }
101
102 void RenderHorizontal(Screen& screen, bool invert) {
103 if (box_.y_min > box_.y_max) {
104 return;
105 }
106
107 // `full` es el índice del glifo "lleno" en `charset`; la celda de
108 // frontera elige el índice del glifo int(full * fractional_fill).
109 const std::string* charset;
110 int full;
111 if (charset_.empty()) {
112 charset = Terminal::GetQuirks().BlockCharacters() // NOLINT
113 ? charset_horizontal
114 : charset_horizontal_microsoft;
115 full = 9;
116 } else {
117 charset = charset_.data();
118 full = static_cast<int>(charset_.size()) - 1;
119 }
120
121 // Dibujar la barra de progreso horizontalmente en toda la altura asignada:
122 const float progress = invert ? 1.F - progress_ : progress_;
123 const auto limit =
124 float(box_.x_min) + progress * float(box_.x_max - box_.x_min + 1);
125 const int limit_int = static_cast<int>(limit);
126
127 for (int y = box_.y_min; y <= box_.y_max; y++) {
128 int x = box_.x_min;
129 while (x < limit_int) {
130 screen.at(x++, y) = charset[full];
131 }
132 if (x <= box_.x_max) {
133 screen.at(x++, y) = charset[int(full * (limit - limit_int))];
134 }
135 while (x <= box_.x_max) {
136 screen.at(x++, y) = charset[0];
137 }
138 }
139
140 if (invert) {
141 Invert(screen);
142 }
143 }
144
145 void RenderVertical(Screen& screen, bool invert) {
146 if (box_.x_min > box_.x_max) {
147 return;
148 }
149
150 const std::string* charset;
151 int full;
152 if (charset_.empty()) {
153 charset = charset_vertical;
154 full = 8;
155 } else {
156 charset = charset_.data();
157 full = static_cast<int>(charset_.size()) - 1;
158 }
159
160 // Dibujar la barra de progreso verticalmente en todo el ancho asignado:
161 const float progress = invert ? progress_ : 1.F - progress_;
162 const float limit =
163 float(box_.y_min) + progress * float(box_.y_max - box_.y_min + 1);
164 const int limit_int = static_cast<int>(limit);
165
166 for (int x = box_.x_min; x <= box_.x_max; x++) {
167 int y = box_.y_min;
168 while (y < limit_int) {
169 screen.at(x, y++) = charset[full];
170 }
171 if (y <= box_.y_max) {
172 screen.at(x, y++) = charset[int(full * (limit - limit_int))];
173 }
174 while (y <= box_.y_max) {
175 screen.at(x, y++) = charset[0];
176 }
177 }
178 if (invert) {
179 Invert(screen);
180 }
181 }
182
183 void Invert(Screen& screen) {
184 for (int y = box_.y_min; y <= box_.y_max; y++) {
185 for (int x = box_.x_min; x <= box_.x_max; x++) {
186 screen.CellAt(x, y).inverted ^= true;
187 }
188 }
189 }
190
191 private:
192 float progress_;
193 Direction direction_;
194 std::vector<std::string> charset_;
195};
196
197} // namespace
198
199/// @brief Dibuja una barra de progreso de alta definición que avanza en la dirección especificada.
200/// @param progress La proporción del área a rellenar. Pertenece a [0,1].
201/// @param direction Dirección de progresión de la barra de progreso.
202/// @ingroup dom
204 return std::make_shared<Gauge>(progress, direction);
205}
206
207/// @brief Dibuja una barra de progreso de alta definición que avanza de izquierda a derecha.
208/// @param progress La proporción del área a rellenar. Pertenece a [0,1].
209/// @ingroup dom
210///
211/// ### Ejemplo
212///
213/// Un medidor. Puede ser usado para representar una barra de progreso.
214/// ~~~cpp
215/// border(gaugeRight(0.5))
216/// ~~~
217///
218/// #### Output
219///
220/// ~~~bash
221/// ┌──────────────────────────────────────────────────────────────────────────┐
222/// │█████████████████████████████████████ │
223/// └──────────────────────────────────────────────────────────────────────────┘
224/// ~~~
225Element gaugeRight(float progress) {
226 return gaugeDirection(progress, Direction::Right);
227}
228
229/// @brief Dibuja una barra de progreso de alta definición que avanza de derecha a izquierda.
230/// @param progress La proporción del área a rellenar. Pertenece a [0,1].
231/// @ingroup dom
232///
233/// ### Ejemplo
234///
235/// Un medidor. Puede ser usado para representar una barra de progreso.
236/// ~~~cpp
237/// border(gaugeLeft(0.5))
238/// ~~~
239///
240/// #### Output
241///
242/// ~~~bash
243/// ┌──────────────────────────────────────────────────────────────────────────┐
244/// │ █████████████████████████████████████│
245/// └──────────────────────────────────────────────────────────────────────────┘
246/// ~~~
247Element gaugeLeft(float progress) {
248 return gaugeDirection(progress, Direction::Left);
249}
250
251/// @brief Dibuja una barra de progreso de alta definición que avanza de abajo hacia arriba.
252/// @param progress La proporción del área a rellenar. Pertenece a [0,1].
253/// @ingroup dom
254///
255/// ### Ejemplo
256///
257/// Un medidor. Puede ser usado para representar una barra de progreso.
258/// ~~~cpp
259/// border(gaugeUp(0.5))
260/// ~~~
261///
262/// #### Output
263///
264/// ~~~bash
265/// ┌─┐
266/// │ │
267/// │ │
268/// │ │
269/// │ │
270/// │█│
271/// │█│
272/// │█│
273/// │█│
274/// └─┘
275/// ~~~
276Element gaugeUp(float progress) {
277 return gaugeDirection(progress, Direction::Up);
278}
279
280/// @brief Dibuja una barra de progreso de alta definición que avanza de arriba hacia abajo.
281/// @param progress La proporción del área a rellenar. Pertenece a [0,1].
282/// @ingroup dom
283///
284/// ### Ejemplo
285///
286/// Un medidor. Puede ser usado para representar una barra de progreso.
287/// ~~~cpp
288/// border(gaugeDown(0.5))
289/// ~~~
290///
291/// #### Output
292///
293/// ~~~bash
294/// ┌─┐
295/// │█│
296/// │█│
297/// │█│
298/// │█│
299/// │ │
300/// │ │
301/// │ │
302/// │ │
303/// └─┘
304/// ~~~
305Element gaugeDown(float progress) {
306 return gaugeDirection(progress, Direction::Down);
307}
308
309/// @brief Dibuja una barra de progreso de alta definición.
310/// @param progress La proporción del área a rellenar. Pertenece a [0,1].
311/// @ingroup dom
312///
313/// ### Ejemplo
314///
315/// Un medidor. Puede ser usado para representar una barra de progreso.
316/// ~~~cpp
317/// border(gauge(0.5))
318/// ~~~
319///
320/// #### Output
321///
322/// ~~~bash
323/// ┌──────────────────────────────────────────────────────────────────────────┐
324/// │█████████████████████████████████████ │
325/// └──────────────────────────────────────────────────────────────────────────┘
326/// ~~~
327Element gauge(float progress) {
328 return gaugeRight(progress);
329}
330
331/// @brief Dibuja una barra de progreso de alta definición usando un conjunto de caracteres personalizado.
332/// @param progress La proporción del área a rellenar. Pertenece a [0,1].
333/// @param charset Glifos desde "vacío" (índice 0) hasta "lleno" (último índice); un
334/// conjunto de 2 entradas da una barra plana sin sombreado.
335/// @param direction Dirección de progresión de las barras de progreso. Por defecto,
336/// Derecha.
337/// @ingroup dom
338///
339/// ### Ejemplo
340///
341/// Una barra de progreso renderizada con un conjunto de caracteres personalizado en lugar de los
342/// caracteres de bloque predeterminados.
343/// ~~~cpp
344/// border(gaugeCharset(0.5, {".", "#"}))
345/// ~~~
346///
347/// #### Salida
348///
349/// ~~~bash
350/// ┌──────────────────────────────────────────────────────────────────────────┐
351/// │#####################################.....................................│
352/// └──────────────────────────────────────────────────────────────────────────┘
353/// ~~~
354Element gaugeCharset(float progress,
355 std::vector<std::string> charset,
357 return std::make_shared<Gauge>(progress, direction, std::move(charset));
358}
359
360} // namespace ftxui
Element gaugeDirection(float progress, Direction direction)
Dibuja una barra de progreso de alta definición que avanza en la dirección especificada.
Element gaugeRight(float progress)
Dibuja una barra de progreso de alta definición que avanza de izquierda a derecha.
Direction
Direction es una enumeración que representa las cuatro cardinales direcciones.
Definition direction.hpp:15
Element gaugeUp(float progress)
Dibuja una barra de progreso de alta definición que avanza de abajo hacia arriba.
Element gaugeCharset(float progress, std::vector< std::string > charset, Direction direction=Direction::Right)
Dibuja una barra de progreso de alta definición usando un conjunto de caracteres personalizado.
Element gaugeLeft(float progress)
Dibuja una barra de progreso de alta definición que avanza de derecha a izquierda.
Element gauge(float progress)
Dibuja una barra de progreso de alta definición.
Element gaugeDown(float progress)
Dibuja una barra de progreso de alta definición que avanza de arriba hacia abajo.
Quirks GetQuirks()
Obtiene las peculiaridades de la terminal.
Definition terminal.cpp:355
El espacio de nombres ftxui:: de FTXUI.
Definition animation.hpp:11
std::shared_ptr< Node > Element
Definition elements.hpp:25
Direction direction
Definition elements.hpp:83
int y
Definition elements.hpp:134
void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:105
const Charset & charset_