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{
" ",
" ",
" ",
" ",
" ",
" "},
36class Border :
public Node {
40 std::optional<Color> foreground_color = std::nullopt)
41 : Node(std::move(children)),
42 charset_(simple_border_charset[style])
49 void ComputeRequirement()
override {
50 Node::ComputeRequirement();
51 requirement_ = children_[0]->requirement();
52 requirement_.min_x += 2;
53 requirement_.min_y += 2;
54 if (children_.size() == 2) {
56 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
58 requirement_.focused.box.x_min++;
59 requirement_.focused.box.x_max++;
60 requirement_.focused.box.y_min++;
61 requirement_.focused.box.y_max++;
64 void SetBox(Box box)
override {
66 if (children_.size() == 2) {
68 title_box.x_min = box.x_min + 1;
69 title_box.x_max = std::min(box.x_max - 1,
70 box.x_min + children_[1]->requirement().min_x);
71 title_box.y_min = box.y_min;
72 title_box.y_max = box.y_min;
73 children_[1]->SetBox(title_box);
79 children_[0]->SetBox(box);
82 void Render(Screen& screen)
override {
85 children_[0]->Render(screen);
89 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
93 screen.at(box_.x_min, box_.y_min) =
charset_[0];
94 screen.at(box_.x_max, box_.y_min) =
charset_[1];
95 screen.at(box_.x_min, box_.y_max) =
charset_[2];
96 screen.at(box_.x_max, box_.y_max) =
charset_[3];
98 for (
int x = box_.x_min + 1; x < box_.x_max; ++x) {
99 Cell& p1 = screen.CellAt(x, box_.y_min);
100 Cell& p2 = screen.CellAt(x, box_.y_max);
106 for (
int y = box_.y_min + 1;
y < box_.y_max; ++
y) {
107 Cell& p3 = screen.CellAt(box_.x_min,
y);
108 Cell& p4 = screen.CellAt(box_.x_max,
y);
117 if (children_.size() == 2) {
118 children_[1]->Render(screen);
123 if (foreground_color_) {
124 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
128 for (
int y = box_.y_min;
y <= box_.y_max; ++
y) {
138class BorderCell :
public Node {
140 BorderCell(
Elements children, Cell pixel)
141 : Node(std::move(children)), pixel_(std::move(pixel)) {}
146 void ComputeRequirement()
override {
147 Node::ComputeRequirement();
148 requirement_ = children_[0]->requirement();
149 requirement_.min_x += 2;
150 requirement_.min_y += 2;
151 if (children_.size() == 2) {
153 std::max(requirement_.min_x, children_[1]->requirement().min_x + 2);
156 requirement_.focused.box.Shift(1, 1);
159 void SetBox(Box box)
override {
161 if (children_.size() == 2) {
163 title_box.x_min = box.x_min + 1;
164 title_box.x_max = box.x_max - 1;
165 title_box.y_min = box.y_min;
166 title_box.y_max = box.y_min;
167 children_[1]->SetBox(title_box);
173 children_[0]->SetBox(box);
176 void Render(Screen& screen)
override {
179 children_[0]->Render(screen);
183 if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max) {
187 screen.CellAt(box_.x_min, box_.y_min) = pixel_;
188 screen.CellAt(box_.x_max, box_.y_min) = pixel_;
189 screen.CellAt(box_.x_min, box_.y_max) = pixel_;
190 screen.CellAt(box_.x_max, box_.y_max) = pixel_;
192 for (
int x = box_.x_min + 1; x < box_.x_max; ++x) {
193 screen.CellAt(x, box_.y_min) = pixel_;
194 screen.CellAt(x, box_.y_max) = pixel_;
196 for (
int y = box_.y_min + 1;
y < box_.y_max; ++
y) {
197 screen.CellAt(box_.x_min,
y) = pixel_;
198 screen.CellAt(box_.x_max,
y) = pixel_;
236 return std::make_shared<Border>(unpack(std::move(child)),
ROUNDED);
243 return [pixel](
Element child) {
244 return std::make_shared<BorderCell>(unpack(std::move(child)), pixel);
252 return [style](
Element child) {
253 return std::make_shared<Border>(unpack(std::move(child)), style);
261 return [foreground_color](
Element child) {
262 return std::make_shared<Border>(unpack(std::move(child)),
ROUNDED,
271 return [style, foreground_color](
Element child) {
272 return std::make_shared<Border>(unpack(std::move(child)), style,
309 return std::make_shared<Border>(unpack(std::move(child)),
DASHED);
344 return std::make_shared<Border>(unpack(std::move(child)),
LIGHT);
379 return std::make_shared<Border>(unpack(std::move(child)),
HEAVY);
414 return std::make_shared<Border>(unpack(std::move(child)),
DOUBLE);
449 return std::make_shared<Border>(unpack(std::move(child)),
ROUNDED);
484 return std::make_shared<Border>(unpack(std::move(child)),
EMPTY);
516 return std::make_shared<Border>(unpack(std::move(content), std::move(title)),
Element window(Element title, Element content, BorderStyle border=ROUNDED)
Dibuja una ventana con un título y un borde alrededor del elemento.
Element borderDouble(Element child)
Dibuja un borde doble alrededor del elemento.
Element borderDashed(Element child)
Dibuja un borde discontinuo alrededor del elemento.
Element borderRounded(Element child)
Dibuja un borde redondeado alrededor del elemento.
BorderStyle
BorderStyle es una enumeración que representa los diferentes estilos de bordes que se pueden aplicar ...
Element borderHeavy(Element child)
Dibuja un borde grueso alrededor del elemento.
Decorator borderWith(const Cell &pixel)
Igual que border pero con un Cell constante alrededor del elemento.
Element borderLight(Element child)
Dibuja un borde ligero alrededor del elemento.
Decorator borderStyled(BorderStyle style)
Igual que border pero con estilos diferentes.
Element border(Element child)
Dibuja un borde alrededor del elemento.
Element borderEmpty(Element child)
Dibuja un borde vacío alrededor del elemento.
El espacio de nombres ftxui:: de FTXUI.
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_