FTXUI  3.0.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
border.cpp
Go to the documentation of this file.
1#include <algorithm> // for max
2#include <array> // for array
3#include <memory> // for allocator, make_shared, __shared_ptr_access
4#include <string> // for basic_string, string
5#include <utility> // for move
6#include <vector> // for __alloc_traits<>::value_type
7
8#include "ftxui/dom/elements.hpp" // for unpack, Element, Decorator, BorderStyle, ROUNDED, Elements, DOUBLE, EMPTY, HEAVY, LIGHT, border, borderDouble, borderEmpty, borderHeavy, borderLight, borderRounded, borderStyled, borderWith, window
9#include "ftxui/dom/node.hpp" // for Node, Elements
10#include "ftxui/dom/requirement.hpp" // for Requirement
11#include "ftxui/screen/box.hpp" // for Box
12#include "ftxui/screen/screen.hpp" // for Pixel, Screen
13
14namespace ftxui {
15
16using Charset = std::array<std::string, 6>; // NOLINT
17using Charsets = std::array<Charset, 6>; // NOLINT
18// NOLINTNEXTLINE
19static Charsets simple_border_charset = {
20 Charset{"┌", "┐", "└", "┘", "─", "│"},
21 Charset{"┏", "┓", "┗", "┛", "━", "┃"},
22 Charset{"╔", "╗", "╚", "╝", "═", "║"},
23 Charset{"╭", "╮", "╰", "╯", "─", "│"},
24 Charset{" ", " ", " ", " ", " ", " "},
25};
26
27// For reference, here is the charset for normal border:
28class Border : public Node {
29 public:
30 Border(Elements children, BorderStyle style)
31 : Node(std::move(children)),
32 charset_(simple_border_charset[style]) {} // NOLINT
33
34 const Charset& charset_; // NOLINT
35
36 void ComputeRequirement() override {
38 requirement_ = children_[0]->requirement();
41 if (children_.size() == 2) {
43 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
44 }
49 }
50
51 void SetBox(Box box) override {
52 Node::SetBox(box);
53 if (children_.size() == 2) {
54 Box title_box;
55 title_box.x_min = box.x_min + 1;
56 title_box.x_max = box.x_max - 1;
57 title_box.y_min = box.y_min;
58 title_box.y_max = box.y_min;
59 children_[1]->SetBox(title_box);
60 }
61 box.x_min++;
62 box.x_max--;
63 box.y_min++;
64 box.y_max--;
65 children_[0]->SetBox(box);
66 }
67
68 void Render(Screen& screen) override {
69 // Draw content.
70 children_[0]->Render(screen);
71
72 // Draw the border.
73 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
74 return;
75 }
76
77 screen.at(box_.x_min, box_.y_min) = charset_[0]; // NOLINT
78 screen.at(box_.x_max, box_.y_min) = charset_[1]; // NOLINT
79 screen.at(box_.x_min, box_.y_max) = charset_[2]; // NOLINT
80 screen.at(box_.x_max, box_.y_max) = charset_[3]; // NOLINT
81
82 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
83 Pixel& p1 = screen.PixelAt(x, box_.y_min);
84 Pixel& p2 = screen.PixelAt(x, box_.y_max);
85 p1.character = charset_[4]; // NOLINT
86 p2.character = charset_[4]; // NOLINT
87 p1.automerge = true;
88 p2.automerge = true;
89 }
90 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
91 Pixel& p3 = screen.PixelAt(box_.x_min, y);
92 Pixel& p4 = screen.PixelAt(box_.x_max, y);
93 p3.character = charset_[5]; // NOLINT
94 p4.character = charset_[5]; // NOLINT
95 p3.automerge = true;
96 p4.automerge = true;
97 }
98
99 // Draw title.
100 if (children_.size() == 2) {
101 children_[1]->Render(screen);
102 }
103 }
104};
105
106// For reference, here is the charset for normal border:
107class BorderPixel : public Node {
108 public:
109 BorderPixel(Elements children, Pixel pixel)
110 : Node(std::move(children)), pixel_(std::move(pixel)) {}
111
112 private:
113 Pixel pixel_;
114
115 void ComputeRequirement() override {
117 requirement_ = children_[0]->requirement();
118 requirement_.min_x += 2;
119 requirement_.min_y += 2;
120 if (children_.size() == 2) {
122 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
123 }
128 }
129
130 void SetBox(Box box) override {
131 Node::SetBox(box);
132 if (children_.size() == 2) {
133 Box title_box;
134 title_box.x_min = box.x_min + 1;
135 title_box.x_max = box.x_max - 1;
136 title_box.y_min = box.y_min;
137 title_box.y_max = box.y_min;
138 children_[1]->SetBox(title_box);
139 }
140 box.x_min++;
141 box.x_max--;
142 box.y_min++;
143 box.y_max--;
144 children_[0]->SetBox(box);
145 }
146
147 void Render(Screen& screen) override {
148 // Draw content.
149 children_[0]->Render(screen);
150
151 // Draw the border.
152 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
153 return;
154 }
155
156 screen.PixelAt(box_.x_min, box_.y_min) = pixel_;
157 screen.PixelAt(box_.x_max, box_.y_min) = pixel_;
158 screen.PixelAt(box_.x_min, box_.y_max) = pixel_;
159 screen.PixelAt(box_.x_max, box_.y_max) = pixel_;
160
161 for (int x = box_.x_min + 1; x < box_.x_max; ++x) {
162 screen.PixelAt(x, box_.y_min) = pixel_;
163 screen.PixelAt(x, box_.y_max) = pixel_;
164 }
165 for (int y = box_.y_min + 1; y < box_.y_max; ++y) {
166 screen.PixelAt(box_.x_min, y) = pixel_;
167 screen.PixelAt(box_.x_max, y) = pixel_;
168 }
169 }
170};
171
172/// @brief Draw a border around the element.
173/// @ingroup dom
174/// @see border
175/// @see borderLight
176/// @see borderDouble
177/// @see borderHeavy
178/// @see borderEmpty
179/// @see borderRounded
180///
181/// Add a border around an element
182///
183/// ### Example
184///
185/// ```cpp
186/// // Use 'border' as a function...
187/// Element document = border(text("The element"));
188///
189/// // ...Or as a 'pipe'.
190/// Element document = text("The element") | border;
191/// ```
192///
193/// ### Output
194///
195/// ```bash
196/// ┌───────────┐
197/// │The element│
198/// └───────────┘
199/// ```
201 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
202}
203
204/// @brief Same as border but with a constant Pixel around the element.
205/// @ingroup dom
206/// @see border
208 return [pixel](Element child) {
209 return std::make_shared<BorderPixel>(unpack(std::move(child)), pixel);
210 };
211}
212
213/// @brief Same as border but with different styles.
214/// @ingroup dom
215/// @see border
217 return [style](Element child) {
218 return std::make_shared<Border>(unpack(std::move(child)), style);
219 };
220}
221
222/// @brief Draw a light border around the element.
223/// @ingroup dom
224/// @see border
225/// @see borderLight
226/// @see borderDouble
227/// @see borderHeavy
228/// @see borderRounded
229/// @see borderEmpty
230/// @see borderStyled
231/// @see borderWith
232///
233/// Add a border around an element
234///
235/// ### Example
236///
237/// ```cpp
238/// // Use 'borderLight' as a function...
239/// Element document = borderLight(text("The element"));
240///
241/// // ...Or as a 'pipe'.
242/// Element document = text("The element") | borderLight;
243/// ```
244///
245/// ### Output
246///
247/// ```bash
248/// ┌──────────────┐
249/// │The element │
250/// └──────────────┘
251/// ```
253 return std::make_shared<Border>(unpack(std::move(child)), LIGHT);
254}
255
256/// @brief Draw a heavy border around the element.
257/// @ingroup dom
258/// @see border
259/// @see borderLight
260/// @see borderDouble
261/// @see borderHeavy
262/// @see borderRounded
263/// @see borderEmpty
264/// @see borderStyled
265/// @see borderWith
266///
267/// Add a border around an element
268///
269/// ### Example
270///
271/// ```cpp
272/// // Use 'borderHeavy' as a function...
273/// Element document = borderHeavy(text("The element"));
274///
275/// // ...Or as a 'pipe'.
276/// Element document = text("The element") | borderHeavy;
277/// ```
278///
279/// ### Output
280///
281/// ```bash
282/// ┏━━━━━━━━━━━━━━┓
283/// ┃The element ┃
284/// ┗━━━━━━━━━━━━━━┛
285/// ```
287 return std::make_shared<Border>(unpack(std::move(child)), HEAVY);
288}
289
290/// @brief Draw a double border around the element.
291/// @ingroup dom
292/// @see border
293/// @see borderLight
294/// @see borderDouble
295/// @see borderHeavy
296/// @see borderRounded
297/// @see borderEmpty
298/// @see borderStyled
299/// @see borderWith
300///
301/// Add a border around an element
302///
303/// ### Example
304///
305/// ```cpp
306/// // Use 'borderDouble' as a function...
307/// Element document = borderDouble(text("The element"));
308///
309/// // ...Or as a 'pipe'.
310/// Element document = text("The element") | borderDouble;
311/// ```
312///
313/// ### Output
314///
315/// ```bash
316/// ╔══════════════╗
317/// ║The element ║
318/// ╚══════════════╝
319/// ```
321 return std::make_shared<Border>(unpack(std::move(child)), DOUBLE);
322}
323
324/// @brief Draw a rounded border around the element.
325/// @ingroup dom
326/// @see border
327/// @see borderLight
328/// @see borderDouble
329/// @see borderHeavy
330/// @see borderRounded
331/// @see borderEmpty
332/// @see borderStyled
333/// @see borderWith
334///
335/// Add a border around an element
336///
337/// ### Example
338///
339/// ```cpp
340/// // Use 'borderRounded' as a function...
341/// Element document = borderRounded(text("The element"));
342///
343/// // ...Or as a 'pipe'.
344/// Element document = text("The element") | borderRounded;
345/// ```
346///
347/// ### Output
348///
349/// ```bash
350/// ╭──────────────╮
351/// │The element │
352/// ╰──────────────╯
353/// ```
355 return std::make_shared<Border>(unpack(std::move(child)), ROUNDED);
356}
357
358/// @brief Draw an empty border around the element.
359/// @ingroup dom
360/// @see border
361/// @see borderLight
362/// @see borderDouble
363/// @see borderHeavy
364/// @see borderRounded
365/// @see borderEmpty
366/// @see borderStyled
367/// @see borderWith
368///
369/// Add a border around an element
370///
371/// ### Example
372///
373/// ```cpp
374/// // Use 'borderRounded' as a function...
375/// Element document = borderRounded(text("The element"));
376///
377/// // ...Or as a 'pipe'.
378/// Element document = text("The element") | borderRounded;
379/// ```
380///
381/// ### Output
382///
383/// ```bash
384///
385/// The element
386///
387/// ```
389 return std::make_shared<Border>(unpack(std::move(child)), EMPTY);
390}
391
392/// @brief Draw window with a title and a border around the element.
393/// @param title The title of the window.
394/// @param content The element to be wrapped.
395/// @ingroup dom
396/// @see border
397///
398/// ### Example
399///
400/// ```cpp
401/// Element document = window(text("Title"),
402/// text("content")
403/// );
404/// ```
405///
406/// ### Output
407///
408/// ```bash
409/// ┌Title──┐
410/// │content│
411/// └───────┘
412/// ```
413Element window(Element title, Element content) {
414 return std::make_shared<Border>(unpack(std::move(content), std::move(title)),
415 ROUNDED);
416}
417} // namespace ftxui
418
419// Copyright 2020 Arthur Sonzogni. All rights reserved.
420// Use of this source code is governed by the MIT license that can be found in
421// the LICENSE file.
Elements children_
Definition node.hpp:53
virtual void SetBox(Box box)
Assign a position and a dimension to an element for drawing.
Definition node.cpp:22
Requirement requirement_
Definition node.hpp:54
virtual void ComputeRequirement()
Compute how much space an elements needs.
Definition node.cpp:14
Box box_
Definition node.hpp:55
Element borderDouble(Element)
Draw a double border around the element.
Definition border.cpp:320
std::function< Element(Element)> Decorator
Definition elements.hpp:20
std::shared_ptr< Node > Element
Definition elements.hpp:18
Element borderRounded(Element)
Draw a rounded border around the element.
Definition border.cpp:354
Element window(Element title, Element content)
Draw window with a title and a border around the element.
Definition border.cpp:413
std::vector< Element > Elements
Definition elements.hpp:19
std::array< Charset, 6 > Charsets
Definition border.cpp:17
Element borderHeavy(Element)
Draw a heavy border around the element.
Definition border.cpp:286
Element borderLight(Element)
Draw a light border around the element.
Definition border.cpp:252
Decorator borderWith(const Pixel &)
Same as border but with a constant Pixel around the element.
Definition border.cpp:207
Decorator borderStyled(BorderStyle)
Same as border but with different styles.
Definition border.cpp:216
std::array< std::string, 6 > Charset
Definition border.cpp:16
Element border(Element)
Draw a border around the element.
Definition border.cpp:200
Element borderEmpty(Element)
Draw an empty border around the element.
Definition border.cpp:388
BorderStyle
Definition elements.hpp:23
@ EMPTY
Definition elements.hpp:23
@ DOUBLE
Definition elements.hpp:23
@ HEAVY
Definition elements.hpp:23
@ ROUNDED
Definition elements.hpp:23
@ LIGHT
Definition elements.hpp:23
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