42FlexboxConfig Normalize(FlexboxConfig config) {
43 Normalize(config.direction);
44 Normalize(config.wrap);
45 Normalize(config.justify_content);
46 Normalize(config.align_content);
50class Flexbox :
public Node {
52 Flexbox(
Elements children, FlexboxConfig config)
53 : Node(std::move(children)),
55 config_normalized_(Normalize(config)) {
56 requirement_.flex_grow_x = 1;
57 requirement_.flex_grow_y = 0;
59 if (IsColumnOriented()) {
60 std::swap(requirement_.flex_grow_x, requirement_.flex_grow_y);
64 bool IsColumnOriented()
const {
69 void Layout(flexbox_helper::Global& global,
70 bool compute_requirement =
false) {
71 for (
auto& child : children_) {
72 flexbox_helper::Block block;
73 block.min_size_x = child->requirement().min_x;
74 block.min_size_y = child->requirement().min_y;
75 if (!compute_requirement) {
76 block.flex_grow_x = child->requirement().flex_grow_x;
77 block.flex_grow_y = child->requirement().flex_grow_y;
78 block.flex_shrink_x = child->requirement().flex_shrink_x;
79 block.flex_shrink_y = child->requirement().flex_shrink_y;
81 global.blocks.push_back(block);
87 void ComputeRequirement()
override {
88 for (
auto& child : children_) {
89 child->ComputeRequirement();
91 flexbox_helper::Global global;
92 global.config = config_normalized_;
93 if (IsColumnOriented()) {
94 global.size_x = 100000;
95 global.size_y = asked_;
97 global.size_x = asked_;
98 global.size_y = 100000;
100 Layout(global,
true);
102 if (global.blocks.empty()) {
103 requirement_.min_x = 0;
104 requirement_.min_y = 0;
109 box.x_min = global.blocks[0].x;
110 box.y_min = global.blocks[0].y;
111 box.x_max = global.blocks[0].x + global.blocks[0].dim_x;
112 box.y_max = global.blocks[0].y + global.blocks[0].dim_y;
114 for (
auto& b : global.blocks) {
115 box.x_min = std::min(box.x_min, b.x);
116 box.y_min = std::min(box.y_min, b.y);
117 box.x_max = std::max(box.x_max, b.x + b.dim_x);
118 box.y_max = std::max(box.y_max, b.y + b.dim_y);
121 requirement_.min_x = box.x_max - box.x_min;
122 requirement_.min_y = box.y_max - box.y_min;
125 void SetBox(Box box)
override {
128 asked_ = std::min(asked_, IsColumnOriented() ? box.y_max - box.y_min + 1
129 : box.x_max - box.x_min + 1);
130 flexbox_helper::Global global;
131 global.config = config_;
132 global.size_x = box.x_max - box.x_min + 1;
133 global.size_y = box.y_max - box.y_min + 1;
136 need_iteration_ =
false;
137 for (
size_t i = 0; i < children_.size(); ++i) {
138 auto& child = children_[i];
139 auto& b = global.blocks[i];
142 children_box.x_min = box.x_min + b.x;
143 children_box.y_min = box.y_min + b.y;
144 children_box.x_max = box.x_min + b.x + b.dim_x - 1;
145 children_box.y_max = box.y_min + b.y + b.dim_y - 1;
148 child->SetBox(intersection);
150 need_iteration_ |= (intersection != children_box);
154 void Check(Status* status)
override {
155 for (
auto& child : children_) {
156 child->Check(status);
159 if (status->iteration == 0) {
161 need_iteration_ =
true;
164 status->need_iteration |= need_iteration_;
168 bool need_iteration_ =
true;
169 const FlexboxConfig config_;
170 const FlexboxConfig config_normalized_;
196 return std::make_shared<Flexbox>(std::move(children), config);
214 return flexbox(std::move(children), FlexboxConfig());
234 return flexbox(std::move(children),
virtual void SetBox(Box box)
Assign a position and a dimension to an element for drawing.
void Compute(Global &global)
Element flexbox(Elements, FlexboxConfig config=FlexboxConfig())
std::shared_ptr< Node > Element
std::vector< Element > Elements
static auto Intersection(Box a, Box b) -> Box
@ FlexStart
items are placed at the start of the cross axis.
@ Column
Flex items are laid out in a column.
@ Row
Flex items are laid out in a row.
@ RowInversed
Flex items are laid out in a row, but in reverse order.
@ Wrap
Flex items will wrap onto multiple lines.
@ FlexStart
Items are aligned to the start of flexbox's direction.