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