FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/dom/border.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// Derechos de autor 2020 Arthur Sonzogni. Todos los derechos reservados.
5// El uso de este código fuente se rige por la licencia MIT que se puede encontrar en
6// el archivo LICENSE.
7#include <algorithm> // for max
8#include <array> // for array
9#include <ftxui/screen/color.hpp> // for Color
10#include <memory> // for allocator, make_shared, __shared_ptr_access
11#include <optional> // for optional, nullopt
12#include <string> // for basic_string, string
13#include <utility> // for move
14
15#include "ftxui/dom/elements.hpp" // for unpack, Element, Decorator, BorderStyle, ROUNDED, borderStyled, Elements, DASHED, DOUBLE, EMPTY, HEAVY, LIGHT, border, borderDashed, borderDouble, borderEmpty, borderHeavy, borderLight, borderRounded, borderWith, window
16#include "ftxui/dom/node.hpp" // for Node, Elements
17#include "ftxui/dom/requirement.hpp" // for Requirement
18#include "ftxui/screen/box.hpp" // for Box
19#include "ftxui/screen/pixel.hpp" // for Pixel
20#include "ftxui/screen/screen.hpp" // for Pixel, Screen
21
22namespace ftxui {
23
24namespace {
25using Charset = std::array<std::string, 6>; // NOLINT
26using Charsets = std::array<Charset, 6>; // NOLINT
27// NOLINTNEXTLINE
28static Charsets simple_border_charset = {
29 Charset{"┌", "┐", "└", "┘", "─", "│"}, // LIGHT
30 Charset{"┏", "┓", "┗", "┛", "╍", "╏"}, // DASHED
31 Charset{"┏", "┓", "┗", "┛", "━", "┃"}, // HEAVY
32 Charset{"╔", "╗", "╚", "╝", "═", "║"}, // DOUBLE
33 Charset{"╭", "╮", "╰", "╯", "─", "│"}, // ROUNDED
34 Charset{" ", " ", " ", " ", " ", " "}, // EMPTY
35};
36
37// For reference, here is the charset for normal border:
38// Para referencia, aquí está el conjunto de caracteres para un borde normal:
39class Border : public Node {
40 public:
41 Border(Elements children,
42 BorderStyle style,
43 std::optional<Color> foreground_color = std::nullopt)
44 : Node(std::move(children)),
45 charset_(simple_border_charset[style]) // NOLINT
46 ,
47 foreground_color_(foreground_color) {} // NOLINT
48
49 const Charset& charset_; // NOLINT
50 std::optional<Color> foreground_color_;
51
52 void ComputeRequirement() override {
54 requirement_ = children_[0]->requirement();
55 requirement_.min_x += 2;
56 requirement_.min_y += 2;
57 if (children_.size() == 2) {
58 requirement_.min_x =
59 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
60 }
61 requirement_.focused.box.x_min++;
62 requirement_.focused.box.x_max++;
63 requirement_.focused.box.y_min++;
64 requirement_.focused.box.y_max++;
65 }
66
67 void SetBox(Box box) override {
68 Node::SetBox(box);
69 if (children_.size() == 2) {
70 Box title_box;
71 title_box.x_min = box.x_min + 1;
72 title_box.x_max = std::min(box.x_max - 1,
73 box.x_min + children_[1]->requirement().min_x);
74 title_box.y_min = box.y_min;
75 title_box.y_max = box.y_min;
76 children_[1]->SetBox(title_box);
77 }
78 box.x_min++;
79 box.x_max--;
80 box.y_min++;
81 box.y_max--;
82 children_[0]->SetBox(box);
83 }
84
85 void Render(Screen& screen) override {
86 // Draw content.
87 // Dibujar contenido.
88 children_[0]->Render(screen);
89
90 // Draw the border.
91 // Dibujar el borde.
92 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
93 return;
94 }
95
96 screen.at(box_.x_min, box_.y_min) = charset_[0]; // NOLINT
97 screen.at(box_.x_max, box_.y_min) = charset_[1]; // NOLINT
98 screen.at(box_.x_min, box_.y_max) = charset_[2]; // NOLINT
99 screen.at(box_.x_max, box_.y_max) = charset_[3]; // NOLINT
100
101 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
102 Pixel& p1 = screen.PixelAt(x, box_.y_min);
103 Pixel& p2 = screen.PixelAt(x, box_.y_max);
104 p1.character = charset_[4]; // NOLINT
105 p2.character = charset_[4]; // NOLINT
106 p1.automerge = true;
107 p2.automerge = true;
108 }
109 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
110 Pixel& p3 = screen.PixelAt(box_.x_min, y);
111 Pixel& p4 = screen.PixelAt(box_.x_max, y);
112 p3.character = charset_[5]; // NOLINT
113 p4.character = charset_[5]; // NOLINT
114 p3.automerge = true;
115 p4.automerge = true;
116 }
117
118 // Draw title.
119 // Dibujar título.
120 if (children_.size() == 2) {
121 children_[1]->Render(screen);
122 }
123
124 // Draw the border color.
125 // Dibujar el color del borde.
126 if (foreground_color_) {
127 for (int x = box_.x_min; x <= box_.x_max; ++x) {
128 screen.PixelAt(x, box_.y_min).foreground_color = *foreground_color_;
129 screen.PixelAt(x, box_.y_max).foreground_color = *foreground_color_;
130 }
131 for (int y = box_.y_min; y <= box_.y_max; ++y) {
132 screen.PixelAt(box_.x_min, y).foreground_color = *foreground_color_;
133 screen.PixelAt(box_.x_max, y).foreground_color = *foreground_color_;
134 }
135 }
136 }
137};
138
139// For reference, here is the charset for normal border:
140// Para referencia, aquí está el conjunto de caracteres para un borde normal:
141class BorderPixel : public Node {
142 public:
143 BorderPixel(Elements children, Pixel pixel)
144 : Node(std::move(children)), pixel_(std::move(pixel)) {}
145
146 private:
147 Pixel pixel_;
148
149 void ComputeRequirement() override {
151 requirement_ = children_[0]->requirement();
152 requirement_.min_x += 2;
153 requirement_.min_y += 2;
154 if (children_.size() == 2) {
155 requirement_.min_x =
156 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
157 }
158
159 requirement_.focused.box.Shift(1, 1);
160 }
161
162 void SetBox(Box box) override {
163 Node::SetBox(box);
164 if (children_.size() == 2) {
165 Box title_box;
166 title_box.x_min = box.x_min + 1;
167 title_box.x_max = box.x_max - 1;
168 title_box.y_min = box.y_min;
169 title_box.y_max = box.y_min;
170 children_[1]->SetBox(title_box);
171 }
172 box.x_min++;
173 box.x_max--;
174 box.y_min++;
175 box.y_max--;
176 children_[0]->SetBox(box);
177 }
178
179 void Render(Screen& screen) override {
180 // Draw content.
181 // Dibujar contenido.
182 children_[0]->Render(screen);
183
184 // Draw the border.
185 // Dibujar el borde.
186 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
187 return;
188 }
189
190 screen.PixelAt(box_.x_min, box_.y_min) = pixel_;
191 screen.PixelAt(box_.x_max, box_.y_min) = pixel_;
192 screen.PixelAt(box_.x_min, box_.y_max) = pixel_;
193 screen.PixelAt(box_.x_max, box_.y_max) = pixel_;
194
195 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
196 screen.PixelAt(x, box_.y_min) = pixel_;
197 screen.PixelAt(x, box_.y_max) = pixel_;
198 }
199 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
200 screen.PixelAt(box_.x_min, y) = pixel_;
201 screen.PixelAt(box_.x_max, y) = pixel_;
202 }
203 }
204};
205} // namespace
206
207/// @brief Draw a border around the element.
208/// @brief Dibuja un borde alrededor del elemento.
209/// @ingroup dom
210/// @see border
211/// @see borderLight
212/// @see borderDashed
213/// @see borderDouble
214/// @see borderHeavy
215/// @see borderEmpty
216/// @see borderRounded
217/// @see borderStyled
218/// @see borderWith
219///
220/// Add a border around an element
221/// Añade un borde alrededor de un elemento
222///
223/// ### Example
224/// ### Ejemplo
225///
226/// ```cpp
227/// // Use 'border' as a function...
228/// // Usar 'border' como una función...
229/// Element document = border(text("The element"));
230///
231/// // ...Or as a 'pipe'.
232/// // ...O como un 'pipe'.
233/// Element document = text("The element") | border;
234/// ```
235///
236/// ### Output
237/// ### Salida
238///
239/// ```bash
240/// ┌───────────┐
241/// │The element│
242/// └───────────┘
243/// ```
245 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
246}
247
248/// @brief Same as border but with a constant Pixel around the element.
249/// @brief Igual que 'border' pero con un Pixel constante alrededor del elemento.
250/// @ingroup dom
251/// @see border
253 return [pixel](Element child) {
254 return std::make_shared<BorderPixel>(unpack(std::move(child)), pixel);
255 };
256}
257
258/// @brief Same as border but with different styles.
259/// @brief Igual que 'border' pero con diferentes estilos.
260/// @ingroup dom
261/// @see border
263 return [style](Element child) {
264 return std::make_shared<Border>(unpack(std::move(child)), style);
265 };
266}
267
268/// @brief Same as border but with a foreground color.
269/// @brief Igual que 'border' pero con un color de primer plano.
270/// @ingroup dom
271/// @see border
272Decorator borderStyled(Color foreground_color) {
273 return [foreground_color](Element child) {
274 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED,
275 foreground_color);
276 };
277}
278
279/// @brief Same as border but with a foreground color and a different style
280/// @brief Igual que 'border' pero con un color de primer plano y un estilo diferente
281/// @ingroup dom
282/// @see border
283Decorator borderStyled(BorderStyle style, Color foreground_color) {
284 return [style, foreground_color](Element child) {
285 return std::make_shared<Border>(unpack(std::move(child)), style,
286 foreground_color);
287 };
288}
289
290/// @brief Draw a dashed border around the element.
291/// @brief Dibuja un borde discontinuo alrededor del elemento.
292/// @ingroup dom
293/// @see border
294/// @see borderLight
295/// @see borderDashed
296/// @see borderDouble
297/// @see borderHeavy
298/// @see borderRounded
299/// @see borderEmpty
300/// @see borderStyled
301/// @see borderWith
302///
303/// Add a border around an element
304/// Añade un borde alrededor de un elemento
305///
306/// ### Example
307/// ### Ejemplo
308///
309/// ```cpp
310/// // Use 'borderDash' as a function...
311/// // Usar 'borderDash' como una función...
312/// Element document = borderDashed(text("The element"));
313///
314/// // ...Or as a 'pipe'.
315/// // ...O como un 'pipe'.
316/// Element document = text("The element") | borderDashed;
317/// ```
318///
319/// ### Output
320/// ### Salida
321///
322/// ```bash
323/// ┏╍╍╍╍╍╍╍╍╍╍╍╍╍╍┓
324/// ╏The element ╏
325/// ┗╍╍╍╍╍╍╍╍╍╍╍╍╍╍┛
326/// ```
328 return std::make_shared<Border>(unpack(std::move(child)), DASHED);
329}
330
331/// @brief Draw a light border around the element.
332/// @brief Dibuja un borde ligero alrededor del elemento.
333/// @ingroup dom
334/// @see border
335/// @see borderLight
336/// @see borderDashed
337/// @see borderDouble
338/// @see borderHeavy
339/// @see borderRounded
340/// @see borderEmpty
341/// @see borderStyled
342/// @see borderWith
343///
344/// Add a border around an element
345/// Añade un borde alrededor de un elemento
346///
347/// ### Example
348/// ### Ejemplo
349///
350/// ```cpp
351/// // Use 'borderLight' as a function...
352/// // Usar 'borderLight' como una función...
353/// Element document = borderLight(text("The element"));
354///
355/// // ...Or as a 'pipe'.
356/// // ...O como un 'pipe'.
357/// Element document = text("The element") | borderLight;
358/// ```
359///
360/// ### Output
361/// ### Salida
362///
363/// ```bash
364/// ┌──────────────┐
365/// │The element │
366/// └──────────────┘
367/// ```
369 return std::make_shared<Border>(unpack(std::move(child)), LIGHT);
370}
371
372/// @brief Draw a heavy border around the element.
373/// @brief Dibuja un borde grueso alrededor del elemento.
374/// @ingroup dom
375/// @see border
376/// @see borderLight
377/// @see borderDashed
378/// @see borderDouble
379/// @see borderHeavy
380/// @see borderRounded
381/// @see borderEmpty
382/// @see borderStyled
383/// @see borderWith
384///
385/// Add a border around an element
386/// Añade un borde alrededor de un elemento
387///
388/// ### Example
389/// ### Ejemplo
390///
391/// ```cpp
392/// // Use 'borderHeavy' as a function...
393/// // Usar 'borderHeavy' como una función...
394/// Element document = borderHeavy(text("The element"));
395///
396/// // ...Or as a 'pipe'.
397/// // ...O como un 'pipe'.
398/// Element document = text("The element") | borderHeavy;
399/// ```
400///
401/// ### Output
402/// ### Salida
403///
404/// ```bash
405/// ┏━━━━━━━━━━━━━━┓
406/// ┃The element ┃
407/// ┗━━━━━━━━━━━━━━┛
408/// ```
410 return std::make_shared<Border>(unpack(std::move(child)), HEAVY);
411}
412
413/// @brief Draw a double border around the element.
414/// @brief Dibuja un borde doble alrededor del elemento.
415/// @ingroup dom
416/// @see border
417/// @see borderLight
418/// @see borderDashed
419/// @see borderDouble
420/// @see borderHeavy
421/// @see borderRounded
422/// @see borderEmpty
423/// @see borderStyled
424/// @see borderWith
425///
426/// Add a border around an element
427/// Añade un borde alrededor de un elemento
428///
429/// ### Example
430/// ### Ejemplo
431///
432/// ```cpp
433/// // Use 'borderDouble' as a function...
434/// // Usar 'borderDouble' como una función...
435/// Element document = borderDouble(text("The element"));
436///
437/// // ...Or as a 'pipe'.
438/// // ...O como un 'pipe'.
439/// Element document = text("The element") | borderDouble;
440/// ```
441///
442/// ### Output
443/// ### Salida
444///
445/// ```bash
446/// ╔══════════════╗
447/// ║The element ║
448/// ╚══════════════╝
449/// ```
451 return std::make_shared<Border>(unpack(std::move(child)), DOUBLE);
452}
453
454/// @brief Draw a rounded border around the element.
455/// @brief Dibuja un borde redondeado alrededor del elemento.
456/// @ingroup dom
457/// @see border
458/// @see borderLight
459/// @see borderDashed
460/// @see borderDouble
461/// @see borderHeavy
462/// @see borderRounded
463/// @see borderEmpty
464/// @see borderStyled
465/// @see borderWith
466///
467/// Add a border around an element
468/// Añade un borde alrededor de un elemento
469///
470/// ### Example
471/// ### Ejemplo
472///
473/// ```cpp
474/// // Use 'borderRounded' as a function...
475/// // Usar 'borderRounded' como una función...
476/// Element document = borderRounded(text("The element"));
477///
478/// // ...Or as a 'pipe'.
479/// // ...O como un 'pipe'.
480/// Element document = text("The element") | borderRounded;
481/// ```
482///
483/// ### Output
484/// ### Salida
485///
486/// ```bash
487/// ╭──────────────╮
488/// │The element │
489/// ╰──────────────╯
490/// ```
492 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
493}
494
495/// @brief Draw an empty border around the element.
496/// @brief Dibuja un borde vacío alrededor del elemento.
497/// @ingroup dom
498/// @see border
499/// @see borderLight
500/// @see borderDashed
501/// @see borderDouble
502/// @see borderHeavy
503/// @see borderRounded
504/// @see borderEmpty
505/// @see borderStyled
506/// @see borderWith
507///
508/// Add a border around an element
509/// Añade un borde alrededor de un elemento
510///
511/// ### Example
512/// ### Ejemplo
513///
514/// ```cpp
515/// // Use 'borderRounded' as a function...
516/// // Usar 'borderRounded' como una función...
517/// Element document = borderRounded(text("The element"));
518///
519/// // ...Or as a 'pipe'.
520/// // ...O como un 'pipe'.
521/// Element document = text("The element") | borderRounded;
522/// ```
523///
524/// ### Output
525/// ### Salida
526///
527/// ```bash
528///
529/// The element
530///
531/// ```
533 return std::make_shared<Border>(unpack(std::move(child)), EMPTY);
534}
535
536/// @brief Draw window with a title and a border around the element.
537/// @brief Dibuja una ventana con un título y un borde alrededor del elemento.
538/// @param title The title of the window.
539/// @param title El título de la ventana.
540/// @param content The element to be wrapped.
541/// @param content El elemento a ser envuelto.
542/// @param border The style of the border. Default is ROUNDED.
543/// @param border El estilo del borde. El valor predeterminado es ROUNDED.
544/// @ingroup dom
545/// @see border
546///
547/// ### Example
548/// ### Ejemplo
549///
550/// ```cpp
551/// Element document = window(text("Title"),
552/// text("content")
553/// );
554///
555/// // With specifying border
556/// // Especificando el borde
557/// Element document = window(text("Title"),
558/// text("content"),
559/// ROUNDED
560/// );
561/// ```
562///
563/// ### Output
564/// ### Salida
565///
566/// ```bash
567/// ┌Title──┐
568/// │content│
569/// └───────┘
570/// ```
572 return std::make_shared<Border>(unpack(std::move(content), std::move(title)),
573 border);
574}
575} // namespace ftxui
auto screen
virtual void SetBox(Box box)
Asigna una posición y una dimensión a un elemento para dibujarlo.
Definition node.cpp:41
virtual void ComputeRequirement()
Calcula cuánto espacio necesita un elemento.
Definition node.cpp:20
Element window(Element title, Element content, BorderStyle border=ROUNDED)
Draw window with a title and a border around the element.
Element borderDouble(Element)
Draw a double border around the element.
Element borderDashed(Element)
Draw a dashed border around the element.
Element borderRounded(Element)
Draw a rounded border around the element.
Element borderHeavy(Element)
Draw a heavy border around the element.
Element borderLight(Element)
Draw a light border around the element.
Decorator borderWith(const Pixel &)
Same as border but with a constant Pixel around the element.
Decorator borderStyled(BorderStyle)
Same as border but with different styles.
void Render(Screen &screen, const Element &element)
Muestra un elemento en un ftxui::Screen.
Definition node.cpp:84
Element border(Element)
Draw a border around the element.
Element borderEmpty(Element)
Draw an empty border around the element.
BorderStyle
BorderStyle es una enumeración que representa los diferentes estilos de bordes que se pueden aplicar ...
Definition elements.hpp:35
@ EMPTY
Definition elements.hpp:41
@ DOUBLE
Definition elements.hpp:39
@ HEAVY
Definition elements.hpp:38
@ ROUNDED
Definition elements.hpp:40
@ DASHED
Definition elements.hpp:37
@ LIGHT
Definition elements.hpp:36
Color es una clase que representa un color en la interfaz de usuario de la terminal.
Definition color.hpp:21
Un carácter Unicode y su estilo asociado.
Definition pixel.hpp:15
std::string title
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
std::vector< Element > Elements
Definition elements.hpp:23
const Charset & charset_
std::optional< Color > foreground_color_