FTXUI 7.0.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/dom/separator.cpp
Go to the documentation of this file.
1#include <string_view>
2// Copyright 2020 Arthur Sonzogni. All rights reserved.
3// Use of this source code is governed by the MIT license that can be found in
4// the LICENSE file.
5#include <array> // for array, array<>::value_type
6#include <memory> // for make_shared, allocator
7#include <string> // for basic_string, string
8#include <utility> // for move
9
10#include "ftxui/dom/elements.hpp" // for Element, BorderStyle, LIGHT, separator, DOUBLE, EMPTY, HEAVY, separatorCharacter, separatorDouble, separatorEmpty, separatorHSelector, separatorHeavy, separatorLight, separatorStyled, separatorVSelector
11#include "ftxui/dom/node.hpp" // for Node
12#include "ftxui/dom/requirement.hpp" // for Requirement
13#include "ftxui/screen/box.hpp" // for Box
14#include "ftxui/screen/cell.hpp" // for Cell
15#include "ftxui/screen/color.hpp" // for Color
16#include "ftxui/screen/screen.hpp" // for Cell, Screen
17
18namespace ftxui {
19
20namespace {
21using SeparatorCharset = std::array<std::string, 2>; // NOLINT
22using SeparatorCharsets = std::array<SeparatorCharset, 6>; // NOLINT
23
24const SeparatorCharsets charsets = {
25 // NOLINT
26 SeparatorCharset{"│", "─"}, // LIGHT
27 SeparatorCharset{"╏", "╍"}, // DASHED
28 SeparatorCharset{"┃", "━"}, // HEAVY
29 SeparatorCharset{"║", "═"}, // DOUBLE
30 SeparatorCharset{"│", "─"}, // ROUNDED
31 SeparatorCharset{" ", " "}, // EMPTY
32};
33
34class Separator : public Node {
35 public:
36 explicit Separator(std::string value) : value_(std::move(value)) {}
37
38 void ComputeRequirement() override {
39 requirement_.min_x = 1;
40 requirement_.min_y = 1;
41 }
42
43 void Render(Screen& screen) override {
44 for (int y = box_.y_min; y <= box_.y_max; ++y) {
45 for (int x = box_.x_min; x <= box_.x_max; ++x) {
46 Cell& pixel = screen.CellAt(x, y);
47 pixel.character = value_;
48 pixel.automerge = true;
49 }
50 }
51 }
52
53 std::string value_;
54};
55
56class SeparatorAuto : public Node {
57 public:
58 explicit SeparatorAuto(BorderStyle style) : style_(style) {}
59
60 void ComputeRequirement() override {
61 requirement_.min_x = 1;
62 requirement_.min_y = 1;
63 }
64
65 void Render(Screen& screen) override {
66 const bool is_column = (box_.x_max == box_.x_min);
67 const bool is_line = (box_.y_min == box_.y_max);
68
69 const std::string c =
70 charsets[style_][int(is_line && !is_column)]; // NOLINT
71
72 for (int y = box_.y_min; y <= box_.y_max; ++y) {
73 for (int x = box_.x_min; x <= box_.x_max; ++x) {
74 Cell& pixel = screen.CellAt(x, y);
75 pixel.character = c;
76 pixel.automerge = true;
77 }
78 }
79 }
80
82};
83
84class SeparatorWithCell : public SeparatorAuto {
85 public:
86 explicit SeparatorWithCell(Cell pixel)
87 : SeparatorAuto(LIGHT), pixel_(std::move(pixel)) {
88 pixel_.automerge = true;
89 }
90 void Render(Screen& screen) override {
91 for (int y = box_.y_min; y <= box_.y_max; ++y) {
92 for (int x = box_.x_min; x <= box_.x_max; ++x) {
93 screen.CellAt(x, y) = pixel_;
94 }
95 }
96 }
97
98 private:
99 Cell pixel_;
100};
101} // namespace
102
103/// @brief Draw a vertical or horizontal separation in between two other
104/// elements.
105/// @ingroup dom
106/// @see separator
107/// @see separatorLight
108/// @see separatorDashed
109/// @see separatorDouble
110/// @see separatorHeavy
111/// @see separatorEmpty
112/// @see separatorRounded
113/// @see separatorStyled
114/// @see separatorCharacter
115///
116/// Add a visual separation in between two elements.
117///
118/// ### Example
119///
120/// ```cpp
121/// // Use 'border' as a function...
122/// Element document = vbox({
123/// text("up"),
124/// separator(),
125/// text("down"),
126/// });
127/// ```
128///
129/// ### Output
130///
131/// ```bash
132/// up
133/// ────
134/// down
135/// ```
137 return std::make_shared<SeparatorAuto>(LIGHT);
138}
139
140/// @brief Draw a vertical or horizontal separation in between two other
141/// elements.
142/// @param style the style of the separator.
143/// @ingroup dom
144/// @see separator
145/// @see separatorLight
146/// @see separatorDashed
147/// @see separatorDouble
148/// @see separatorHeavy
149/// @see separatorEmpty
150/// @see separatorRounded
151/// @see separatorStyled
152/// @see separatorCharacter
153///
154/// Add a visual separation in between two elements.
155///
156/// ### Example
157///
158/// ```cpp
159/// // Use 'border' as a function...
160/// Element document = vbox({
161/// text("up"),
162/// separatorStyled(DOUBLE),
163/// text("down"),
164/// });
165/// ```
166///
167/// ### Output
168///
169/// ```bash
170/// up
171/// ════
172/// down
173/// ```
175 return std::make_shared<SeparatorAuto>(style);
176}
177
178/// @brief Draw a vertical or horizontal separation in between two other
179/// elements, using the LIGHT style.
180/// @ingroup dom
181/// @see separator
182/// @see separatorLight
183/// @see separatorDashed
184/// @see separatorDouble
185/// @see separatorHeavy
186/// @see separatorEmpty
187/// @see separatorRounded
188/// @see separatorStyled
189/// @see separatorCharacter
190///
191/// Add a visual separation in between two elements.
192///
193/// ### Example
194///
195/// ```cpp
196/// // Use 'border' as a function...
197/// Element document = vbox({
198/// text("up"),
199/// separatorLight(),
200/// text("down"),
201/// });
202/// ```
203///
204/// ### Output
205///
206/// ```bash
207/// up
208/// ────
209/// down
210/// ```
212 return std::make_shared<SeparatorAuto>(LIGHT);
213}
214
215/// @brief Draw a vertical or horizontal separation in between two other
216/// elements, using the DASHED style.
217/// @ingroup dom
218/// @see separator
219/// @see separatorLight
220/// @see separatorDashed
221/// @see separatorDouble
222/// @see separatorHeavy
223/// @see separatorEmpty
224/// @see separatorRounded
225/// @see separatorStyled
226/// @see separatorCharacter
227///
228/// Add a visual separation in between two elements.
229///
230/// ### Example
231///
232/// ```cpp
233/// // Use 'border' as a function...
234/// Element document = vbox({
235/// text("up"),
236/// separatorLight(),
237/// text("down"),
238/// });
239/// ```
240///
241/// ### Output
242///
243/// ```bash
244/// up
245/// ╍╍╍╍
246/// down
247/// ```
249 return std::make_shared<SeparatorAuto>(DASHED);
250}
251
252/// @brief Draw a vertical or horizontal separation in between two other
253/// elements, using the HEAVY style.
254/// @ingroup dom
255/// @see separator
256/// @see separatorLight
257/// @see separatorDashed
258/// @see separatorDouble
259/// @see separatorHeavy
260/// @see separatorEmpty
261/// @see separatorRounded
262/// @see separatorStyled
263/// @see separatorCharacter
264///
265/// Add a visual separation in between two elements.
266///
267/// ### Example
268///
269/// ```cpp
270/// // Use 'border' as a function...
271/// Element document = vbox({
272/// text("up"),
273/// separatorHeavy(),
274/// text("down"),
275/// });
276/// ```
277///
278/// ### Output
279///
280/// ```bash
281/// up
282/// ━━━━
283/// down
284/// ```
286 return std::make_shared<SeparatorAuto>(HEAVY);
287}
288
289/// @brief Draw a vertical or horizontal separation in between two other
290/// elements, using the DOUBLE style.
291/// @ingroup dom
292/// @see separator
293/// @see separatorLight
294/// @see separatorDashed
295/// @see separatorDouble
296/// @see separatorHeavy
297/// @see separatorEmpty
298/// @see separatorRounded
299/// @see separatorStyled
300/// @see separatorCharacter
301///
302/// Add a visual separation in between two elements.
303///
304/// ### Example
305///
306/// ```cpp
307/// // Use 'border' as a function...
308/// Element document = vbox({
309/// text("up"),
310/// separatorDouble(),
311/// text("down"),
312/// });
313/// ```
314///
315/// ### Output
316///
317/// ```bash
318/// up
319/// ════
320/// down
321/// ```
323 return std::make_shared<SeparatorAuto>(DOUBLE);
324}
325
326/// @brief Draw a vertical or horizontal separation in between two other
327/// elements, using the EMPTY style.
328/// @ingroup dom
329/// @see separator
330/// @see separatorLight
331/// @see separatorDashed
332/// @see separatorDouble
333/// @see separatorHeavy
334/// @see separatorEmpty
335/// @see separatorRounded
336/// @see separatorStyled
337/// @see separatorCharacter
338///
339/// Add a visual separation in between two elements.
340///
341/// ### Example
342///
343/// ```cpp
344/// // Use 'border' as a function...
345/// Element document = vbox({
346/// text("up"),
347/// separator(),
348/// text("down"),
349/// });
350/// ```
351///
352/// ### Output
353///
354/// ```bash
355/// up
356///
357/// down
358/// ```
360 return std::make_shared<SeparatorAuto>(EMPTY);
361}
362
363/// @brief Draw a vertical or horizontal separation in between two other
364/// elements.
365/// @param value the character to fill the separator area.
366/// @ingroup dom
367/// @see separator
368/// @see separatorLight
369/// @see separatorDashed
370/// @see separatorDouble
371/// @see separatorHeavy
372/// @see separatorEmpty
373/// @see separatorRounded
374/// @see separatorStyled
375/// @see separatorCharacter
376///
377/// Add a visual separation in between two elements.
378///
379/// ### Example
380///
381/// ```cpp
382/// // Use 'border' as a function...
383/// Element document = vbox({
384/// text("up"),
385/// separator(),
386/// text("down"),
387/// });
388/// ```
389///
390/// ### Output
391///
392/// ```bash
393/// up
394/// ────
395/// down
396/// ```
398 return std::make_shared<Separator>(std::string(value));
399}
400
401/// @brief Draw a separator in between two element filled with a given pixel.
402/// @ingroup dom
403/// @see separator
404/// @see separatorLight
405/// @see separatorDashed
406/// @see separatorHeavy
407/// @see separatorDouble
408/// @see separatorStyled
409///
410/// ### Example
411///
412/// ```cpp
413/// Cell empty;
414/// Element document = vbox({
415/// text("Up"),
416/// separator(empty),
417/// text("Down"),
418/// })
419/// ```
420///
421/// ### Output
422///
423/// ```bash
424/// Up
425///
426/// Down
427/// ```
428Element separator(Cell pixel) {
429 return std::make_shared<SeparatorWithCell>(std::move(pixel));
430}
431
432/// @brief Draw a horizontal bar, with the area in between left/right colored
433/// differently.
434/// @param left the left limit of the active area.
435/// @param right the right limit of the active area.
436/// @param selected_color the color of the selected area.
437/// @param unselected_color the color of the unselected area.
438///
439/// ### Example
440///
441/// ```cpp
442/// Element document = separatorHSelector(2,5, Color::White, Color::Blue);
443/// ```
445 float right,
446 Color unselected_color,
447 Color selected_color) {
448 class Impl : public Node {
449 public:
450 Impl(float left, float right, Color selected_color, Color unselected_color)
451 : left_(left),
452 right_(right),
453 unselected_color_(unselected_color),
454 selected_color_(selected_color) {}
455 void ComputeRequirement() override {
456 requirement_.min_x = 1;
457 requirement_.min_y = 1;
458 }
459
460 void Render(Screen& screen) override {
461 if (box_.y_max < box_.y_min) {
462 return;
463 }
464
465 // This are the two location with an empty demi-cell.
466 int demi_cell_left = int(left_ * 2.F - 1.F); // NOLINT
467 int demi_cell_right = int(right_ * 2.F + 2.F); // NOLINT
468
469 const int y = box_.y_min;
470 for (int x = box_.x_min; x <= box_.x_max; ++x) {
471 Cell& pixel = screen.CellAt(x, y);
472
473 const int a = (x - box_.x_min) * 2;
474 const int b = a + 1;
475 const bool a_empty = demi_cell_left == a || demi_cell_right == a;
476 const bool b_empty = demi_cell_left == b || demi_cell_right == b;
477
478 if (!a_empty && !b_empty) {
479 pixel.character = "─";
480 pixel.automerge = true;
481 } else {
482 pixel.character = a_empty ? "╶" : "╴"; // NOLINT
483 pixel.automerge = false;
484 }
485
486 if (demi_cell_left <= a && b <= demi_cell_right) {
487 pixel.foreground_color = selected_color_;
488 } else {
489 pixel.foreground_color = unselected_color_;
490 }
491 }
492 }
493
494 float left_;
495 float right_;
496 Color unselected_color_;
497 Color selected_color_;
498 };
499 return std::make_shared<Impl>(left, right, unselected_color, selected_color);
500}
501
502/// @brief Draw an vertical bar, with the area in between up/downcolored
503/// differently.
504/// @param up the left limit of the active area.
505/// @param down the right limit of the active area.
506/// @param selected_color the color of the selected area.
507/// @param unselected_color the color of the unselected area.
508///
509/// ### Example
510///
511/// ```cpp
512/// Element document = separatorHSelector(2,5, Color::White, Color::Blue);
513/// ```
515 float down,
516 Color unselected_color,
517 Color selected_color) {
518 class Impl : public Node {
519 public:
520 Impl(float up, float down, Color unselected_color, Color selected_color)
521 : up_(up),
522 down_(down),
523 unselected_color_(unselected_color),
524 selected_color_(selected_color) {}
525 void ComputeRequirement() override {
526 requirement_.min_x = 1;
527 requirement_.min_y = 1;
528 }
529
530 void Render(Screen& screen) override {
531 if (box_.x_max < box_.x_min) {
532 return;
533 }
534
535 // This are the two location with an empty demi-cell.
536 const int demi_cell_up = int(up_ * 2 - 1);
537 const int demi_cell_down = int(down_ * 2 + 2);
538
539 const int x = box_.x_min;
540 for (int y = box_.y_min; y <= box_.y_max; ++y) {
541 Cell& pixel = screen.CellAt(x, y);
542
543 const int a = (y - box_.y_min) * 2;
544 const int b = a + 1;
545 const bool a_empty = demi_cell_up == a || demi_cell_down == a;
546 const bool b_empty = demi_cell_up == b || demi_cell_down == b;
547
548 if (!a_empty && !b_empty) {
549 pixel.character = "│";
550 pixel.automerge = true;
551 } else {
552 pixel.character = a_empty ? "╷" : "╵"; // NOLINT
553 pixel.automerge = false;
554 }
555
556 if (demi_cell_up <= a && b <= demi_cell_down) {
557 pixel.foreground_color = selected_color_;
558 } else {
559 pixel.foreground_color = unselected_color_;
560 }
561 }
562 }
563
564 float up_;
565 float down_;
566 Color unselected_color_;
567 Color selected_color_;
568 };
569 return std::make_shared<Impl>(up, down, unselected_color, selected_color);
570}
571
572} // namespace ftxui
Element separatorStyled(BorderStyle style)
Draw a vertical or horizontal separation in between two other elements.
Element separatorEmpty()
Draw a vertical or horizontal separation in between two other elements, using the EMPTY style.
Element separatorLight()
Draw a vertical or horizontal separation in between two other elements, using the LIGHT style.
BorderStyle
BorderStyle is an enumeration that represents the different styles of borders that can be applied to ...
Definition elements.hpp:38
Element separatorDashed()
Draw a vertical or horizontal separation in between two other elements, using the DASHED style.
Element separator()
Draw a vertical or horizontal separation in between two other elements.
Element separatorCharacter(std::string_view value)
Draw a vertical or horizontal separation in between two other elements.
Element separatorDouble()
Draw a vertical or horizontal separation in between two other elements, using the DOUBLE style.
Element separatorHeavy()
Draw a vertical or horizontal separation in between two other elements, using the HEAVY style.
@ EMPTY
Definition elements.hpp:44
@ DOUBLE
Definition elements.hpp:42
@ HEAVY
Definition elements.hpp:41
@ DASHED
Definition elements.hpp:40
@ LIGHT
Definition elements.hpp:39
The FTXUI ftxui:: namespace.
Definition animation.hpp:11
Element separatorVSelector(float up, float down, Color unselected_color, Color selected_color)
Draw an vertical bar, with the area in between up/downcolored differently.
std::shared_ptr< Node > Element
Definition elements.hpp:25
FTXUI_EXPORT(DOM) Element separatorCharacter(std Element separatorHSelector(float left, float right, Color unselected_color, Color selected_color)
Draw a horizontal bar, with the area in between left/right colored differently.
int y
Definition elements.hpp:127
void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:105
int value
Definition elements.hpp:188
std::uint8_t left
Definition screen.cpp:142
std::uint8_t down
Definition screen.cpp:145
std::uint8_t right
Definition screen.cpp:144
std::function< void(Cell &)> style_
std::string value_