FTXUI 6.1.9
C++ functional terminal UI.
Chargement...
Recherche...
Aucune correspondance
src/ftxui/dom/border.cpp
Aller à la documentation de ce fichier.
1// Copyright 2020 Arthur Sonzogni. Tous droits réservés.
2// L'utilisation de ce code source est régie par la licence MIT qui peut être trouvée dans
3// le fichier LICENSE.
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/pixel.hpp" // for Pixel
17#include "ftxui/screen/screen.hpp" // for Pixel, 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{"┌", "┐", "└", "┘", "─", "│"}, // LIGHT
27 Charset{"┏", "┓", "┗", "┛", "╍", "╏"}, // DASHED
28 Charset{"┏", "┓", "┗", "┛", "━", "┃"}, // HEAVY
29 Charset{"╔", "╗", "╚", "╝", "═", "║"}, // DOUBLE
30 Charset{"╭", "╮", "╰", "╯", "─", "│"}, // ROUNDED
31 Charset{" ", " ", " ", " ", " ", " "}, // EMPTY
32};
33
34// Pour référence, voici le jeu de caractères pour une bordure normale :
35class Border : public Node {
36 public:
37 Border(Elements children,
38 BorderStyle style,
39 std::optional<Color> foreground_color = std::nullopt)
40 : Node(std::move(children)),
41 charset_(simple_border_charset[style]) // NOLINT
42 ,
43 foreground_color_(foreground_color) {} // NOLINT
44
45 const Charset& charset_; // NOLINT
46 std::optional<Color> foreground_color_;
47
48 void ComputeRequirement() override {
50 requirement_ = children_[0]->requirement();
51 requirement_.min_x += 2;
52 requirement_.min_y += 2;
53 if (children_.size() == 2) {
54 requirement_.min_x =
55 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
56 }
57 requirement_.focused.box.x_min++;
58 requirement_.focused.box.x_max++;
59 requirement_.focused.box.y_min++;
60 requirement_.focused.box.y_max++;
61 }
62
63 void SetBox(Box box) override {
64 Node::SetBox(box);
65 if (children_.size() == 2) {
66 Box title_box;
67 title_box.x_min = box.x_min + 1;
68 title_box.x_max = std::min(box.x_max - 1,
69 box.x_min + children_[1]->requirement().min_x);
70 title_box.y_min = box.y_min;
71 title_box.y_max = box.y_min;
72 children_[1]->SetBox(title_box);
73 }
74 box.x_min++;
75 box.x_max--;
76 box.y_min++;
77 box.y_max--;
78 children_[0]->SetBox(box);
79 }
80
81 void Render(Screen& screen) override {
82 // Draw content.
83 children_[0]->Render(screen);
84
85 // Draw the border.
86 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
87 return;
88 }
89
90 screen.at(box_.x_min, box_.y_min) = charset_[0]; // NOLINT
91 screen.at(box_.x_max, box_.y_min) = charset_[1]; // NOLINT
92 screen.at(box_.x_min, box_.y_max) = charset_[2]; // NOLINT
93 screen.at(box_.x_max, box_.y_max) = charset_[3]; // NOLINT
94
95 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
96 Pixel& p1 = screen.PixelAt(x, box_.y_min);
97 Pixel& p2 = screen.PixelAt(x, box_.y_max);
98 p1.character = charset_[4]; // NOLINT
99 p2.character = charset_[4]; // NOLINT
100 p1.automerge = true;
101 p2.automerge = true;
102 }
103 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
104 Pixel& p3 = screen.PixelAt(box_.x_min, y);
105 Pixel& p4 = screen.PixelAt(box_.x_max, y);
106 p3.character = charset_[5]; // NOLINT
107 p4.character = charset_[5]; // NOLINT
108 p3.automerge = true;
109 p4.automerge = true;
110 }
111
112 // Draw title.
113 if (children_.size() == 2) {
114 children_[1]->Render(screen);
115 }
116
117 // Draw the border color.
118 if (foreground_color_) {
119 for (int x = box_.x_min; x <= box_.x_max; ++x) {
120 screen.PixelAt(x, box_.y_min).foreground_color = *foreground_color_;
121 screen.PixelAt(x, box_.y_max).foreground_color = *foreground_color_;
122 }
123 for (int y = box_.y_min; y <= box_.y_max; ++y) {
124 screen.PixelAt(box_.x_min, y).foreground_color = *foreground_color_;
125 screen.PixelAt(box_.x_max, y).foreground_color = *foreground_color_;
126 }
127 }
128 }
129};
130
131// Pour référence, voici le jeu de caractères pour une bordure normale :
132class BorderPixel : public Node {
133 public:
134 BorderPixel(Elements children, Pixel pixel)
135 : Node(std::move(children)), pixel_(std::move(pixel)) {}
136
137 private:
138 Pixel pixel_;
139
140 void ComputeRequirement() override {
142 requirement_ = children_[0]->requirement();
143 requirement_.min_x += 2;
144 requirement_.min_y += 2;
145 if (children_.size() == 2) {
146 requirement_.min_x =
147 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
148 }
149
150 requirement_.focused.box.Shift(1, 1);
151 }
152
153 void SetBox(Box box) override {
154 Node::SetBox(box);
155 if (children_.size() == 2) {
156 Box title_box;
157 title_box.x_min = box.x_min + 1;
158 title_box.x_max = box.x_max - 1;
159 title_box.y_min = box.y_min;
160 title_box.y_max = box.y_min;
161 children_[1]->SetBox(title_box);
162 }
163 box.x_min++;
164 box.x_max--;
165 box.y_min++;
166 box.y_max--;
167 children_[0]->SetBox(box);
168 }
169
170 void Render(Screen& screen) override {
171 // Draw content.
172 children_[0]->Render(screen);
173
174 // Draw the border.
175 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
176 return;
177 }
178
179 screen.PixelAt(box_.x_min, box_.y_min) = pixel_;
180 screen.PixelAt(box_.x_max, box_.y_min) = pixel_;
181 screen.PixelAt(box_.x_min, box_.y_max) = pixel_;
182 screen.PixelAt(box_.x_max, box_.y_max) = pixel_;
183
184 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
185 screen.PixelAt(x, box_.y_min) = pixel_;
186 screen.PixelAt(x, box_.y_max) = pixel_;
187 }
188 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
189 screen.PixelAt(box_.x_min, y) = pixel_;
190 screen.PixelAt(box_.x_max, y) = pixel_;
191 }
192 }
193};
194} // namespace
195
196/// @brief Dessine une bordure autour de l'élément.
197/// @ingroup dom
198/// @see border
199/// @see borderLight
200/// @see borderDashed
201/// @see borderDouble
202/// @see borderHeavy
203/// @see borderEmpty
204/// @see borderRounded
205/// @see borderStyled
206/// @see borderWith
207///
208/// Ajoute une bordure autour d'un élément
209///
210/// ### Exemple
211///
212/// ```cpp
213/// // Utilisation de 'border' comme une fonction...
214/// Element document = border(text("The element"));
215///
216/// // ...Ou comme un 'pipe'.
217/// Element document = text("The element") | border;
218/// ```
219///
220/// ### Sortie
221///
222/// ```bash
223/// ┌───────────┐
224/// │The element│
225/// └───────────┘
226/// ```
228 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
229}
230
231/// @brief Identique à border mais avec un Pixel constant autour de l'élément.
232/// @ingroup dom
233/// @see border
235 return [pixel](Element child) {
236 return std::make_shared<BorderPixel>(unpack(std::move(child)), pixel);
237 };
238}
239
240/// @brief Identique à border mais avec différents styles.
241/// @ingroup dom
242/// @see border
244 return [style](Element child) {
245 return std::make_shared<Border>(unpack(std::move(child)), style);
246 };
247}
248
249/// @brief Identique à border mais avec une couleur de premier plan.
250/// @ingroup dom
251/// @see border
252Decorator borderStyled(Color foreground_color) {
253 return [foreground_color](Element child) {
254 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED,
255 foreground_color);
256 };
257}
258
259/// @brief Identique à border mais avec une couleur de premier plan et un style différent
260/// @ingroup dom
261/// @see border
262Decorator borderStyled(BorderStyle style, Color foreground_color) {
263 return [style, foreground_color](Element child) {
264 return std::make_shared<Border>(unpack(std::move(child)), style,
265 foreground_color);
266 };
267}
268
269/// @brief Dessine une bordure en pointillés autour de l'élément.
270/// @ingroup dom
271/// @see border
272/// @see borderLight
273/// @see borderDashed
274/// @see borderDouble
275/// @see borderHeavy
276/// @see borderRounded
277/// @see borderEmpty
278/// @see borderStyled
279/// @see borderWith
280///
281/// Ajoute une bordure autour d'un élément
282///
283/// ### Exemple
284///
285/// ```cpp
286/// // Utilisation de 'borderDash' comme une fonction...
287/// Element document = borderDashed(text("The element"));
288///
289/// // ...Ou comme un 'pipe'.
290/// Element document = text("The element") | borderDashed;
291/// ```
292///
293/// ### Sortie
294///
295/// ```bash
296/// ┏╍╍╍╍╍╍╍╍╍╍╍╍╍╍┓
297/// ╏The element ╏
298/// ┗╍╍╍╍╍╍╍╍╍╍╍╍╍╍┛
299/// ```
301 return std::make_shared<Border>(unpack(std::move(child)), DASHED);
302}
303
304/// @brief Dessine une bordure fine autour de l'élément.
305/// @ingroup dom
306/// @see border
307/// @see borderLight
308/// @see borderDashed
309/// @see borderDouble
310/// @see borderHeavy
311/// @see borderRounded
312/// @see borderEmpty
313/// @see borderStyled
314/// @see borderWith
315///
316/// Ajoute une bordure autour d'un élément
317///
318/// ### Exemple
319///
320/// ```cpp
321/// // Utilisation de 'borderLight' comme une fonction...
322/// Element document = borderLight(text("The element"));
323///
324/// // ...Ou comme un 'pipe'.
325/// Element document = text("The element") | borderLight;
326/// ```
327///
328/// ### Sortie
329///
330/// ```bash
331/// ┌──────────────┐
332/// │The element │
333/// └──────────────┘
334/// ```
336 return std::make_shared<Border>(unpack(std::move(child)), LIGHT);
337}
338
339/// @brief Dessine une bordure épaisse autour de l'élément.
340/// @ingroup dom
341/// @see border
342/// @see borderLight
343/// @see borderDashed
344/// @see borderDouble
345/// @see borderHeavy
346/// @see borderRounded
347/// @see borderEmpty
348/// @see borderStyled
349/// @see borderWith
350///
351/// Ajoute une bordure autour d'un élément
352///
353/// ### Exemple
354///
355/// ```cpp
356/// // Utilisation de 'borderHeavy' comme une fonction...
357/// Element document = borderHeavy(text("The element"));
358///
359/// // ...Ou comme un 'pipe'.
360/// Element document = text("The element") | borderHeavy;
361/// ```
362///
363/// ### Sortie
364///
365/// ```bash
366/// ┏━━━━━━━━━━━━━━┓
367/// ┃The element ┃
368/// ┗━━━━━━━━━━━━━━┛
369/// ```
371 return std::make_shared<Border>(unpack(std::move(child)), HEAVY);
372}
373
374/// @brief Dessine une double bordure autour de l'élément.
375/// @ingroup dom
376/// @see border
377/// @see borderLight
378/// @see borderDashed
379/// @see borderDouble
380/// @see borderHeavy
381/// @see borderRounded
382/// @see borderEmpty
383/// @see borderStyled
384/// @see borderWith
385///
386/// Ajoute une bordure autour d'un élément
387///
388/// ### Exemple
389///
390/// ```cpp
391/// // Utilisation de 'borderDouble' comme une fonction...
392/// Element document = borderDouble(text("The element"));
393///
394/// // ...Ou comme un 'pipe'.
395/// Element document = text("The element") | borderDouble;
396/// ```
397///
398/// ### Sortie
399///
400/// ```bash
401/// ╔══════════════╗
402/// ║The element ║
403/// ╚══════════════╝
404/// ```
406 return std::make_shared<Border>(unpack(std::move(child)), DOUBLE);
407}
408
409/// @brief Dessine une bordure arrondie autour de l'élément.
410/// @ingroup dom
411/// @see border
412/// @see borderLight
413/// @see borderDashed
414/// @see borderDouble
415/// @see borderHeavy
416/// @see borderRounded
417/// @see borderEmpty
418/// @see borderStyled
419/// @see borderWith
420///
421/// Ajoute une bordure autour d'un élément
422///
423/// ### Exemple
424///
425/// ```cpp
426/// // Utilisation de 'borderRounded' comme une fonction...
427/// Element document = borderRounded(text("The element"));
428///
429/// // ...Ou comme un 'pipe'.
430/// Element document = text("The element") | borderRounded;
431/// ```
432///
433/// ### Sortie
434///
435/// ```bash
436/// ╭──────────────╮
437/// │The element │
438/// ╰──────────────╯
439/// ```
441 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
442}
443
444/// @brief Dessine une bordure vide autour de l'élément.
445/// @ingroup dom
446/// @see border
447/// @see borderLight
448/// @see borderDashed
449/// @see borderDouble
450/// @see borderHeavy
451/// @see borderRounded
452/// @see borderEmpty
453/// @see borderStyled
454/// @see borderWith
455///
456/// Ajoute une bordure autour d'un élément
457///
458/// ### Exemple
459///
460/// ```cpp
461/// // Utilisation de 'borderEmpty' comme une fonction...
462/// Element document = borderEmpty(text("The element"));
463///
464/// // ...Ou comme un 'pipe'.
465/// Element document = text("The element") | borderEmpty;
466/// ```
467///
468/// ### Sortie
469///
470/// ```bash
471///
472/// The element
473///
474/// ```
476 return std::make_shared<Border>(unpack(std::move(child)), EMPTY);
477}
478
479/// @brief Dessine une fenêtre avec un titre et une bordure autour de l'élément.
480/// @param title Le titre de la fenêtre.
481/// @param content L'élément à envelopper.
482/// @param border Le style de la bordure. La valeur par défaut est ROUNDED.
483/// @ingroup dom
484/// @see border
485///
486/// ### Exemple
487///
488/// ```cpp
489/// Element document = window(text("Title"),
490/// text("content")
491/// );
492///
493/// // En spécifiant la bordure
494/// Element document = window(text("Title"),
495/// text("content"),
496/// ROUNDED
497/// );
498/// ```
499///
500/// ### Sortie
501///
502/// ```bash
503/// ┌Title──┐
504/// │content│
505/// └───────┘
506/// ```
507Element window(Element title, Element content, BorderStyle border) {
508 return std::make_shared<Border>(unpack(std::move(content), std::move(title)),
509 border);
510}
511} // namespace ftxui
auto screen
virtual void SetBox(Box box)
Assigne une position et une dimension à un élément pour le dessin.
Definition node.cpp:41
virtual void ComputeRequirement()
Calcule l'espace nécessaire à un élément.
Definition node.cpp:20
Element window(Element title, Element content, BorderStyle border=ROUNDED)
Dessine une fenêtre avec un titre et une bordure autour de l'élément.
Element borderDouble(Element)
Dessine une double bordure autour de l'élément.
Element borderDashed(Element)
Dessine une bordure en pointillés autour de l'élément.
Element borderRounded(Element)
Dessine une bordure arrondie autour de l'élément.
Element borderHeavy(Element)
Dessine une bordure épaisse autour de l'élément.
Element borderLight(Element)
Dessine une bordure fine autour de l'élément.
Decorator borderWith(const Pixel &)
Identique à border mais avec un Pixel constant autour de l'élément.
Decorator borderStyled(BorderStyle)
Identique à border mais avec différents styles.
Element border(Element)
Dessine une bordure autour de l'élément.
Element borderEmpty(Element)
Dessine une bordure vide autour de l'élément.
BorderStyle
BorderStyle est une énumération qui représente les différents styles de bordures pouvant être appliqu...
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 est une classe qui représente une couleur dans l'interface utilisateur du terminal.
Definition color.hpp:21
Un caractère Unicode et son style associé.
Definition pixel.hpp:15
L'espace de noms FTXUI 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
void Render(Screen &screen, const Element &element)
const Charset & charset_
std::optional< Color > foreground_color_