22using Charset = std::array<std::string, 6>;
23using Charsets = std::array<Charset, 6>;
25static Charsets simple_border_charset = {
26 Charset{
"┌",
"┐",
"└",
"┘",
"─",
"│"},
27 Charset{
"┏",
"┓",
"┗",
"┛",
"╍",
"╏"},
28 Charset{
"┏",
"┓",
"┗",
"┛",
"━",
"┃"},
29 Charset{
"╔",
"╗",
"╚",
"╝",
"═",
"║"},
30 Charset{
"╭",
"╮",
"╰",
"╯",
"─",
"│"},
31 Charset{
" ",
" ",
" ",
" ",
" ",
" "},
35class Border :
public Node {
39 std::optional<Color> foreground_color = std::nullopt)
40 : Node(std::move(children)),
41 charset_(simple_border_charset[style])
48 void ComputeRequirement()
override {
49 Node::ComputeRequirement();
50 requirement_ = children_[0]->requirement();
51 requirement_.min_x += 2;
52 requirement_.min_y += 2;
53 if (children_.size() == 2) {
55 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
57 requirement_.focused.box.x_min++;
58 requirement_.focused.box.x_max++;
59 requirement_.focused.box.y_min++;
60 requirement_.focused.box.y_max++;
63 void SetBox(Box box)
override {
65 if (children_.size() == 2) {
67 title_box.x_min = box.x_min + 1;
68 title_box.x_max = std::min(box.x_max - 1,
69 box.x_min + children_[1]->requirement().min_x);
70 title_box.y_min = box.y_min;
71 title_box.y_max = box.y_min;
72 children_[1]->SetBox(title_box);
78 children_[0]->SetBox(box);
81 void Render(Screen& screen)
override {
83 children_[0]->Render(screen);
86 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
90 screen.at(box_.x_min, box_.y_min) =
charset_[0];
91 screen.at(box_.x_max, box_.y_min) =
charset_[1];
92 screen.at(box_.x_min, box_.y_max) =
charset_[2];
93 screen.at(box_.x_max, box_.y_max) =
charset_[3];
95 for (
int x = box_.x_min + 1; x < box_.x_max; ++x) {
96 Cell& p1 = screen.CellAt(x, box_.y_min);
97 Cell& p2 = screen.CellAt(x, box_.y_max);
103 for (
int y = box_.y_min + 1;
y < box_.y_max; ++
y) {
104 Cell& p3 = screen.CellAt(box_.x_min,
y);
105 Cell& p4 = screen.CellAt(box_.x_max,
y);
113 if (children_.size() == 2) {
114 children_[1]->Render(screen);
118 if (foreground_color_) {
119 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
123 for (
int y = box_.y_min;
y <= box_.y_max; ++
y) {
132class BorderCell :
public Node {
134 BorderCell(
Elements children, Cell pixel)
135 : Node(std::move(children)), pixel_(std::move(pixel)) {}
140 void ComputeRequirement()
override {
141 Node::ComputeRequirement();
142 requirement_ = children_[0]->requirement();
143 requirement_.min_x += 2;
144 requirement_.min_y += 2;
145 if (children_.size() == 2) {
147 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
150 requirement_.focused.box.Shift(1, 1);
153 void SetBox(Box box)
override {
155 if (children_.size() == 2) {
157 title_box.x_min = box.x_min + 1;
158 title_box.x_max = box.x_max - 1;
159 title_box.y_min = box.y_min;
160 title_box.y_max = box.y_min;
161 children_[1]->SetBox(title_box);
167 children_[0]->SetBox(box);
170 void Render(Screen& screen)
override {
172 children_[0]->Render(screen);
175 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
179 screen.CellAt(box_.x_min, box_.y_min) = pixel_;
180 screen.CellAt(box_.x_max, box_.y_min) = pixel_;
181 screen.CellAt(box_.x_min, box_.y_max) = pixel_;
182 screen.CellAt(box_.x_max, box_.y_max) = pixel_;
184 for (
int x = box_.x_min + 1; x < box_.x_max; ++x) {
185 screen.CellAt(x, box_.y_min) = pixel_;
186 screen.CellAt(x, box_.y_max) = pixel_;
188 for (
int y = box_.y_min + 1;
y < box_.y_max; ++
y) {
189 screen.CellAt(box_.x_min,
y) = pixel_;
190 screen.CellAt(box_.x_max,
y) = pixel_;
228 return std::make_shared<Border>(unpack(std::move(child)),
ROUNDED);
235 return [pixel](
Element child) {
236 return std::make_shared<BorderCell>(unpack(std::move(child)), pixel);
244 return [style](
Element child) {
245 return std::make_shared<Border>(unpack(std::move(child)), style);
253 return [foreground_color](
Element child) {
254 return std::make_shared<Border>(unpack(std::move(child)),
ROUNDED,
263 return [style, foreground_color](
Element child) {
264 return std::make_shared<Border>(unpack(std::move(child)), style,
301 return std::make_shared<Border>(unpack(std::move(child)),
DASHED);
336 return std::make_shared<Border>(unpack(std::move(child)),
LIGHT);
371 return std::make_shared<Border>(unpack(std::move(child)),
HEAVY);
406 return std::make_shared<Border>(unpack(std::move(child)),
DOUBLE);
441 return std::make_shared<Border>(unpack(std::move(child)),
ROUNDED);
476 return std::make_shared<Border>(unpack(std::move(child)),
EMPTY);
508 return std::make_shared<Border>(unpack(std::move(content), std::move(title)),
Element window(Element title, Element content, BorderStyle border=ROUNDED)
Draw window with a title and a border around the element.
Element borderDouble(Element child)
Draw a double border around the element.
Element borderDashed(Element child)
Draw a dashed border around the element.
Element borderRounded(Element child)
Draw a rounded border around the element.
BorderStyle
BorderStyle is an enumeration that represents the different styles of borders that can be applied to ...
Element borderHeavy(Element child)
Draw a heavy border around the element.
Decorator borderWith(const Cell &pixel)
Same as border but with a constant Cell around the element.
Element borderLight(Element child)
Draw a light border around the element.
Decorator borderStyled(BorderStyle style)
Same as border but with different styles.
Element border(Element child)
Draw a border around the element.
Element borderEmpty(Element child)
Draw an empty border around the element.
The FTXUI ftxui:: namespace.
std::shared_ptr< Node > Element
std::vector< Element > Elements
std::function< Element(Element)> Decorator
void Render(Screen &screen, Node *node, Selection &selection)
std::optional< Color > foreground_color_