FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
src/ftxui/dom/border.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// このソースコードの使用は、LICENSEファイルにあるMITライセンスに準拠します。
3#include <algorithm> // for max
4#include <array> // for array
5#include <ftxui/screen/color.hpp> // for Color
6#include <memory> // for allocator, make_shared, __shared_ptr_access
7#include <optional> // for optional, nullopt
8#include <string> // for basic_string, string
9#include <utility> // for move
10
11#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
12#include "ftxui/dom/node.hpp" // for Node, Elements
13#include "ftxui/dom/requirement.hpp" // for Requirement
14#include "ftxui/screen/box.hpp" // for Box
15#include "ftxui/screen/pixel.hpp" // for Pixel
16#include "ftxui/screen/screen.hpp" // for Pixel, Screen
17
18namespace ftxui {
19
20namespace {
21using Charset = std::array<std::string, 6>; // NOLINT
22using Charsets = std::array<Charset, 6>; // NOLINT
23// NOLINTNEXTLINE
24static Charsets simple_border_charset = {
25 Charset{"┌", "┐", "└", "┘", "─", "│"}, // LIGHT
26 Charset{"┏", "┓", "┗", "┛", "╍", "╏"}, // DASHED
27 Charset{"┏", "┓", "┗", "┛", "━", "┃"}, // HEAVY
28 Charset{"╔", "╗", "╚", "╝", "═", "║"}, // DOUBLE
29 Charset{"╭", "╮", "╰", "╯", "─", "│"}, // ROUNDED
30 Charset{" ", " ", " ", " ", " ", " "}, // EMPTY
31};
32
33// 参考までに、通常のボーダーの文字セットを以下に示します:
34 public:
35 Border(Elements children,
36 BorderStyle style,
37 std::optional<Color> foreground_color = std::nullopt)
38 : Node(std::move(children)),
39 charset_(simple_border_charset[style]) // NOLINT
40 ,
41 foreground_color_(foreground_color) {} // NOLINT
42
43 const Charset& charset_; // NOLINT
44 std::optional<Color> foreground_color_;
45
46 void ComputeRequirement() override {
48 requirement_ = children_[0]->requirement();
49 requirement_.min_x += 2;
50 requirement_.min_y += 2;
51 if (children_.size() == 2) {
52 requirement_.min_x =
53 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
54 }
55 requirement_.focused.box.x_min++;
56 requirement_.focused.box.x_max++;
57 requirement_.focused.box.y_min++;
58 requirement_.focused.box.y_max++;
59 }
60
61 void SetBox(Box box) override {
62 Node::SetBox(box);
63 if (children_.size() == 2) {
64 Box title_box;
65 title_box.x_min = box.x_min + 1;
66 title_box.x_max = std::min(box.x_max - 1,
67 box.x_min + children_[1]->requirement().min_x);
68 title_box.y_min = box.y_min;
69 title_box.y_max = box.y_min;
70 children_[1]->SetBox(title_box);
71 }
72 box.x_min++;
73 box.x_max--;
74 box.y_min++;
75 box.y_max--;
76 children_[0]->SetBox(box);
77 }
78
79 void Render(Screen& screen) override {
80 // コンテンツを描画します。
81 children_[0]->Render(screen);
82
83 // ボーダーを描画します。
84 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
85 return;
86 }
87
88 screen.at(box_.x_min, box_.y_min) = charset_[0]; // NOLINT
89 screen.at(box_.x_max, box_.y_min) = charset_[1]; // NOLINT
90 screen.at(box_.x_min, box_.y_max) = charset_[2]; // NOLINT
91 screen.at(box_.x_max, box_.y_max) = charset_[3]; // NOLINT
92
93 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
94 Pixel& p1 = screen.PixelAt(x, box_.y_min);
95 Pixel& p2 = screen.PixelAt(x, box_.y_max);
96 p1.character = charset_[4]; // NOLINT
97 p2.character = charset_[4]; // NOLINT
98 p1.automerge = true;
99 p2.automerge = true;
100 }
101 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
102 Pixel& p3 = screen.PixelAt(box_.x_min, y);
103 Pixel& p4 = screen.PixelAt(box_.x_max, y);
104 p3.character = charset_[5]; // NOLINT
105 p4.character = charset_[5]; // NOLINT
106 p3.automerge = true;
107 p4.automerge = true;
108 }
109
110 // タイトルを描画します。
111 if (children_.size() == 2) {
112 children_[1]->Render(screen);
113 }
114
115 // ボーダーの色を描画します。
116 if (foreground_color_) {
117 for (int x = box_.x_min; x <= box_.x_max; ++x) {
118 screen.PixelAt(x, box_.y_min).foreground_color = *foreground_color_;
119 screen.PixelAt(x, box_.y_max).foreground_color = *foreground_color_;
120 }
121 for (int y = box_.y_min; y <= box_.y_max; ++y) {
122 screen.PixelAt(box_.x_min, y).foreground_color = *foreground_color_;
123 screen.PixelAt(box_.x_max, y).foreground_color = *foreground_color_;
124 }
125 }
126 }
127};
128
129// 参考までに、通常のボーダーの文字セットを以下に示します:
130class BorderPixel : public Node {
131 public:
132 BorderPixel(Elements children, Pixel pixel)
133 : Node(std::move(children)), pixel_(std::move(pixel)) {}
134
135 private:
136 Pixel pixel_;
137
138 void ComputeRequirement() override {
140 requirement_ = children_[0]->requirement();
141 requirement_.min_x += 2;
142 requirement_.min_y += 2;
143 if (children_.size() == 2) {
145 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
146 }
147
149 }
150
151 void SetBox(Box box) override {
152 Node::SetBox(box);
153 if (children_.size() == 2) {
154 Box title_box;
155 title_box.x_min = box.x_min + 1;
156 title_box.x_max = box.x_max - 1;
157 title_box.y_min = box.y_min;
158 title_box.y_max = box.y_min;
159 children_[1]->SetBox(title_box);
160 }
161 box.x_min++;
162 box.x_max--;
163 box.y_min++;
164 box.y_max--;
165 children_[0]->SetBox(box);
166 }
167
168 void Render(Screen& screen) override {
169 // コンテンツを描画します。
170 children_[0]->Render(screen);
171
172 // ボーダーを描画します。
173 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
174 return;
175 }
176
177 screen.PixelAt(box_.x_min, box_.y_min) = pixel_;
178 screen.PixelAt(box_.x_max, box_.y_min) = pixel_;
179 screen.PixelAt(box_.x_min, box_.y_max) = pixel_;
180 screen.PixelAt(box_.x_max, box_.y_max) = pixel_;
181
182 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
183 screen.PixelAt(x, box_.y_min) = pixel_;
184 screen.PixelAt(x, box_.y_max) = pixel_;
185 }
186 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
187 screen.PixelAt(box_.x_min, y) = pixel_;
188 screen.PixelAt(box_.x_max, y) = pixel_;
189 }
190 }
191};
192} // namespace
193
194/// @brief 要素の周囲にボーダーを描画します。
195/// @ingroup dom
196/// @see border
197/// @see borderLight
198/// @see borderDashed
199/// @see borderDouble
200/// @see borderHeavy
201/// @see borderEmpty
202/// @see borderRounded
203/// @see borderStyled
204/// @see borderWith
205///
206/// 要素の周囲にボーダーを追加します
207///
208/// ### 例
209///
210/// ```cpp
211/// // 関数として'border'を使用する...
212/// Element document = border(text("The element"));
213///
214/// // ...または'パイプ'として。
215/// Element document = text("The element") | border;
216/// ```
217///
218/// ### 出力
219///
220/// ```bash
221/// ┌───────────┐
222/// │The element│
223/// └───────────┘
224/// ```
225Element border(Element child) {
226 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
227}
228
229/// @brief borderと同じですが、要素の周囲に一定のピクセルを使用します。
230/// @ingroup dom
231/// @see border
232Decorator borderWith(const Pixel& pixel) {
233 return [pixel](Element child) {
234 return std::make_shared<BorderPixel>(unpack(std::move(child)), pixel);
235 };
236}
237
238/// @brief borderと同じですが、異なるスタイルを使用します。
239/// @ingroup dom
240/// @see border
241Decorator borderStyled(BorderStyle style) {
242 return [style](Element child) {
243 return std::make_shared<Border>(unpack(std::move(child)), style);
244 };
245}
246
247/// @brief borderと同じですが、前景色を使用します。
248/// @ingroup dom
249/// @see border
250Decorator borderStyled(Color foreground_color) {
251 return [foreground_color](Element child) {
252 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED,
253 foreground_color);
254 };
255}
256
257/// @brief borderと同じですが、前景色と異なるスタイルを使用します
258/// @ingroup dom
259/// @see border
260Decorator borderStyled(BorderStyle style, Color foreground_color) {
261 return [style, foreground_color](Element child) {
262 return std::make_shared<Border>(unpack(std::move(child)), style,
263 foreground_color);
264 };
265}
266
267/// @brief 要素の周囲に破線のボーダーを描画します。
268/// @ingroup dom
269/// @see border
270/// @see borderLight
271/// @see borderDashed
272/// @see borderDouble
273/// @see borderHeavy
274/// @see borderRounded
275/// @see borderEmpty
276/// @see borderStyled
277/// @see borderWith
278///
279/// 要素の周囲にボーダーを追加します
280///
281/// ### 例
282///
283/// ```cpp
284/// // 関数として'borderDash'を使用する...
285/// Element document = borderDash(text("The element"));
286///
287/// // ...または'パイプ'として。
288/// Element document = text("The element") | borderDAsh;
289/// ```
290///
291/// ### 出力
292///
293/// ```bash
294/// ┏╍╍╍╍╍╍╍╍╍╍╍╍╍╍┓
295/// ╏The element ╏
296/// ┗╍╍╍╍╍╍╍╍╍╍╍╍╍╍┛
297/// ```
298Element borderDashed(Element child) {
299 return std::make_shared<Border>(unpack(std::move(child)), DASHED);
300}
301
302/// @brief 要素の周囲に細いボーダーを描画します。
303/// @ingroup dom
304/// @see border
305/// @see borderLight
306/// @see borderDashed
307/// @see borderDouble
308/// @see borderHeavy
309/// @see borderRounded
310/// @see borderEmpty
311/// @see borderStyled
312/// @see borderWith
313///
314/// 要素の周囲にボーダーを追加します
315///
316/// ### 例
317///
318/// ```cpp
319/// // 関数として'borderLight'を使用する...
320/// Element document = borderLight(text("The element"));
321///
322/// // ...または'パイプ'として。
323/// Element document = text("The element") | borderLight;
324/// ```
325///
326/// ### 出力
327///
328/// ```bash
329/// ┌──────────────┐
330/// │The element │
331/// └──────────────┘
332/// ```
333Element borderLight(Element child) {
334 return std::make_shared<Border>(unpack(std::move(child)), LIGHT);
335}
336
337/// @brief 要素の周囲に太いボーダーを描画します。
338/// @ingroup dom
339/// @see border
340/// @see borderLight
341/// @see borderDashed
342/// @see borderDouble
343/// @see borderHeavy
344/// @see borderRounded
345/// @see borderEmpty
346/// @see borderStyled
347/// @see borderWith
348///
349/// 要素の周囲にボーダーを追加します
350///
351/// ### 例
352///
353/// ```cpp
354/// // 関数として'borderHeavy'を使用する...
355/// Element document = borderHeavy(text("The element"));
356///
357/// // ...または'パイプ'として。
358/// Element document = text("The element") | borderHeavy;
359/// ```
360///
361/// ### 出力
362///
363/// ```bash
364/// ┏━━━━━━━━━━━━━━┓
365/// ┃The element ┃
366/// ┗━━━━━━━━━━━━━━┛
367/// ```
368Element borderHeavy(Element child) {
369 return std::make_shared<Border>(unpack(std::move(child)), HEAVY);
370}
371
372/// @brief 要素の周囲に二重線のボーダーを描画します。
373/// @ingroup dom
374/// @see border
375/// @see borderLight
376/// @see borderDashed
377/// @see borderDouble
378/// @see borderHeavy
379/// @see borderRounded
380/// @see borderEmpty
381/// @see borderStyled
382/// @see borderWith
383///
384/// 要素の周囲にボーダーを追加します
385///
386/// ### 例
387///
388/// ```cpp
389/// // 関数として'borderDouble'を使用する...
390/// Element document = borderDouble(text("The element"));
391///
392/// // ...または'パイプ'として。
393/// Element document = text("The element") | borderDouble;
394/// ```
395///
396/// ### 出力
397///
398/// ```bash
399/// ╔══════════════╗
400/// ║The element ║
401/// ╚══════════════╝
402/// ```
403Element borderDouble(Element child) {
404 return std::make_shared<Border>(unpack(std::move(child)), DOUBLE);
405}
406
407/// @brief 要素の周囲に角の丸いボーダーを描画します。
408/// @ingroup dom
409/// @see border
410/// @see borderLight
411/// @see borderDashed
412/// @see borderDouble
413/// @see borderHeavy
414/// @see borderRounded
415/// @see borderEmpty
416/// @see borderStyled
417/// @see borderWith
418///
419/// 要素の周囲にボーダーを追加します
420///
421/// ### 例
422///
423/// ```cpp
424/// // 関数として'borderRounded'を使用する...
425/// Element document = borderRounded(text("The element"));
426///
427/// // ...または'パイプ'として。
428/// Element document = text("The element") | borderRounded;
429/// ```
430///
431/// ### 出力
432///
433/// ```bash
434/// ╭──────────────╮
435/// │The element │
436/// ╰──────────────╯
437/// ```
438Element borderRounded(Element child) {
439 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
440}
441
442/// @brief 要素の周囲に空のボーダーを描画します。
443/// @ingroup dom
444/// @see border
445/// @see borderLight
446/// @see borderDashed
447/// @see borderDouble
448/// @see borderHeavy
449/// @see borderRounded
450/// @see borderEmpty
451/// @see borderStyled
452/// @see borderWith
453///
454/// 要素の周囲にボーダーを追加します
455///
456/// ### 例
457///
458/// ```cpp
459/// // 関数として'borderRounded'を使用する...
460/// Element document = borderRounded(text("The element"));
461///
462/// // ...または'パイプ'として。
463/// Element document = text("The element") | borderRounded;
464/// ```
465///
466/// ### 出力
467///
468/// ```bash
469///
470/// The element
471///
472/// ```
473Element borderEmpty(Element child) {
474 return std::make_shared<Border>(unpack(std::move(child)), EMPTY);
475}
476
477/// @brief 要素の周囲にタイトルとボーダーを持つウィンドウを描画します。
478/// @param title ウィンドウのタイトル。
479/// @param content ラップする要素。
480/// @param border ボーダーのスタイル。デフォルトはROUNDEDです。
481/// @ingroup dom
482/// @see border
483///
484/// ### 例
485///
486/// ```cpp
487/// Element document = window(text("Title"),
488/// text("content")
489/// );
490///
491/// // ボーダーを指定する場合
492/// Element document = window(text("Title"),
493/// text("content"),
494/// ROUNDED
495/// );
496/// ```
497///
498/// ### 出力
499///
500/// ```bash
501/// ┌Title──┐
502/// │content│
503/// └───────┘
504/// ```
505Element window(Element title, Element content, BorderStyle border) {
506 return std::make_shared<Border>(unpack(std::move(content), std::move(title)),
507 border);
508}
509} // namespace ftxui
Elements children_
Definition node.hpp:76
virtual void SetBox(Box box)
描画のために要素に位置と次元を割り当てます。
Definition node.cpp:41
Requirement requirement_
Definition node.hpp:77
virtual void ComputeRequirement()
要素が必要とするスペースを計算します。
Definition node.cpp:20
Box box_
Definition node.hpp:78
friend void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:96
Element window(Element title, Element content, BorderStyle border)
要素の周囲にタイトルとボーダーを持つウィンドウを描画します。
Element borderDouble(Element child)
要素の周囲に二重線のボーダーを描画します。
Element borderDashed(Element child)
要素の周囲に破線のボーダーを描画します。
Element borderRounded(Element child)
要素の周囲に角の丸いボーダーを描画します。
Element borderHeavy(Element child)
要素の周囲に太いボーダーを描画します。
Element borderLight(Element child)
要素の周囲に細いボーダーを描画します。
Decorator borderWith(const Pixel &pixel)
borderと同じですが、要素の周囲に一定のピクセルを使用します。
Decorator borderStyled(BorderStyle style)
borderと同じですが、異なるスタイルを使用します。
void Render(Screen &screen, const Element &element)
要素をftxui::Screenに表示します。
Definition node.cpp:84
Element border(Element child)
要素の周囲にボーダーを描画します。
Element borderEmpty(Element child)
要素の周囲に空のボーダーを描画します。
BorderStyle
BorderStyleは、ターミナルUIの要素に適用できる様々なボーダースタイルを表す列挙型です。
Definition elements.hpp:31
void Shift(int x, int y)
Definition box.cpp:33
int x_max
Definition box.hpp:16
int y_min
Definition box.hpp:17
int y_max
Definition box.hpp:18
int x_min
Definition box.hpp:15
FTXUI ftxui:: 名前空間
Definition animation.hpp:9
std::vector< Element > Elements
Definition elements.hpp:22