FTXUI 7.0.3
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#include <algorithm> // for max
5#include <array> // for array
6#include <ftxui/screen/color.hpp> // for Color
7#include <memory> // for allocator, make_shared, __shared_ptr_access
8#include <optional> // for optional, nullopt
9#include <string> // for basic_string, string
10#include <utility> // for move
11
12#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
13#include "ftxui/dom/node.hpp" // for Node, Elements
14#include "ftxui/dom/requirement.hpp" // for Requirement
15#include "ftxui/screen/box.hpp" // for Box
16#include "ftxui/screen/cell.hpp" // for Cell
17#include "ftxui/screen/screen.hpp" // for Cell, Screen
18
19namespace ftxui {
20
21namespace {
22using Charset = std::array<std::string, 6>; // NOLINT
23using Charsets = std::array<Charset, 6>; // NOLINT
24// NOLINTNEXTLINE
25static Charsets simple_border_charset = {
26 Charset{"┌", "┐", "└", "┘", "─", "│"}, // LIGERO
27 Charset{"┏", "┓", "┗", "┛", "╍", "╏"}, // DISCONTINUO
28 Charset{"┏", "┓", "┗", "┛", "━", "┃"}, // GRUESO
29 Charset{"╔", "╗", "╚", "╝", "═", "║"}, // DOBLE
30 Charset{"╭", "╮", "╰", "╯", "─", "│"}, // REDONDEADO
31 Charset{" ", " ", " ", " ", " ", " "}, // VACÍO
32};
33
34// For reference, here is the charset for normal border:
35// Para referencia, aquí está el conjunto de caracteres para un borde normal:
36class Border : public Node {
37 public:
38 Border(Elements children,
39 BorderStyle style,
40 std::optional<Color> foreground_color = std::nullopt)
41 : Node(std::move(children)),
42 charset_(simple_border_charset[style]) // NOLINT
43 ,
44 foreground_color_(foreground_color) {} // NOLINT
45
46 const Charset& charset_; // NOLINT
47 std::optional<Color> foreground_color_;
48
49 void ComputeRequirement() override {
50 Node::ComputeRequirement();
51 requirement_ = children_[0]->requirement();
52 requirement_.min_x += 2;
53 requirement_.min_y += 2;
54 if (children_.size() == 2) {
55 requirement_.min_x =
56 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
57 }
58 requirement_.focused.box.x_min++;
59 requirement_.focused.box.x_max++;
60 requirement_.focused.box.y_min++;
61 requirement_.focused.box.y_max++;
62 }
63
64 void SetBox(Box box) override {
65 Node::SetBox(box);
66 if (children_.size() == 2) {
67 Box title_box;
68 title_box.x_min = box.x_min + 1;
69 title_box.x_max = std::min(box.x_max - 1,
70 box.x_min + children_[1]->requirement().min_x);
71 title_box.y_min = box.y_min;
72 title_box.y_max = box.y_min;
73 children_[1]->SetBox(title_box);
74 }
75 box.x_min++;
76 box.x_max--;
77 box.y_min++;
78 box.y_max--;
79 children_[0]->SetBox(box);
80 }
81
82 void Render(Screen& screen) override {
83 // Draw content.
84 // Dibujar contenido.
85 children_[0]->Render(screen);
86
87 // Draw the border.
88 // Dibujar el borde.
89 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
90 return;
91 }
92
93 screen.at(box_.x_min, box_.y_min) = charset_[0]; // NOLINT
94 screen.at(box_.x_max, box_.y_min) = charset_[1]; // NOLINT
95 screen.at(box_.x_min, box_.y_max) = charset_[2]; // NOLINT
96 screen.at(box_.x_max, box_.y_max) = charset_[3]; // NOLINT
97
98 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
99 Cell& p1 = screen.CellAt(x, box_.y_min);
100 Cell& p2 = screen.CellAt(x, box_.y_max);
101 p1.character = charset_[4]; // NOLINT
102 p2.character = charset_[4]; // NOLINT
103 p1.automerge = true;
104 p2.automerge = true;
105 }
106 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
107 Cell& p3 = screen.CellAt(box_.x_min, y);
108 Cell& p4 = screen.CellAt(box_.x_max, y);
109 p3.character = charset_[5]; // NOLINT
110 p4.character = charset_[5]; // NOLINT
111 p3.automerge = true;
112 p4.automerge = true;
113 }
114
115 // Draw title.
116 // Dibujar título.
117 if (children_.size() == 2) {
118 children_[1]->Render(screen);
119 }
120
121 // Draw the border color.
122 // Dibujar el color del borde.
123 if (foreground_color_) {
124 for (int x = box_.x_min; x <= box_.x_max; ++x) {
125 screen.CellAt(x, box_.y_min).foreground_color = *foreground_color_;
126 screen.CellAt(x, box_.y_max).foreground_color = *foreground_color_;
127 }
128 for (int y = box_.y_min; y <= box_.y_max; ++y) {
129 screen.CellAt(box_.x_min, y).foreground_color = *foreground_color_;
130 screen.CellAt(box_.x_max, y).foreground_color = *foreground_color_;
131 }
132 }
133 }
134};
135
136// For reference, here is the charset for normal border:
137// Para referencia, aquí está el conjunto de caracteres para un borde normal:
138class BorderCell : public Node {
139 public:
140 BorderCell(Elements children, Cell pixel)
141 : Node(std::move(children)), pixel_(std::move(pixel)) {}
142
143 private:
144 Cell pixel_;
145
146 void ComputeRequirement() override {
147 Node::ComputeRequirement();
148 requirement_ = children_[0]->requirement();
149 requirement_.min_x += 2;
150 requirement_.min_y += 2;
151 if (children_.size() == 2) {
152 requirement_.min_x =
153 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
154 }
155
156 requirement_.focused.box.Shift(1, 1);
157 }
158
159 void SetBox(Box box) override {
160 Node::SetBox(box);
161 if (children_.size() == 2) {
162 Box title_box;
163 title_box.x_min = box.x_min + 1;
164 title_box.x_max = box.x_max - 1;
165 title_box.y_min = box.y_min;
166 title_box.y_max = box.y_min;
167 children_[1]->SetBox(title_box);
168 }
169 box.x_min++;
170 box.x_max--;
171 box.y_min++;
172 box.y_max--;
173 children_[0]->SetBox(box);
174 }
175
176 void Render(Screen& screen) override {
177 // Draw content.
178 // Dibujar contenido.
179 children_[0]->Render(screen);
180
181 // Draw the border.
182 // Dibujar el borde.
183 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
184 return;
185 }
186
187 screen.CellAt(box_.x_min, box_.y_min) = pixel_;
188 screen.CellAt(box_.x_max, box_.y_min) = pixel_;
189 screen.CellAt(box_.x_min, box_.y_max) = pixel_;
190 screen.CellAt(box_.x_max, box_.y_max) = pixel_;
191
192 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
193 screen.CellAt(x, box_.y_min) = pixel_;
194 screen.CellAt(x, box_.y_max) = pixel_;
195 }
196 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
197 screen.CellAt(box_.x_min, y) = pixel_;
198 screen.CellAt(box_.x_max, y) = pixel_;
199 }
200 }
201};
202} // namespace
203
204/// @brief Dibuja un borde alrededor del elemento.
205/// @ingroup dom
206/// @see border
207/// @see borderLight
208/// @see borderDashed
209/// @see borderDouble
210/// @see borderHeavy
211/// @see borderEmpty
212/// @see borderRounded
213/// @see borderStyled
214/// @see borderWith
215///
216/// Agrega un borde alrededor de un elemento
217///
218/// ### Ejemplo
219///
220/// ```cpp
221/// // Usa 'border' como una función...
222/// Element document = border(text("The element"));
223///
224/// // ...O como una 'tubería' (pipe).
225/// Element document = text("The element") | border;
226/// ```
227///
228/// ### Salida
229///
230/// ```bash
231/// ┌───────────┐
232/// │The element│
233/// └───────────┘
234/// ```
236 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
237}
238
239/// @brief Igual que border pero con un Cell constante alrededor del elemento.
240/// @ingroup dom
241/// @see border
242Decorator borderWith(const Cell& pixel) {
243 return [pixel](Element child) {
244 return std::make_shared<BorderCell>(unpack(std::move(child)), pixel);
245 };
246}
247
248/// @brief Igual que border pero con estilos diferentes.
249/// @ingroup dom
250/// @see border
252 return [style](Element child) {
253 return std::make_shared<Border>(unpack(std::move(child)), style);
254 };
255}
256
257/// @brief Igual que border pero con un color de primer plano.
258/// @ingroup dom
259/// @see border
260Decorator borderStyled(Color foreground_color) {
261 return [foreground_color](Element child) {
262 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED,
263 foreground_color);
264 };
265}
266
267/// @brief Igual que border pero con un color de primer plano y un estilo diferente
268/// @ingroup dom
269/// @see border
270Decorator borderStyled(BorderStyle style, Color foreground_color) {
271 return [style, foreground_color](Element child) {
272 return std::make_shared<Border>(unpack(std::move(child)), style,
273 foreground_color);
274 };
275}
276
277/// @brief Dibuja un borde discontinuo alrededor del elemento.
278/// @ingroup dom
279/// @see border
280/// @see borderLight
281/// @see borderDashed
282/// @see borderDouble
283/// @see borderHeavy
284/// @see borderRounded
285/// @see borderEmpty
286/// @see borderStyled
287/// @see borderWith
288///
289/// Agrega un borde alrededor de un elemento
290///
291/// ### Ejemplo
292///
293/// ```cpp
294/// // Usa 'borderDash' como una función...
295/// Element document = borderDash(text("The element"));
296///
297/// // ...O como una 'tubería' (pipe).
298/// Element document = text("The element") | borderDAsh;
299/// ```
300///
301/// ### Salida
302///
303/// ```bash
304/// ┏╍╍╍╍╍╍╍╍╍╍╍╍╍╍┓
305/// ╏The element ╏
306/// ┗╍╍╍╍╍╍╍╍╍╍╍╍╍╍┛
307/// ```
309 return std::make_shared<Border>(unpack(std::move(child)), DASHED);
310}
311
312/// @brief Dibuja un borde ligero alrededor del elemento.
313/// @ingroup dom
314/// @see border
315/// @see borderLight
316/// @see borderDashed
317/// @see borderDouble
318/// @see borderHeavy
319/// @see borderRounded
320/// @see borderEmpty
321/// @see borderStyled
322/// @see borderWith
323///
324/// Agrega un borde alrededor de un elemento
325///
326/// ### Ejemplo
327///
328/// ```cpp
329/// // Usa 'borderLight' como una función...
330/// Element document = borderLight(text("The element"));
331///
332/// // ...O como una 'tubería' (pipe).
333/// Element document = text("The element") | borderLight;
334/// ```
335///
336/// ### Salida
337///
338/// ```bash
339/// ┌──────────────┐
340/// │The element │
341/// └──────────────┘
342/// ```
344 return std::make_shared<Border>(unpack(std::move(child)), LIGHT);
345}
346
347/// @brief Dibuja un borde grueso alrededor del elemento.
348/// @ingroup dom
349/// @see border
350/// @see borderLight
351/// @see borderDashed
352/// @see borderDouble
353/// @see borderHeavy
354/// @see borderRounded
355/// @see borderEmpty
356/// @see borderStyled
357/// @see borderWith
358///
359/// Agrega un borde alrededor de un elemento
360///
361/// ### Ejemplo
362///
363/// ```cpp
364/// // Usa 'borderHeavy' como una función...
365/// Element document = borderHeavy(text("The element"));
366///
367/// // ...O como una 'tubería' (pipe).
368/// Element document = text("The element") | borderHeavy;
369/// ```
370///
371/// ### Salida
372///
373/// ```bash
374/// ┏━━━━━━━━━━━━━━┓
375/// ┃The element ┃
376/// ┗━━━━━━━━━━━━━━┛
377/// ```
379 return std::make_shared<Border>(unpack(std::move(child)), HEAVY);
380}
381
382/// @brief Dibuja un borde doble alrededor del elemento.
383/// @ingroup dom
384/// @see border
385/// @see borderLight
386/// @see borderDashed
387/// @see borderDouble
388/// @see borderHeavy
389/// @see borderRounded
390/// @see borderEmpty
391/// @see borderStyled
392/// @see borderWith
393///
394/// Agrega un borde alrededor de un elemento
395///
396/// ### Ejemplo
397///
398/// ```cpp
399/// // Usa 'borderDouble' como una función...
400/// Element document = borderDouble(text("The element"));
401///
402/// // ...O como una 'tubería' (pipe).
403/// Element document = text("The element") | borderDouble;
404/// ```
405///
406/// ### Salida
407///
408/// ```bash
409/// ╔══════════════╗
410/// ║The element ║
411/// ╚══════════════╝
412/// ```
414 return std::make_shared<Border>(unpack(std::move(child)), DOUBLE);
415}
416
417/// @brief Dibuja un borde redondeado alrededor del elemento.
418/// @ingroup dom
419/// @see border
420/// @see borderLight
421/// @see borderDashed
422/// @see borderDouble
423/// @see borderHeavy
424/// @see borderRounded
425/// @see borderEmpty
426/// @see borderStyled
427/// @see borderWith
428///
429/// Agrega un borde alrededor de un elemento
430///
431/// ### Ejemplo
432///
433/// ```cpp
434/// // Usa 'borderRounded' como una función...
435/// Element document = borderRounded(text("The element"));
436///
437/// // ...O como una 'tubería' (pipe).
438/// Element document = text("The element") | borderRounded;
439/// ```
440///
441/// ### Salida
442///
443/// ```bash
444/// ╭──────────────╮
445/// │The element │
446/// ╰──────────────╯
447/// ```
449 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
450}
451
452/// @brief Dibuja un borde vacío alrededor del elemento.
453/// @ingroup dom
454/// @see border
455/// @see borderLight
456/// @see borderDashed
457/// @see borderDouble
458/// @see borderHeavy
459/// @see borderRounded
460/// @see borderEmpty
461/// @see borderStyled
462/// @see borderWith
463///
464/// Agrega un borde alrededor de un elemento
465///
466/// ### Ejemplo
467///
468/// ```cpp
469/// // Usa 'borderRounded' como una función...
470/// Element document = borderRounded(text("The element"));
471///
472/// // ...O como una 'tubería' (pipe).
473/// Element document = text("The element") | borderRounded;
474/// ```
475///
476/// ### Salida
477///
478/// ```bash
479///
480/// The element
481///
482/// ```
484 return std::make_shared<Border>(unpack(std::move(child)), EMPTY);
485}
486
487/// @brief Dibuja una ventana con un título y un borde alrededor del elemento.
488/// @param title El título de la ventana.
489/// @param content El elemento a envolver.
490/// @param border El estilo del borde. Por defecto es ROUNDED.
491/// @ingroup dom
492/// @see border
493///
494/// ### Ejemplo
495///
496/// ```cpp
497/// Element document = window(text("Title"),
498/// text("content")
499/// );
500///
501/// // Especificando el borde
502/// Element document = window(text("Title"),
503/// text("content"),
504/// ROUNDED
505/// );
506/// ```
507///
508/// ### Salida
509///
510/// ```bash
511/// ┌Title──┐
512/// │content│
513/// └───────┘
514/// ```
515Element window(Element title, Element content, BorderStyle border) {
516 return std::make_shared<Border>(unpack(std::move(content), std::move(title)),
517 border);
518}
519} // namespace ftxui
Element window(Element title, Element content, BorderStyle border=ROUNDED)
Dibuja una ventana con un título y un borde alrededor del elemento.
Element borderDouble(Element child)
Dibuja un borde doble alrededor del elemento.
Element borderDashed(Element child)
Dibuja un borde discontinuo alrededor del elemento.
Element borderRounded(Element child)
Dibuja un borde redondeado alrededor del elemento.
BorderStyle
BorderStyle es una enumeración que representa los diferentes estilos de bordes que se pueden aplicar ...
Definition elements.hpp:38
Element borderHeavy(Element child)
Dibuja un borde grueso alrededor del elemento.
Decorator borderWith(const Cell &pixel)
Igual que border pero con un Cell constante alrededor del elemento.
Element borderLight(Element child)
Dibuja un borde ligero alrededor del elemento.
Decorator borderStyled(BorderStyle style)
Igual que border pero con estilos diferentes.
Element border(Element child)
Dibuja un borde alrededor del elemento.
Element borderEmpty(Element child)
Dibuja un borde vacío alrededor del elemento.
@ EMPTY
Definition elements.hpp:44
@ DOUBLE
Definition elements.hpp:42
@ HEAVY
Definition elements.hpp:41
@ ROUNDED
Definition elements.hpp:43
@ DASHED
Definition elements.hpp:40
@ LIGHT
Definition elements.hpp:39
El espacio de nombres ftxui:: de FTXUI.
Definition animation.hpp:11
std::shared_ptr< Node > Element
Definition elements.hpp:25
std::vector< Element > Elements
Definition elements.hpp:26
std::function< Element(Element)> Decorator
Definition elements.hpp:27
int y
Definition elements.hpp:134
void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:105
const Charset & charset_
std::optional< Color > foreground_color_