FTXUI 7.0.3
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 他の2つの要素の間に垂直または水平の区切り線を描画します。
104/// @ingroup dom
105/// @see separator
106/// @see separatorLight
107/// @see separatorDashed
108/// @see separatorDouble
109/// @see separatorHeavy
110/// @see separatorEmpty
111/// @see separatorRounded
112/// @see separatorStyled
113/// @see separatorCharacter
114///
115/// 2つの要素間に視覚的な区切りを追加します。
116///
117/// ### Example
118///
119/// ```cpp
120/// // 関数として \'border\' を使用...
121/// Element document = vbox({
122/// text("up"),
123/// separator(),
124/// text("down"),
125/// });
126Element separator() {
127 return std::make_shared<SeparatorAuto>(LIGHT);
128}
129
130/// @brief 他の2つの要素の間に垂直または水平の区切り線を描画します。
131/// @param style 区切り線のスタイル。
132/// @ingroup dom
133/// @see separator
134/// @see separatorLight
135/// @see separatorDashed
136/// @see separatorDouble
137/// @see separatorHeavy
138/// @see separatorEmpty
139/// @see separatorRounded
140/// @see separatorStyled
141/// @see separatorCharacter
142///
143/// 2つの要素間に視覚的な区切りを追加します。
144///
145/// ### Example
146///
147/// ```cpp
148/// // 関数として \'border\' を使用...
149/// Element document = vbox({
150/// text("up"),
151/// separatorStyled(DOUBLE),
152/// text("down"),
153/// });
155 return std::make_shared<SeparatorAuto>(style);
156}
157
158/// @brief 他の2つの要素の間にLIGHTスタイルで垂直または水平の区切り線を描画します。
159/// @ingroup dom
160/// @see separator
161/// @see separatorLight
162/// @see separatorDashed
163/// @see separatorDouble
164/// @see separatorHeavy
165/// @see separatorEmpty
166/// @see separatorRounded
167/// @see separatorStyled
168/// @see separatorCharacter
169///
170/// 2つの要素間に視覚的な区切りを追加します。
171///
172/// ### Example
173///
174/// ```cpp
175/// // 関数として \'border\' を使用...
176/// Element document = vbox({
177/// text("up"),
178/// separatorLight(),
179/// text("down"),
180/// });
181Element separatorLight() {
182 return std::make_shared<SeparatorAuto>(LIGHT);
183}
184
185/// @brief 他の2つの要素の間にDASHEDスタイルで垂直または水平の区切り線を描画します。
186/// @ingroup dom
187/// @see separator
188/// @see separatorLight
189/// @see separatorDashed
190/// @see separatorDouble
191/// @see separatorHeavy
192/// @see separatorEmpty
193/// @see separatorRounded
194/// @see separatorStyled
195/// @see separatorCharacter
196///
197/// 2つの要素間に視覚的な区切りを追加します。
198///
199/// ### Example
200///
201/// ```cpp
202/// // 関数として \'border\' を使用...
203/// Element document = vbox({
204/// text("up"),
205/// separatorDashed(),
206/// text("down"),
207/// });
209 return std::make_shared<SeparatorAuto>(DASHED);
210}
211
212/// @brief 他の2つの要素の間にHEAVYスタイルで垂直または水平の区切り線を描画します。
213/// @ingroup dom
214/// @see separator
215/// @see separatorLight
216/// @see separatorDashed
217/// @see separatorDouble
218/// @see separatorHeavy
219/// @see separatorEmpty
220/// @see separatorRounded
221/// @see separatorStyled
222/// @see separatorCharacter
223///
224/// 2つの要素間に視覚的な区切りを追加します。
225///
226/// ### Example
227///
228/// ```cpp
229/// // 関数として \'border\' を使用...
230/// Element document = vbox({
231/// text("up"),
232/// separatorHeavy(),
233/// text("down"),
234/// });
235Element separatorHeavy() {
236 return std::make_shared<SeparatorAuto>(HEAVY);
237}
238
239/// @brief 他の2つの要素の間にDOUBLEスタイルで垂直または水平の区切り線を描画します。
240/// @ingroup dom
241/// @see separator
242/// @see separatorLight
243/// @see separatorDashed
244/// @see separatorDouble
245/// @see separatorHeavy
246/// @see separatorEmpty
247/// @see separatorRounded
248/// @see separatorStyled
249/// @see separatorCharacter
250///
251/// 2つの要素間に視覚的な区切りを追加します。
252///
253/// ### Example
254///
255/// ```cpp
256/// // 関数として \'border\' を使用...
257/// Element document = vbox({
258/// text("up"),
259/// separatorDouble(),
260/// text("down"),
261/// });
263 return std::make_shared<SeparatorAuto>(DOUBLE);
264}
265
266/// @brief 他の2つの要素の間にEMPTYスタイルで垂直または水平の区切り線を描画します。
267/// @ingroup dom
268/// @see separator
269/// @see separatorLight
270/// @see separatorDashed
271/// @see separatorDouble
272/// @see separatorHeavy
273/// @see separatorEmpty
274/// @see separatorRounded
275/// @see separatorStyled
276/// @see separatorCharacter
277///
278/// 2つの要素間に視覚的な区切りを追加します。
279///
280/// ### Example
281///
282/// ```cpp
283/// // 関数として \'border\' を使用...
284/// Element document = vbox({
285/// text("up"),
286/// separatorEmpty(),
287/// text("down"),
288/// });
289/// ```
290///
291/// ### Output
292///
293/// ```bash
294/// up
295///
296/// down
297/// ```
299 return std::make_shared<SeparatorAuto>(EMPTY);
300}
301
302/// @brief 他の2つの要素の間に垂直または水平の区切り線を描画します。
303/// @param value 区切り領域を埋める文字。
304/// @ingroup dom
305/// @see separator
306/// @see separatorLight
307/// @see separatorDashed
308/// @see separatorDouble
309/// @see separatorHeavy
310/// @see separatorEmpty
311/// @see separatorRounded
312/// @see separatorStyled
313/// @see separatorCharacter
314///
315/// 2つの要素間に視覚的な区切りを追加します。
316///
317/// ### Example
318///
319/// ```cpp
320/// // 関数として \'border\' を使用...
321/// Element document = vbox({
322/// text("up"),
323/// separatorCharacter("-"),
324/// text("down"),
325/// });
326///
327/// ### Output
328///
329/// ```bash
330/// up
331/// ────
332/// down
333/// ```
334Element separatorCharacter(std::string_view value) {
335 return std::make_shared<Separator>(std::string(value));
336}
337
338/// @brief 与えられたピクセルで塗りつぶされた2つの要素の間にセパレーターを描画する。
339/// @ingroup dom
340/// @see separator
341/// @see separatorLight
342/// @see separatorDashed
343/// @see separatorHeavy
344/// @see separatorDouble
345/// @see separatorStyled
346///
347/// ### Example
348///
349/// ```cpp
350/// Cell empty;
351/// Element document = vbox({
352/// text("Up"),
353/// separator(empty),
354/// text("Down"),
355/// })
356/// ```
357///
358/// ### Output
359///
360/// ```bash
361/// Up
362///
363/// Down
364/// ```
365Element separator(Cell pixel) {
366 return std::make_shared<SeparatorWithCell>(std::move(pixel));
367}
368
369/// @brief 左右の領域が異なる色で表示される水平バーを描画します。
370/// @param left アクティブ領域の左端。
371/// @param right アクティブ領域の右端。
372/// @param selected_color 選択された領域の色。
373/// @param unselected_color 選択されていない領域の色。
374///
375/// ### 例
376///
377/// ```cpp
378/// Element document = separatorHSelector(2,5, Color::White, Color::Blue);
379/// ```
381 float right,
382 Color unselected_color,
383 Color selected_color) {
384 class Impl : public Node {
385 public:
386 Impl(float left, float right, Color selected_color, Color unselected_color)
387 : left_(left),
388 right_(right),
389 unselected_color_(unselected_color),
390 selected_color_(selected_color) {}
391 void ComputeRequirement() override {
392 requirement_.min_x = 1;
393 requirement_.min_y = 1;
394 }
395
396 void Render(Screen& screen) override {
397 if (box_.y_max < box_.y_min) {
398 return;
399 }
400
401 // これは、空のデミセルを持つ2つの位置です。
402 int demi_cell_left = int(left_ * 2.F - 1.F); // NOLINT
403 int demi_cell_right = int(right_ * 2.F + 2.F); // NOLINT
404
405 const int y = box_.y_min;
406 for (int x = box_.x_min; x <= box_.x_max; ++x) {
407 Cell& pixel = screen.CellAt(x, y);
408
409 const int a = (x - box_.x_min) * 2;
410 const int b = a + 1;
411 const bool a_empty = demi_cell_left == a || demi_cell_right == a;
412 const bool b_empty = demi_cell_left == b || demi_cell_right == b;
413
414 if (!a_empty && !b_empty) {
415 pixel.character = "─";
416 pixel.automerge = true;
417 } else {
418 pixel.character = a_empty ? "╶" : "╴"; // NOLINT
419 pixel.automerge = false;
420 }
421
422 if (demi_cell_left <= a && b <= demi_cell_right) {
423 pixel.foreground_color = selected_color_;
424 } else {
425 pixel.foreground_color = unselected_color_;
426 }
427 }
428 }
429
430 float left_;
431 float right_;
432 Color unselected_color_;
433 Color selected_color_;
434 };
435 return std::make_shared<Impl>(left, right, unselected_color, selected_color);
436}
437
438/// @brief 上下の領域が異なる色で表示される垂直バーを描画します。
439/// @param up アクティブ領域の上端。
440/// @param down アクティブ領域の下端。
441/// @param selected_color 選択された領域の色。
442/// @param unselected_color 選択されていない領域の色。
443///
444/// ### 例
445///
446/// ```cpp
447/// Element document = separatorVSelector(2,5, Color::White, Color::Blue);
448/// ```
450 float down,
451 Color unselected_color,
452 Color selected_color) {
453 class Impl : public Node {
454 public:
455 Impl(float up, float down, Color unselected_color, Color selected_color)
456 : up_(up),
457 down_(down),
458 unselected_color_(unselected_color),
459 selected_color_(selected_color) {}
460 void ComputeRequirement() override {
461 requirement_.min_x = 1;
462 requirement_.min_y = 1;
463 }
464
465 void Render(Screen& screen) override {
466 if (box_.x_max < box_.x_min) {
467 return;
468 }
469
470 // これは、空のデミセルを持つ2つの位置です。
471 const int demi_cell_up = int(up_ * 2 - 1);
472 const int demi_cell_down = int(down_ * 2 + 2);
473
474 const int x = box_.x_min;
475 for (int y = box_.y_min; y <= box_.y_max; ++y) {
476 Cell& pixel = screen.CellAt(x, y);
477
478 const int a = (y - box_.y_min) * 2;
479 const int b = a + 1;
480 const bool a_empty = demi_cell_up == a || demi_cell_down == a;
481 const bool b_empty = demi_cell_up == b || demi_cell_down == b;
482
483 if (!a_empty && !b_empty) {
484 pixel.character = "│";
485 pixel.automerge = true;
486 } else {
487 pixel.character = a_empty ? "╷" : "╵"; // NOLINT
488 pixel.automerge = false;
489 }
490
491 if (demi_cell_up <= a && b <= demi_cell_down) {
492 pixel.foreground_color = selected_color_;
493 } else {
494 pixel.foreground_color = unselected_color_;
495 }
496 }
497 }
498
499 float up_;
500 float down_;
501 Color unselected_color_;
502 Color selected_color_;
503 };
504 return std::make_shared<Impl>(up, down, unselected_color, selected_color);
505}
506
507} // namespace ftxui
Element separatorStyled(BorderStyle style)
他の2つの要素の間に垂直または水平の区切り線を描画します。
Element separatorEmpty()
他の2つの要素の間にEMPTYスタイルで垂直または水平の区切り線を描画します。
BorderStyle
BorderStyleは、ターミナルUIの要素に適用できる様々なボーダースタイルを表す列挙型です。
Definition elements.hpp:35
Element separatorDashed()
他の2つの要素の間にLIGHTスタイルで垂直または水平の区切り線を描画します。
Element separatorDouble()
他の2つの要素の間にHEAVYスタイルで垂直または水平の区切り線を描画します。
@ EMPTY
Definition elements.hpp:41
@ DOUBLE
Definition elements.hpp:39
@ HEAVY
Definition elements.hpp:38
@ DASHED
Definition elements.hpp:37
@ LIGHT
Definition elements.hpp:36
FTXUI ftxui::名前空間
Definition animation.hpp:11
Element separatorVSelector(float up, float down, Color unselected_color, Color selected_color)
std::shared_ptr< Node > Element
Definition elements.hpp:25
int y
Definition elements.hpp:131
void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:105
FTXUI_EXPORT(DOM) Element separatorCharacter(std Element separatorHSelector(float left, float right, Color unselected_color, Color selected_color)
int value
Definition elements.hpp:192
std::uint8_t left
Definition screen.cpp:147
std::uint8_t down
Definition screen.cpp:150
std::uint8_t right
Definition screen.cpp:149
std::function< void(Cell &)> style_
std::string value_