FTXUI  4.1.1
C++ functional terminal UI.
Loading...
Searching...
No Matches
gridbox.cpp
Go to the documentation of this file.
1#include <algorithm> // for max, min
2#include <cstddef> // for size_t
3#include <memory> // for __shared_ptr_access, shared_ptr, make_shared, allocator_traits<>::value_type
4#include <utility> // for move
5#include <vector> // for vector, __alloc_traits<>::value_type
6
7#include "ftxui/dom/box_helper.hpp" // for Element, Compute
8#include "ftxui/dom/elements.hpp" // for Elements, filler, Element, gridbox
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
13namespace ftxui {
14class Screen;
15
16namespace {
17
18// Accumulate the values of a list U[n] into v[n]. So that:
19// V[0] = 0;
20// V[n+1] = v[n] + U[n]
21// return the sum of U[n].
22int Integrate(std::vector<int>& elements) {
23 int accu = 0;
24 for (auto& i : elements) {
25 const int old_accu = accu;
26 accu += i;
27 i = old_accu;
28 }
29 return accu;
30}
31} // namespace
32
33class GridBox : public Node {
34 public:
35 explicit GridBox(std::vector<Elements> lines) : lines_(std::move(lines)) {
36 y_size = (int)lines_.size();
37 for (const auto& line : lines_) {
38 x_size = std::max(x_size, (int)line.size());
39 }
40 for (auto& line : lines_) {
41 while (line.size() < (size_t)x_size) {
42 line.push_back(filler());
43 }
44 }
45 }
46
47 void ComputeRequirement() override {
54
55 for (auto& line : lines_) {
56 for (auto& cell : line) {
57 cell->ComputeRequirement();
58 }
59 }
60
61 // Compute the size of each columns/row.
62 std::vector<int> size_x(x_size, 0);
63 std::vector<int> size_y(y_size, 0);
64 for (int x = 0; x < x_size; ++x) {
65 for (int y = 0; y < y_size; ++y) {
66 size_x[x] = std::max(size_x[x], lines_[y][x]->requirement().min_x);
67 size_y[y] = std::max(size_y[y], lines_[y][x]->requirement().min_y);
68 }
69 }
70
71 requirement_.min_x = Integrate(size_x);
72 requirement_.min_y = Integrate(size_y);
73
74 // Forward the selected/focused child state:
76 for (int x = 0; x < x_size; ++x) {
77 for (int y = 0; y < y_size; ++y) {
78 if (requirement_.selection >= lines_[y][x]->requirement().selection) {
79 continue;
80 }
81 requirement_.selection = lines_[y][x]->requirement().selection;
82 requirement_.selected_box = lines_[y][x]->requirement().selected_box;
83 requirement_.selected_box.x_min += size_x[x];
84 requirement_.selected_box.x_max += size_x[x];
85 requirement_.selected_box.y_min += size_y[y];
86 requirement_.selected_box.y_max += size_y[y];
87 }
88 }
89 }
90
91 void SetBox(Box box) override {
92 Node::SetBox(box);
93
94 box_helper::Element init;
95 init.min_size = 0;
96 init.flex_grow = 1024; // NOLINT
97 init.flex_shrink = 1024; // NOLINT
98 std::vector<box_helper::Element> elements_x(x_size, init);
99 std::vector<box_helper::Element> elements_y(y_size, init);
100
101 for (int y = 0; y < y_size; ++y) {
102 for (int x = 0; x < x_size; ++x) {
103 const auto& cell = lines_[y][x];
104 const auto& requirement = cell->requirement();
105 auto& e_x = elements_x[x];
106 auto& e_y = elements_y[y];
107 e_x.min_size = std::max(e_x.min_size, requirement.min_x);
108 e_y.min_size = std::max(e_y.min_size, requirement.min_y);
109 e_x.flex_grow = std::min(e_x.flex_grow, requirement.flex_grow_x);
110 e_y.flex_grow = std::min(e_y.flex_grow, requirement.flex_grow_y);
111 e_x.flex_shrink = std::min(e_x.flex_shrink, requirement.flex_shrink_x);
112 e_y.flex_shrink = std::min(e_y.flex_shrink, requirement.flex_shrink_y);
113 }
114 }
115
116 const int target_size_x = box.x_max - box.x_min + 1;
117 const int target_size_y = box.y_max - box.y_min + 1;
118 box_helper::Compute(&elements_x, target_size_x);
119 box_helper::Compute(&elements_y, target_size_y);
120
121 Box box_y = box;
122 int y = box_y.y_min;
123 for (int iy = 0; iy < y_size; ++iy) {
124 box_y.y_min = y;
125 y += elements_y[iy].size;
126 box_y.y_max = y - 1;
127
128 Box box_x = box_y;
129 int x = box_x.x_min;
130 for (int ix = 0; ix < x_size; ++ix) {
131 box_x.x_min = x;
132 x += elements_x[ix].size;
133 box_x.x_max = x - 1;
134 lines_[iy][ix]->SetBox(box_x);
135 }
136 }
137 }
138
139 void Render(Screen& screen) override {
140 for (auto& line : lines_) {
141 for (auto& cell : line) {
142 cell->Render(screen);
143 }
144 }
145 }
146
147 int x_size = 0;
148 int y_size = 0;
149 std::vector<Elements> lines_;
150};
151
152/// @brief A container displaying a grid of elements.
153/// @param lines A list of lines, each line being a list of elements.
154/// @return The container.
155///
156/// #### Example
157///
158/// ```cpp
159/// auto cell = [](const char* t) { return text(t) | border; };
160/// auto document = gridbox({
161/// {cell("north-west") , cell("north") , cell("north-east")} ,
162/// {cell("west") , cell("center") , cell("east")} ,
163/// {cell("south-west") , cell("south") , cell("south-east")} ,
164/// });
165/// ```
166/// Output:
167/// ```
168/// ╭──────────╮╭──────╮╭──────────╮
169/// │north-west││north ││north-east│
170/// ╰──────────╯╰──────╯╰──────────╯
171/// ╭──────────╮╭──────╮╭──────────╮
172/// │west ││center││east │
173/// ╰──────────╯╰──────╯╰──────────╯
174/// ╭──────────╮╭──────╮╭──────────╮
175/// │south-west││south ││south-east│
176/// ╰──────────╯╰──────╯╰──────────╯
177/// ```
178Element gridbox(std::vector<Elements> lines) {
179 return std::make_shared<GridBox>(std::move(lines));
180}
181
182} // namespace ftxui
183
184// Copyright 2020 Arthur Sonzogni. All rights reserved.
185// Use of this source code is governed by the MIT license that can be found in
186// the LICENSE file.
virtual void SetBox(Box box)
Assign a position and a dimension to an element for drawing.
Definition node.cpp:23
Requirement requirement_
Definition node.hpp:54
Requirement requirement()
Definition node.hpp:34
void Compute(std::vector< Element > *elements, int target_size)
std::shared_ptr< Node > Element
Definition elements.hpp:19
Element gridbox(std::vector< Elements > lines)
A container displaying a grid of elements.
Definition gridbox.cpp:178
Element filler()
An element that will take expand proportionnally to the space left in a container.
Definition flex.cpp:95
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