FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
flexbox.cpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. Todos los derechos reservados.
2// El uso de este código fuente se rige por la licencia MIT que se puede encontrar en
3// el archivo LICENSE.
4#include <algorithm> // for min, max
5#include <cstddef> // for size_t
6#include <memory> // for __shared_ptr_access, shared_ptr, allocator_traits<>::value_type, make_shared
7#include <tuple> // for ignore
8#include <utility> // for move, swap
9#include <vector> // for vector
10
11#include "ftxui/dom/elements.hpp" // for Element, Elements, flexbox, hflow, vflow
12#include "ftxui/dom/flexbox_config.hpp" // for FlexboxConfig, FlexboxConfig::Direction, FlexboxConfig::Direction::Column, FlexboxConfig::AlignContent, FlexboxConfig::Direction::ColumnInversed, FlexboxConfig::Direction::Row, FlexboxConfig::JustifyContent, FlexboxConfig::Wrap, FlexboxConfig::AlignContent::FlexStart, FlexboxConfig::Direction::RowInversed, FlexboxConfig::JustifyContent::FlexStart, FlexboxConfig::Wrap::Wrap
13#include "ftxui/dom/flexbox_helper.hpp" // for Block, Global, Compute
14#include "ftxui/dom/node.hpp" // for Node, Elements, Node::Status
15#include "ftxui/dom/requirement.hpp" // for Requirement
16#include "ftxui/dom/selection.hpp" // for Selection
17#include "ftxui/screen/box.hpp" // for Box
18
19namespace ftxui {
20
21namespace {
22void Normalize(FlexboxConfig::Direction& direction) {
23 switch (direction) {
27 } break;
31 } break;
32 }
33}
34
35void Normalize(FlexboxConfig::AlignContent& align_content) {
37}
38
39void Normalize(FlexboxConfig::JustifyContent& justify_content) {
41}
42
43void Normalize(FlexboxConfig::Wrap& wrap) {
45}
46
47FlexboxConfig Normalize(FlexboxConfig config) {
48 Normalize(config.direction);
49 Normalize(config.wrap);
50 Normalize(config.justify_content);
51 Normalize(config.align_content);
52 return config;
53}
54
55class Flexbox : public Node {
56 public:
57 Flexbox(Elements children, FlexboxConfig config)
58 : Node(std::move(children)),
59 config_(config),
60 config_normalized_(Normalize(config)) {
61 requirement_.flex_grow_x = 1;
62 requirement_.flex_grow_y = 0;
63
64 if (IsColumnOriented()) {
65 std::swap(requirement_.flex_grow_x, requirement_.flex_grow_y);
66 }
67 }
68
69 bool IsColumnOriented() const {
70 return config_.direction == FlexboxConfig::Direction::Column ||
72 }
73
74 void Layout(flexbox_helper::Global& global,
75 bool compute_requirement = false) {
76 global.blocks.reserve(children_.size());
77 for (auto& child : children_) {
78 flexbox_helper::Block block;
79 block.min_size_x = child->requirement().min_x;
80 block.min_size_y = child->requirement().min_y;
81 if (!compute_requirement) {
82 block.flex_grow_x = child->requirement().flex_grow_x;
83 block.flex_grow_y = child->requirement().flex_grow_y;
84 block.flex_shrink_x = child->requirement().flex_shrink_x;
85 block.flex_shrink_y = child->requirement().flex_shrink_y;
86 }
87 global.blocks.push_back(block);
88 }
89
91 }
92
93 void ComputeRequirement() override {
94 requirement_ = Requirement{};
95 for (auto& child : children_) {
96 child->ComputeRequirement();
97 }
98 global_ = flexbox_helper::Global();
100 if (IsColumnOriented()) {
101 global_.size_x = 100000; // NOLINT
102 global_.size_y = asked_;
103 } else {
104 global_.size_x = asked_;
105 global_.size_y = 100000; // NOLINT
106 }
107 Layout(global_, true);
108
109 if (global_.blocks.empty()) {
110 return;
111 }
112
113 // Compute the union of all the blocks:
114 Box box;
115 box.x_min = global_.blocks[0].x;
116 box.y_min = global_.blocks[0].y;
117 box.x_max = global_.blocks[0].x + global_.blocks[0].dim_x;
118 box.y_max = global_.blocks[0].y + global_.blocks[0].dim_y;
119 for (auto& b : global_.blocks) {
120 box.x_min = std::min(box.x_min, b.x);
121 box.y_min = std::min(box.y_min, b.y);
122 box.x_max = std::max(box.x_max, b.x + b.dim_x);
123 box.y_max = std::max(box.y_max, b.y + b.dim_y);
124 }
125 requirement_.min_x = box.x_max - box.x_min;
126 requirement_.min_y = box.y_max - box.y_min;
127
128 // Find the selection:
129 for (size_t i = 0; i < children_.size(); ++i) {
130 if (requirement_.focused.Prefer(children_[i]->requirement().focused)) {
131 requirement_.focused = children_[i]->requirement().focused;
132 // Shift |focused.box| according to its position inside this component:
133 auto& b = global_.blocks[i];
134 requirement_.focused.box.Shift(b.x, b.y);
135 requirement_.focused.box =
136 Box::Intersection(requirement_.focused.box, box);
137 }
138 }
139 }
140
141 void SetBox(Box box) override {
142 Node::SetBox(box);
143
144 const int asked_previous = asked_;
145 asked_ = std::min(asked_, IsColumnOriented() ? box.y_max - box.y_min + 1
146 : box.x_max - box.x_min + 1);
147 need_iteration_ = (asked_ != asked_previous);
148
149 flexbox_helper::Global global;
150 global.config = config_;
151 global.size_x = box.x_max - box.x_min + 1;
152 global.size_y = box.y_max - box.y_min + 1;
153 Layout(global);
154
155 for (size_t i = 0; i < children_.size(); ++i) {
156 auto& child = children_[i];
157 auto& b = global.blocks[i];
158
159 Box children_box;
160 children_box.x_min = box.x_min + b.x;
161 children_box.y_min = box.y_min + b.y;
162 children_box.x_max = box.x_min + b.x + b.dim_x - 1;
163 children_box.y_max = box.y_min + b.y + b.dim_y - 1;
164
165 const Box intersection = Box::Intersection(children_box, box);
166 child->SetBox(intersection);
167
168 need_iteration_ |= (intersection != children_box);
169 }
170 }
171
172 void Select(Selection& selection) override {
173 // If this Node box_ doesn't intersect with the selection, then no
174 // selection.
175 if (Box::Intersection(selection.GetBox(), box_).IsEmpty()) {
176 return;
177 }
178
179 Selection selection_lines = IsColumnOriented()
180 ? selection.SaturateVertical(box_)
181 : selection.SaturateHorizontal(box_);
182
183 size_t i = 0;
184 for (auto& line : global_.lines) {
185 Box box;
186 box.x_min = box_.x_min + line.x;
187 box.x_max = box_.x_min + line.x + line.dim_x - 1;
188 box.y_min = box_.y_min + line.y;
189 box.y_max = box_.y_min + line.y + line.dim_y - 1;
190
191 // If the line box doesn't intersect with the selection, then no
192 // selection.
193 if (Box::Intersection(selection.GetBox(), box).IsEmpty()) {
194 continue;
195 }
196
197 Selection selection_line = IsColumnOriented()
198 ? selection_lines.SaturateHorizontal(box)
199 : selection_lines.SaturateVertical(box);
200
201 for (auto& block : line.blocks) {
202 std::ignore = block;
203 children_[i]->Select(selection_line);
204 i++;
205 }
206 }
207 }
208
209 void Check(Status* status) override {
210 for (auto& child : children_) {
211 child->Check(status);
212 }
213
214 if (status->iteration == 0) {
215 asked_ = 6000; // NOLINT
216 need_iteration_ = true;
217 }
218
219 status->need_iteration |= need_iteration_;
220 }
221
222 int asked_ = 6000; // NOLINT
223 bool need_iteration_ = true;
224 const FlexboxConfig config_;
225 const FlexboxConfig config_normalized_;
226 flexbox_helper::Global global_;
227};
228
229} // namespace
230
231/// @brief Un contenedor que muestra elementos en filas/columnas y es capaz de
232/// ajustarse a la siguiente columna/fila cuando está lleno.
233/// @param children Los elementos en el contenedor
234/// @param config La opción
235/// @return El contenedor.
236///
237/// #### Ejemplo
238///
239/// ```cpp
240/// flexbox({
241/// text("element 1"),
242/// text("element 2"),
243/// text("element 3"),
244/// }, FlexboxConfig()
245/// .Set(FlexboxConfig::Direction::Column)
246/// .Set(FlexboxConfig::Wrap::WrapInversed)
247/// .SetGapMainAxis(1)
248/// .SetGapCrossAxis(1)
249/// )
250/// ```
252 return std::make_shared<Flexbox>(std::move(children), config);
253}
254
255/// @brief Un contenedor que muestra elementos en filas de izquierda a derecha. Cuando
256/// está lleno, comienza en una nueva fila debajo.
257/// @param children Los elementos en el contenedor
258/// @return El contenedor.
259///
260/// #### Ejemplo
261///
262/// ```cpp
263/// hflow({
264/// text("element 1"),
265/// text("element 2"),
266/// text("element 3"),
267/// });
268/// ```
270 return flexbox(std::move(children), FlexboxConfig());
271}
272
273/// @brief Un contenedor que muestra elementos en filas de arriba a abajo. Cuando
274/// está lleno, comienza en una nueva columna a la derecha.
275/// @param children Los elementos en el contenedor
276/// @return El contenedor.
277///
278/// #### Ejemplo
279///
280/// ```cpp
281/// vflow({
282/// text("element 1"),
283/// text("element 2"),
284/// text("element 3"),
285/// });
286/// ```
288 return flexbox(std::move(children),
290}
291
292} // namespace ftxui
int asked_
Definition flexbox.cpp:222
bool need_iteration_
Definition flexbox.cpp:223
const FlexboxConfig config_
Definition flexbox.cpp:224
const FlexboxConfig config_normalized_
Definition flexbox.cpp:225
flexbox_helper::Global global_
Definition flexbox.cpp:226
@ FlexStart
Los elementos se colocan al inicio del eje transversal.
@ Column
Los elementos flex se distribuyen en una columna.
@ Row
Los elementos flex se distribuyen en una fila.
@ RowInversed
Los elementos flex se distribuyen en una fila, pero en orden inverso.
virtual void SetBox(Box box)
Asigna una posición y una dimensión a un elemento para dibujarlo.
Definition node.cpp:41
@ Wrap
Los elementos flex se ajustarán en varias líneas.
@ FlexStart
Los elementos se alinean al inicio de la dirección del flexbox.
FlexboxConfig es una estructura de configuración que define las propiedades de diseño para un contene...
static auto Intersection(Box a, Box b) -> Box
Definition box.cpp:11
void Compute(Global &global)
El espacio de nombres ftxui:: de FTXUI.
Definition animation.hpp:10
Element flexbox(Elements, FlexboxConfig config=FlexboxConfig())
Un contenedor que muestra elementos en filas/columnas y es capaz de ajustarse a la siguiente columna/...
Definition flexbox.cpp:251
std::shared_ptr< Node > Element
Definition elements.hpp:22
Element hflow(Elements)
Un contenedor que muestra elementos en filas de izquierda a derecha. Cuando está lleno,...
Definition flexbox.cpp:269
std::vector< Element > Elements
Definition elements.hpp:23
Element vflow(Elements)
Un contenedor que muestra elementos en filas de arriba a abajo. Cuando está lleno,...
Definition flexbox.cpp:287