FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/dom/table.cpp
Go to the documentation of this file.
1// Copyright 2021 Arthur Sonzogni. Todos los derechos reservados.
2// El uso de este código fuente se rige por la licencia MIT que se puede encontrar en
3// el archivo LICENSE.
4#include "ftxui/dom/table.hpp"
5
6#include <algorithm> // for max
7#include <initializer_list> // for initializer_list
8#include <memory> // for allocator, shared_ptr, allocator_traits<>::value_type
9#include <utility> // for move, swap
10#include <vector> // for vector
11
12#include "ftxui/dom/elements.hpp" // for Element, operator|, text, separatorCharacter, Elements, BorderStyle, Decorator, emptyElement, size, gridbox, EQUAL, flex, flex_shrink, HEIGHT, WIDTH
13
14namespace ftxui {
15namespace {
16
17bool IsCell(int x, int y) {
18 return x % 2 == 1 && y % 2 == 1;
19}
20
21// NOLINTNEXTLINE
22static std::string charset[6][6] = {
23 {"┌", "┐", "└", "┘", "─", "│"}, // LIGERO
24 {"┏", "┓", "┗", "┛", "╍", "╏"}, // DISCONTINUO
25 {"┏", "┓", "┗", "┛", "━", "┃"}, // GRUESO
26 {"╔", "╗", "╚", "╝", "═", "║"}, // DOBLE
27 {"╭", "╮", "╰", "╯", "─", "│"}, // REDONDEADO
28 {" ", " ", " ", " ", " ", " "}, // VACÍO
29};
30
31int Wrap(int input, int modulo) {
32 input %= modulo;
33 input += modulo;
34 input %= modulo;
35 return input;
36}
37
38void Order(int& a, int& b) {
39 if (a >= b) {
40 std::swap(a, b);
41 }
42}
43
44} // namespace
45
46/// @brief Crea una tabla vacía.
48 Initialize({});
49}
50
51/// @brief Crea una tabla a partir de un vector de vectores de cadenas.
52/// @param input Los datos de entrada.
53Table::Table(std::vector<std::vector<std::string>> input) {
54 std::vector<std::vector<Element>> output;
55 output.reserve(input.size());
56 for (auto& row : input) {
57 output.emplace_back();
58 auto& output_row = output.back();
59 output_row.reserve(row.size());
60 for (auto& cell : row) {
61 output_row.push_back(text(std::move(cell)));
62 }
63 }
64 Initialize(std::move(output));
65}
66
67/// @brief Crea una tabla a partir de un vector de vectores de Element.
68/// @param input Los elementos de entrada.
69Table::Table(std::vector<std::vector<Element>> input) {
70 Initialize(std::move(input));
71}
72
73// @brief Crea una tabla a partir de una lista de listas de cadenas.
74// @param init Los datos de entrada.
75Table::Table(std::initializer_list<std::vector<std::string>> init) {
76 std::vector<std::vector<Element>> input;
77 for (const auto& row : init) {
78 std::vector<Element> output_row;
79 output_row.reserve(row.size());
80 for (const auto& cell : row) {
81 output_row.push_back(text(cell));
82 }
83 input.push_back(std::move(output_row));
84 }
85 Initialize(std::move(input));
86}
87
88// private
89void Table::Initialize(std::vector<std::vector<Element>> input) {
90 input_dim_y_ = static_cast<int>(input.size());
91 input_dim_x_ = 0;
92 for (auto& row : input) {
93 input_dim_x_ = std::max(input_dim_x_, int(row.size()));
94 }
95
96 dim_y_ = 2 * input_dim_y_ + 1;
97 dim_x_ = 2 * input_dim_x_ + 1;
98
99 // Reserve space.
100 elements_.resize(dim_y_);
101 for (int y = 0; y < dim_y_; ++y) {
102 elements_[y].resize(dim_x_);
103 }
104
105 // Transfert elements_ from |input| toward |elements_|.
106 {
107 int y = 1;
108 for (auto& row : input) {
109 int x = 1;
110 for (auto& cell : row) {
111 elements_[y][x] = std::move(cell);
112 x += 2;
113 }
114 y += 2;
115 }
116 }
117
118 // Add empty element for the border.
119 for (int y = 0; y < dim_y_; ++y) {
120 for (int x = 0; x < dim_x_; ++x) {
121 auto& element = elements_[y][x];
122
123 if (IsCell(x, y)) {
124 if (!element) {
125 element = emptyElement();
126 }
127 continue;
128 }
129
130 element = emptyElement();
131 }
132 }
133}
134
135/// @brief Selecciona una fila de la tabla.
136/// @param index El índice de la fila a seleccionar.
137/// @note Puedes usar índices negativos para seleccionar desde el final.
139 return SelectRectangle(0, -1, index, index);
140}
141
142/// @brief Selecciona un rango de filas de la tabla.
143/// @param row_min La primera fila a seleccionar.
144/// @param row_max La última fila a seleccionar.
145/// @note Puedes usar índices negativos para seleccionar desde el final.
146TableSelection Table::SelectRows(int row_min, int row_max) {
147 return SelectRectangle(0, -1, row_min, row_max);
148}
149
150/// @brief Selecciona una columna de la tabla.
151/// @param index El índice de la columna a seleccionar.
152/// @note Puedes usar índices negativos para seleccionar desde el final.
154 return SelectRectangle(index, index, 0, -1);
155}
156
157/// @brief Selecciona un rango de columnas de la tabla.
158/// @param column_min La primera columna a seleccionar.
159/// @param column_max La última columna a seleccionar.
160/// @note Puedes usar índices negativos para seleccionar desde el final.
161TableSelection Table::SelectColumns(int column_min, int column_max) {
162 return SelectRectangle(column_min, column_max, 0, -1);
163}
164
165/// @brief Selecciona una celda de la tabla.
166/// @param column La columna de la celda a seleccionar.
167/// @param row La fila de la celda a seleccionar.
168/// @note Puedes usar índices negativos para seleccionar desde el final.
169TableSelection Table::SelectCell(int column, int row) {
170 return SelectRectangle(column, column, row, row);
171}
172
173/// @brief Selecciona un rectángulo de la tabla.
174/// @param column_min La primera columna a seleccionar.
175/// @param column_max La última columna a seleccionar.
176/// @param row_min La primera fila a seleccionar.
177/// @param row_max La última fila a seleccionar.
178/// @note Puedes usar índices negativos para seleccionar desde el final.
180 int column_max,
181 int row_min,
182 int row_max) {
183 column_min = Wrap(column_min, input_dim_x_);
184 column_max = Wrap(column_max, input_dim_x_);
185 Order(column_min, column_max);
186 row_min = Wrap(row_min, input_dim_y_);
187 row_max = Wrap(row_max, input_dim_y_);
188 Order(row_min, row_max);
189
190 TableSelection output; // NOLINT
191 output.table_ = this;
192 output.x_min_ = 2 * column_min;
193 output.x_max_ = 2 * column_max + 2;
194 output.y_min_ = 2 * row_min;
195 output.y_max_ = 2 * row_max + 2;
196 return output;
197}
198
199/// @brief Selecciona toda la tabla.
201 TableSelection output; // NOLINT
202 output.table_ = this;
203 output.x_min_ = 0;
204 output.x_max_ = dim_x_ - 1;
205 output.y_min_ = 0;
206 output.y_max_ = dim_y_ - 1;
207 return output;
208}
209
210/// @brief Renderiza la tabla.
211/// @return La tabla renderizada. Este es un elemento que puedes dibujar.
213 for (int y = 0; y < dim_y_; ++y) {
214 for (int x = 0; x < dim_x_; ++x) {
215 auto& it = elements_[y][x];
216
217 // Línea
218 if ((x + y) % 2 == 1) {
219 it = std::move(it) | flex;
220 continue;
221 }
222
223 // Celdas
224 if ((x % 2) == 1 && (y % 2) == 1) {
225 it = std::move(it) | flex_shrink;
226 continue;
227 }
228
229 // Esquinas
230 it = std::move(it) | size(WIDTH, EQUAL, 0) | size(HEIGHT, EQUAL, 0);
231 }
232 }
233 dim_x_ = 0;
234 dim_y_ = 0;
235 return gridbox(std::move(elements_));
236}
237
238/// @brief Aplica el `decorator` a la selección.
239/// Esto decora tanto las celdas, las líneas y las esquinas.
240/// @param decorator El decorador a aplicar.
241// NOLINTNEXTLINE
243 for (int y = y_min_; y <= y_max_; ++y) {
244 for (int x = x_min_; x <= x_max_; ++x) {
245 Element& e = table_->elements_[y][x];
246 e = std::move(e) | decorator;
247 }
248 }
249}
250
251/// @brief Aplica el `decorator` a la selección.
252/// @param decorator El decorador a aplicar.
253/// Esto decora solo las celdas.
254// NOLINTNEXTLINE
256 for (int y = y_min_; y <= y_max_; ++y) {
257 for (int x = x_min_; x <= x_max_; ++x) {
258 if (y % 2 == 1 && x % 2 == 1) {
259 Element& e = table_->elements_[y][x];
260 e = std::move(e) | decorator;
261 }
262 }
263 }
264}
265
266/// @brief Aplica el `decorator` a la selección.
267/// Esto decora solo las líneas módulo `modulo` con un desplazamiento de `shift`.
268/// @param decorator El decorador a aplicar.
269/// @param modulo El módulo de las líneas a decorar.
270/// @param shift El desplazamiento de las líneas a decorar.
271// NOLINTNEXTLINE
273 int modulo,
274 int shift) {
275 for (int y = y_min_; y <= y_max_; ++y) {
276 for (int x = x_min_; x <= x_max_; ++x) {
277 if (y % 2 == 1 && (x / 2) % modulo == shift) {
278 Element& e = table_->elements_[y][x];
279 e = std::move(e) | decorator;
280 }
281 }
282 }
283}
284
285/// @brief Aplica el `decorator` a la selección.
286/// Esto decora solo las líneas módulo `modulo` con un desplazamiento de `shift`.
287/// @param decorator El decorador a aplicar.
288/// @param modulo El módulo de las líneas a decorar.
289/// @param shift El desplazamiento de las líneas a decorar.
290// NOLINTNEXTLINE
292 int modulo,
293 int shift) {
294 for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
295 for (int x = x_min_; x <= x_max_; ++x) {
296 if (y % 2 == 1 && (y / 2) % modulo == shift) {
297 Element& e = table_->elements_[y][x];
298 e = std::move(e) | decorator;
299 }
300 }
301 }
302}
303
304/// @brief Aplica el `decorator` a la selección.
305/// Esto decora solo las esquinas módulo `modulo` con un desplazamiento de `shift` por celdas.
306/// @param decorator El decorador a aplicar.
307/// @param modulo El módulo de las celdas a decorar.
308/// @param shift El desplazamiento de las celdas a decorar.
309// NOLINTNEXTLINE
311 int modulo,
312 int shift) {
313 for (int y = y_min_; y <= y_max_; ++y) {
314 for (int x = x_min_; x <= x_max_; ++x) {
315 if (y % 2 == 1 && x % 2 == 1 && ((x / 2) % modulo == shift)) {
316 Element& e = table_->elements_[y][x];
317 e = std::move(e) | decorator;
318 }
319 }
320 }
321}
322
323/// @brief Aplica el `decorator` a la selección.
324/// Esto decora solo las esquinas módulo `modulo` con un desplazamiento de `shift` por celdas.
325/// @param decorator El decorador a aplicar.
326/// @param modulo El módulo de las celdas a decorar.
327/// @param shift El desplazamiento de las celdas a decorar.
328// NOLINTNEXTLINE
330 int modulo,
331 int shift) {
332 for (int y = y_min_; y <= y_max_; ++y) {
333 for (int x = x_min_; x <= x_max_; ++x) {
334 if (y % 2 == 1 && x % 2 == 1 && ((y / 2) % modulo == shift)) {
335 Element& e = table_->elements_[y][x];
336 e = std::move(e) | decorator;
337 }
338 }
339 }
340}
341
342/// @brief Aplica un `border` alrededor de la selección.
343/// @param border El estilo de borde a aplicar.
345 BorderLeft(border);
346 BorderRight(border);
347 BorderTop(border);
348 BorderBottom(border);
349
350 // NOLINTNEXTLINE
351 table_->elements_[y_min_][x_min_] = text(charset[border][0]) | automerge;
352 // NOLINTNEXTLINE
353 table_->elements_[y_min_][x_max_] = text(charset[border][1]) | automerge;
354 // NOLINTNEXTLINE
355 table_->elements_[y_max_][x_min_] = text(charset[border][2]) | automerge;
356 // NOLINTNEXTLINE
357 table_->elements_[y_max_][x_max_] = text(charset[border][3]) | automerge;
358}
359
360/// @brief Dibuja algunas líneas separadoras en la selección.
361/// @param border El estilo de borde a aplicar.
363 for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
364 for (int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
365 if (y % 2 == 0 || x % 2 == 0) {
366 Element& e = table_->elements_[y][x];
367 e = (y % 2 == 1)
368 ? separatorCharacter(charset[border][5]) | automerge // NOLINT
369 : separatorCharacter(charset[border][4]) | automerge; // NOLINT
370 }
371 }
372 }
373}
374
375/// @brief Dibuja algunas líneas separadoras verticales en la selección.
376/// @param border El estilo de borde a aplicar.
378 for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
379 for (int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
380 if (x % 2 == 0) {
381 table_->elements_[y][x] =
382 separatorCharacter(charset[border][5]) | automerge; // NOLINT
383 }
384 }
385 }
386}
387
388/// @brief Dibuja algunas líneas separadoras horizontales en la selección.
389/// @param border El estilo de borde a aplicar.
391 for (int y = y_min_ + 1; y <= y_max_ - 1; ++y) {
392 for (int x = x_min_ + 1; x <= x_max_ - 1; ++x) {
393 if (y % 2 == 0) {
394 table_->elements_[y][x] =
395 separatorCharacter(charset[border][4]) | automerge; // NOLINT
396 }
397 }
398 }
399}
400
401/// @brief Dibuja algunas líneas separadoras en el lado izquierdo de la selección.
402/// @param border El estilo de borde a aplicar.
404 for (int y = y_min_; y <= y_max_; y++) {
405 table_->elements_[y][x_min_] =
406 separatorCharacter(charset[border][5]) | automerge; // NOLINT
407 }
408}
409
410/// @brief Dibuja algunas líneas separadoras en el lado derecho de la selección.
411/// @param border El estilo de borde a aplicar.
413 for (int y = y_min_; y <= y_max_; y++) {
414 table_->elements_[y][x_max_] =
415 separatorCharacter(charset[border][5]) | automerge; // NOLINT
416 }
417}
418
419/// @brief Dibuja algunas líneas separadoras en la parte superior de la selección.
420/// @param border El estilo de borde a aplicar.
422 for (int x = x_min_; x <= x_max_; x++) {
423 table_->elements_[y_min_][x] =
424 separatorCharacter(charset[border][4]) | automerge; // NOLINT
425 }
426}
427
428/// @brief Dibuja algunas líneas separadoras en la parte inferior de la selección.
429/// @param border El estilo de borde a aplicar.
431 for (int x = x_min_; x <= x_max_; x++) {
432 table_->elements_[y_max_][x] =
433 separatorCharacter(charset[border][4]) | automerge; // NOLINT
434 }
435}
436
437} // namespace ftxui
void DecorateAlternateColumn(Decorator, int modulo=2, int shift=0)
Aplica el decorator a la selección. Esto decora solo las líneas módulo modulo con un desplazamiento d...
void SeparatorVertical(BorderStyle border=LIGHT)
Dibuja algunas líneas separadoras verticales en la selección.
void DecorateCells(Decorator)
Aplica el decorator a la selección.
void BorderLeft(BorderStyle border=LIGHT)
Dibuja algunas líneas separadoras en el lado izquierdo de la selección.
void DecorateCellsAlternateColumn(Decorator, int modulo=2, int shift=0)
Aplica el decorator a la selección. Esto decora solo las esquinas módulo modulo con un desplazamiento...
void Decorate(Decorator)
Aplica el decorator a la selección. Esto decora tanto las celdas, las líneas y las esquinas.
void DecorateAlternateRow(Decorator, int modulo=2, int shift=0)
Aplica el decorator a la selección. Esto decora solo las líneas módulo modulo con un desplazamiento d...
void BorderTop(BorderStyle border=LIGHT)
Dibuja algunas líneas separadoras en la parte superior de la selección.
void Separator(BorderStyle border=LIGHT)
Dibuja algunas líneas separadoras en la selección.
void BorderBottom(BorderStyle border=LIGHT)
Dibuja algunas líneas separadoras en la parte inferior de la selección.
void DecorateCellsAlternateRow(Decorator, int modulo=2, int shift=0)
Aplica el decorator a la selección. Esto decora solo las esquinas módulo modulo con un desplazamiento...
void BorderRight(BorderStyle border=LIGHT)
Dibuja algunas líneas separadoras en el lado derecho de la selección.
void Border(BorderStyle border=LIGHT)
Aplica un border alrededor de la selección.
void SeparatorHorizontal(BorderStyle border=LIGHT)
Dibuja algunas líneas separadoras horizontales en la selección.
Component Wrap(std::string name, Component component)
Definition gallery.cpp:18
Element Render()
Renderiza la tabla.
Table()
Crea una tabla vacía.
TableSelection SelectCell(int column, int row)
Selecciona una celda de la tabla.
TableSelection SelectColumn(int column_index)
Selecciona una columna de la tabla.
TableSelection SelectRow(int row_index)
Selecciona una fila de la tabla.
TableSelection SelectColumns(int column_min, int column_max)
Selecciona un rango de columnas de la tabla.
TableSelection SelectRows(int row_min, int row_max)
Selecciona un rango de filas de la tabla.
TableSelection SelectAll()
Selecciona toda la tabla.
TableSelection SelectRectangle(int column_min, int column_max, int row_min, int row_max)
Selecciona un rectángulo de la tabla.
Decorator size(WidthOrHeight, Constraint, int value)
Aplica una restricción al tamaño de un elemento.
Element flex(Element)
Hace que un elemento hijo se expanda proporcionalmente al espacio restante en un contenedor.
Definition flex.cpp:123
Element emptyElement()
Definition dom/util.cpp:140
Element flex_shrink(Element)
Minimizar si es necesario.
Definition flex.cpp:159
Element text(std::wstring text)
Muestra un fragmento de texto Unicode.
Definition text.cpp:160
Element separatorCharacter(std::string)
Dibuja una separación vertical u horizontal entre otros dos elementos.
Element automerge(Element child)
Permite que los caracteres se fusionen automáticamente con otros cercanos.
Definition automerge.cpp:17
BorderStyle
BorderStyle es una enumeración que representa los diferentes estilos de bordes que se pueden aplicar ...
Definition elements.hpp:35
El espacio de nombres ftxui:: de FTXUI.
Definition animation.hpp:10
std::function< Element(Element)> Decorator
Definition elements.hpp:24
std::shared_ptr< Node > Element
Definition elements.hpp:22
Element gridbox(std::vector< Elements > lines)
Un contenedor que muestra una cuadrícula de elementos.