FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/dom/separator.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 <array> // for array, array<>::value_type
5#include <memory> // for make_shared, allocator
6#include <string> // for basic_string, string
7#include <utility> // for move
8
9#include "ftxui/dom/elements.hpp" // for Element, BorderStyle, LIGHT, separator, DOUBLE, EMPTY, HEAVY, separatorCharacter, separatorDouble, separatorEmpty, separatorHSelector, separatorHeavy, separatorLight, separatorStyled, separatorVSelector
10#include "ftxui/dom/node.hpp" // for Node
11#include "ftxui/dom/requirement.hpp" // for Requirement
12#include "ftxui/screen/box.hpp" // for Box
13#include "ftxui/screen/color.hpp" // for Color
14#include "ftxui/screen/pixel.hpp" // for Pixel
15#include "ftxui/screen/screen.hpp" // for Pixel, Screen
16
17namespace ftxui {
18
19namespace {
20using Charset = std::array<std::string, 2>; // NOLINT
21using Charsets = std::array<Charset, 6>; // NOLINT
22// NOLINTNEXTLINE
23const Charsets charsets = {
24 Charset{"│", "─"}, // LIGHT
25 Charset{"╏", "╍"}, // DASHED
26 Charset{"┃", "━"}, // HEAVY
27 Charset{"║", "═"}, // DOUBLE
28 Charset{"│", "─"}, // ROUNDED
29 Charset{" ", " "}, // EMPTY
30};
31
32class Separator : public Node {
33 public:
34 explicit Separator(std::string value) : value_(std::move(value)) {}
35
36 void ComputeRequirement() override {
37 requirement_.min_x = 1;
38 requirement_.min_y = 1;
39 }
40
41 void Render(Screen& screen) override {
42 for (int y = box_.y_min; y <= box_.y_max; ++y) {
43 for (int x = box_.x_min; x <= box_.x_max; ++x) {
44 Pixel& pixel = screen.PixelAt(x, y);
45 pixel.character = value_;
46 pixel.automerge = true;
47 }
48 }
49 }
50
51 std::string value_;
52};
53
54class SeparatorAuto : public Node {
55 public:
56 explicit SeparatorAuto(BorderStyle style) : style_(style) {}
57
58 void ComputeRequirement() override {
59 requirement_.min_x = 1;
60 requirement_.min_y = 1;
61 }
62
63 void Render(Screen& screen) override {
64 const bool is_column = (box_.x_max == box_.x_min);
65 const bool is_line = (box_.y_min == box_.y_max);
66
67 const std::string c =
68 charsets[style_][int(is_line && !is_column)]; // NOLINT
69
70 for (int y = box_.y_min; y <= box_.y_max; ++y) {
71 for (int x = box_.x_min; x <= box_.x_max; ++x) {
72 Pixel& pixel = screen.PixelAt(x, y);
73 pixel.character = c;
74 pixel.automerge = true;
75 }
76 }
77 }
78
80};
81
82class SeparatorWithPixel : public SeparatorAuto {
83 public:
84 explicit SeparatorWithPixel(Pixel pixel)
85 : SeparatorAuto(LIGHT), pixel_(std::move(pixel)) {
86 pixel_.automerge = true;
87 }
88 void Render(Screen& screen) override {
89 for (int y = box_.y_min; y <= box_.y_max; ++y) {
90 for (int x = box_.x_min; x <= box_.x_max; ++x) {
91 screen.PixelAt(x, y) = pixel_;
92 }
93 }
94 }
95
96 private:
97 Pixel pixel_;
98};
99} // namespace
100
101/// @brief 在兩個元素之間繪製垂直或水平分隔線。
102/// @ingroup dom
103/// @see separator
104/// @see separatorLight
105/// @see separatorDashed
106/// @see separatorDouble
107/// @see separatorHeavy
108/// @see separatorEmpty
109/// @see separatorRounded
110/// @see separatorStyled
111/// @see separatorCharacter
112///
113/// 在兩個元素之間添加視覺分隔。
114///
115/// ### 範例
116///
117/// ```cpp
118/// // 使用 'border' 作為函式...
119/// Element document = vbox({
120/// text("up"),
121/// separator(),
122/// text("down"),
123/// });
124/// ```
125///
126/// ### 輸出
127///
128/// ```bash
129/// up
130/// ────
131/// down
132/// ```
134 return std::make_shared<SeparatorAuto>(LIGHT);
135}
136
137/// @brief 在兩個元素之間繪製垂直或水平分隔線。
138/// @param style 分隔線的樣式。
139/// @ingroup dom
140/// @see separator
141/// @see separatorLight
142/// @see separatorDashed
143/// @see separatorDouble
144/// @see separatorHeavy
145/// @see separatorEmpty
146/// @see separatorRounded
147/// @see separatorStyled
148/// @see separatorCharacter
149///
150/// 在兩個元素之間添加視覺分隔。
151///
152/// ### 範例
153///
154/// ```cpp
155/// // 使用 'border' 作為函式...
156/// Element document = vbox({
157/// text("up"),
158/// separatorStyled(DOUBLE),
159/// text("down"),
160/// });
161/// ```
162///
163/// ### 輸出
164///
165/// ```bash
166/// up
167/// ════
168/// down
169/// ```
171 return std::make_shared<SeparatorAuto>(style);
172}
173
174/// @brief 使用 LIGHT 樣式在兩個元素之間繪製垂直或水平分隔線。
175/// @ingroup dom
176/// @see separator
177/// @see separatorLight
178/// @see separatorDashed
179/// @see separatorDouble
180/// @see separatorHeavy
181/// @see separatorEmpty
182/// @see separatorRounded
183/// @see separatorStyled
184/// @see separatorCharacter
185///
186/// 在兩個元素之間添加視覺分隔。
187///
188/// ### 範例
189///
190/// ```cpp
191/// // 使用 'border' 作為函式...
192/// Element document = vbox({
193/// text("up"),
194/// separatorLight(),
195/// text("down"),
196/// });
197/// ```
198///
199/// ### 輸出
200///
201/// ```bash
202/// up
203/// ────
204/// down
205/// ```
207 return std::make_shared<SeparatorAuto>(LIGHT);
208}
209
210/// @brief 使用 DASHED 樣式在兩個元素之間繪製垂直或水平分隔線。
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/// 在兩個元素之間添加視覺分隔。
223///
224/// ### 範例
225///
226/// ```cpp
227/// // 使用 'border' 作為函式...
228/// Element document = vbox({
229/// text("up"),
230/// separatorLight(),
231/// text("down"),
232/// });
233/// ```
234///
235/// ### 輸出
236///
237/// ```bash
238/// up
239/// ╍╍╍╍
240/// down
241/// ```
243 return std::make_shared<SeparatorAuto>(DASHED);
244}
245
246/// @brief 使用 HEAVY 樣式在兩個元素之間繪製垂直或水平分隔線。
247/// @ingroup dom
248/// @see separator
249/// @see separatorLight
250/// @see separatorDashed
251/// @see separatorDouble
252/// @see separatorHeavy
253/// @see separatorEmpty
254/// @see separatorRounded
255/// @see separatorStyled
256/// @see separatorCharacter
257///
258/// 在兩個元素之間添加視覺分隔。
259///
260/// ### 範例
261///
262/// ```cpp
263/// // 使用 'border' 作為函式...
264/// Element document = vbox({
265/// text("up"),
266/// separatorHeavy(),
267/// text("down"),
268/// });
269/// ```
270///
271/// ### 輸出
272///
273/// ```bash
274/// up
275/// ━━━━
276/// down
277/// ```
279 return std::make_shared<SeparatorAuto>(HEAVY);
280}
281
282/// @brief 使用 DOUBLE 樣式在兩個元素之間繪製垂直或水平分隔線。
283/// @ingroup dom
284/// @see separator
285/// @see separatorLight
286/// @see separatorDashed
287/// @see separatorDouble
288/// @see separatorHeavy
289/// @see separatorEmpty
290/// @see separatorRounded
291/// @see separatorStyled
292/// @see separatorCharacter
293///
294/// 在兩個元素之間添加視覺分隔。
295///
296/// ### 範例
297///
298/// ```cpp
299/// // 使用 'border' 作為函式...
300/// Element document = vbox({
301/// text("up"),
302/// separatorDouble(),
303/// text("down"),
304/// });
305/// ```
306///
307/// ### 輸出
308///
309/// ```bash
310/// up
311/// ════
312/// down
313/// ```
315 return std::make_shared<SeparatorAuto>(DOUBLE);
316}
317
318/// @brief 使用 EMPTY 樣式在兩個元素之間繪製垂直或水平分隔線。
319/// @ingroup dom
320/// @see separator
321/// @see separatorLight
322/// @see separatorDashed
323/// @see separatorDouble
324/// @see separatorHeavy
325/// @see separatorEmpty
326/// @see separatorRounded
327/// @see separatorStyled
328/// @see separatorCharacter
329///
330/// 在兩個元素之間添加視覺分隔。
331///
332/// ### 範例
333///
334/// ```cpp
335/// // 使用 'border' 作為函式...
336/// Element document = vbox({
337/// text("up"),
338/// separator(),
339/// text("down"),
340/// });
341/// ```
342///
343/// ### 輸出
344///
345/// ```bash
346/// up
347///
348/// down
349/// ```
351 return std::make_shared<SeparatorAuto>(EMPTY);
352}
353
354/// @brief 在兩個元素之間繪製垂直或水平分隔線。
355/// @param value 用於填充分隔線區域的字元。
356/// @ingroup dom
357/// @see separator
358/// @see separatorLight
359/// @see separatorDashed
360/// @see separatorDouble
361/// @see separatorHeavy
362/// @see separatorEmpty
363/// @see separatorRounded
364/// @see separatorStyled
365/// @see separatorCharacter
366///
367/// 在兩個元素之間添加視覺分隔。
368///
369/// ### 範例
370///
371/// ```cpp
372/// // 使用 'border' 作為函式...
373/// Element document = vbox({
374/// text("up"),
375/// separator(),
376/// text("down"),
377/// });
378/// ```
379///
380/// ### 輸出
381///
382/// ```bash
383/// up
384/// ────
385/// down
386/// ```
387Element separatorCharacter(std::string value) {
388 return std::make_shared<Separator>(std::move(value));
389}
390
391/// @brief 在兩個元素之間繪製一個由給定像素填充的分隔線。
392/// @ingroup dom
393/// @see separator
394/// @see separatorLight
395/// @see separatorDashed
396/// @see separatorHeavy
397/// @see separatorDouble
398/// @see separatorStyled
399///
400/// ### 範例
401///
402/// ```cpp
403/// Pixel empty;
404/// Element document = vbox({
405/// text("Up"),
406/// separator(empty),
407/// text("Down"),
408/// })
409/// ```
410///
411/// ### 輸出
412///
413/// ```bash
414/// Up
415///
416/// Down
417/// ```
419 return std::make_shared<SeparatorWithPixel>(std::move(pixel));
420}
421
422/// @brief 繪製一個水平條,其中左右兩側之間的區域以不同顏色顯示。
423/// @param left 活躍區域的左限。
424/// @param right 活躍區域的右限。
425/// @param selected_color 選定區域的顏色。
426/// @param unselected_color 未選定區域的顏色。
427///
428/// ### 範例
429///
430/// ```cpp
431/// Element document = separatorHSelector(2,5, Color::White, Color::Blue);
432/// ```
434 float right,
435 Color unselected_color,
436 Color selected_color) {
437 class Impl : public Node {
438 public:
439 Impl(float left, float right, Color selected_color, Color unselected_color)
440 : left_(left),
441 right_(right),
442 unselected_color_(unselected_color),
443 selected_color_(selected_color) {}
444 void ComputeRequirement() override {
445 requirement_.min_x = 1;
446 requirement_.min_y = 1;
447 }
448
449 void Render(Screen& screen) override {
450 if (box_.y_max < box_.y_min) {
451 return;
452 }
453
454 // This are the two location with an empty demi-cell.
455 int demi_cell_left = int(left_ * 2.F - 1.F); // NOLINT
456 int demi_cell_right = int(right_ * 2.F + 2.F); // NOLINT
457
458 const int y = box_.y_min;
459 for (int x = box_.x_min; x <= box_.x_max; ++x) {
460 Pixel& pixel = screen.PixelAt(x, y);
461
462 const int a = (x - box_.x_min) * 2;
463 const int b = a + 1;
464 const bool a_empty = demi_cell_left == a || demi_cell_right == a;
465 const bool b_empty = demi_cell_left == b || demi_cell_right == b;
466
467 if (!a_empty && !b_empty) {
468 pixel.character = "─";
469 pixel.automerge = true;
470 } else {
471 pixel.character = a_empty ? "╶" : "╴"; // NOLINT
472 pixel.automerge = false;
473 }
474
475 if (demi_cell_left <= a && b <= demi_cell_right) {
476 pixel.foreground_color = selected_color_;
477 } else {
478 pixel.foreground_color = unselected_color_;
479 }
480 }
481 }
482
483 float left_;
484 float right_;
485 Color unselected_color_;
486 Color selected_color_;
487 };
488 return std::make_shared<Impl>(left, right, unselected_color, selected_color);
489}
490
491/// @brief 繪製一個垂直條,其中上方/下方之間的區域以不同顏色顯示。
492/// @param up 活躍區域的上限。
493/// @param down 活躍區域的下限。
494/// @param selected_color 選定區域的顏色。
495/// @param unselected_color 未選定區域的顏色。
496///
497/// ### 範例
498///
499/// ```cpp
500/// Element document = separatorHSelector(2,5, Color::White, Color::Blue);
501/// ```
503 float down,
504 Color unselected_color,
505 Color selected_color) {
506 class Impl : public Node {
507 public:
508 Impl(float up, float down, Color unselected_color, Color selected_color)
509 : up_(up),
510 down_(down),
511 unselected_color_(unselected_color),
512 selected_color_(selected_color) {}
513 void ComputeRequirement() override {
514 requirement_.min_x = 1;
515 requirement_.min_y = 1;
516 }
517
518 void Render(Screen& screen) override {
519 if (box_.x_max < box_.x_min) {
520 return;
521 }
522
523 // This are the two location with an empty demi-cell.
524 const int demi_cell_up = int(up_ * 2 - 1);
525 const int demi_cell_down = int(down_ * 2 + 2);
526
527 const int x = box_.x_min;
528 for (int y = box_.y_min; y <= box_.y_max; ++y) {
529 Pixel& pixel = screen.PixelAt(x, y);
530
531 const int a = (y - box_.y_min) * 2;
532 const int b = a + 1;
533 const bool a_empty = demi_cell_up == a || demi_cell_down == a;
534 const bool b_empty = demi_cell_up == b || demi_cell_down == b;
535
536 if (!a_empty && !b_empty) {
537 pixel.character = "│";
538 pixel.automerge = true;
539 } else {
540 pixel.character = a_empty ? "╷" : "╵"; // NOLINT
541 pixel.automerge = false;
542 }
543
544 if (demi_cell_up <= a && b <= demi_cell_down) {
545 pixel.foreground_color = selected_color_;
546 } else {
547 pixel.foreground_color = unselected_color_;
548 }
549 }
550 }
551
552 float up_;
553 float down_;
554 Color unselected_color_;
555 Color selected_color_;
556 };
557 return std::make_shared<Impl>(up, down, unselected_color, selected_color);
558}
559
560} // namespace ftxui
節點是DOM樹中所有元素的基底類別。
Definition node.hpp:34
Element separatorStyled(BorderStyle)
在兩個元素之間繪製垂直或水平分隔線。
Element separatorEmpty()
使用 EMPTY 樣式在兩個元素之間繪製垂直或水平分隔線。
Element separatorLight()
使用 LIGHT 樣式在兩個元素之間繪製垂直或水平分隔線。
Element separatorDashed()
使用 DASHED 樣式在兩個元素之間繪製垂直或水平分隔線。
Element separatorCharacter(std::string)
在兩個元素之間繪製垂直或水平分隔線。
Element separator()
在兩個元素之間繪製垂直或水平分隔線。
void Render(Screen &screen, const Element &element)
在 ftxui::Screen 上顯示元素。
Definition node.cpp:82
Element separatorDouble()
使用 DOUBLE 樣式在兩個元素之間繪製垂直或水平分隔線。
Element separatorHeavy()
使用 HEAVY 樣式在兩個元素之間繪製垂直或水平分隔線。
BorderStyle
BorderStyle 是一個列舉,表示可以應用於終端機 UI 元素的不同邊框樣式。
Definition elements.hpp:32
@ EMPTY
Definition elements.hpp:38
@ DOUBLE
Definition elements.hpp:36
@ HEAVY
Definition elements.hpp:35
@ DASHED
Definition elements.hpp:34
@ LIGHT
Definition elements.hpp:33
Color foreground_color
Definition pixel.hpp:48
std::string character
Definition pixel.hpp:44
Pixel & PixelAt(int x, int y)
存取給定位置的單元格 (Pixel)。
Definition image.cpp:43
bool automerge
Definition pixel.hpp:35
Color 是一個在終端使用者介面中表示顏色的類別。
Definition color.hpp:20
像素的矩形網格。
Definition screen.hpp:26
一個 Unicode 字元及其相關樣式。
Definition pixel.hpp:14
FTXUI 的 ftxui:: 命名空間
Definition animation.hpp:10
Element separatorVSelector(float up, float down, Color unselected_color, Color selected_color)
繪製一個垂直條,其中上方/下方之間的區域以不同顏色顯示。
std::shared_ptr< Node > Element
Definition elements.hpp:22
Element separatorHSelector(float left, float right, Color unselected_color, Color selected_color)
繪製一個水平條,其中左右兩側之間的區域以不同顏色顯示。
void Render(Screen &screen, const Element &element)
std::uint8_t left
Definition screen.cpp:130
std::uint8_t down
Definition screen.cpp:133
std::uint8_t right
Definition screen.cpp:132
std::function< void(Pixel &)> style_
std::string value_