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