FTXUI  5.0.0
C++ functional terminal UI.
box_helper.cpp
Go to the documentation of this file.
1// Copyright 2021 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
5
6#include <algorithm> // for max
7
9
10namespace {
11// Called when the size allowed is greater than the requested size. This
12// distributes the extra spaces toward the flexible elements, in relative
13// proportions.
14void ComputeGrow(std::vector<Element>* elements,
15 int extra_space,
16 int flex_grow_sum) {
17 for (Element& element : *elements) {
18 const int added_space =
19 extra_space * element.flex_grow / std::max(flex_grow_sum, 1);
20 extra_space -= added_space;
21 flex_grow_sum -= element.flex_grow;
22 element.size = element.min_size + added_space;
23 }
24}
25
26// Called when the size allowed is lower than the requested size, and the
27// shrinkable element can absorbe the (negative) extra_space. This distribute
28// the extra_space toward those.
29void ComputeShrinkEasy(std::vector<Element>* elements,
30 int extra_space,
31 int flex_shrink_sum) {
32 for (Element& element : *elements) {
33 const int added_space = extra_space * element.min_size *
34 element.flex_shrink / std::max(flex_shrink_sum, 1);
35 extra_space -= added_space;
36 flex_shrink_sum -= element.flex_shrink * element.min_size;
37 element.size = element.min_size + added_space;
38 }
39}
40
41// Called when the size allowed is lower than the requested size, and the
42// shrinkable element can not absorbe the (negative) extra_space. This assign
43// zero to shrinkable elements and distribute the remaining (negative)
44// extra_space toward the other non shrinkable elements.
45void ComputeShrinkHard(std::vector<Element>* elements,
46 int extra_space,
47 int size) {
48 for (Element& element : *elements) {
49 if (element.flex_shrink != 0) {
50 element.size = 0;
51 continue;
52 }
53
54 const int added_space = extra_space * element.min_size / std::max(1, size);
55 extra_space -= added_space;
56 size -= element.min_size;
57
58 element.size = element.min_size + added_space;
59 }
60}
61
62} // namespace
63
64void Compute(std::vector<Element>* elements, int target_size) {
65 int size = 0;
66 int flex_grow_sum = 0;
67 int flex_shrink_sum = 0;
68 int flex_shrink_size = 0;
69
70 for (auto& element : *elements) {
71 flex_grow_sum += element.flex_grow;
72 flex_shrink_sum += element.min_size * element.flex_shrink;
73 if (element.flex_shrink != 0) {
74 flex_shrink_size += element.min_size;
75 }
76 size += element.min_size;
77 }
78
79 const int extra_space = target_size - size;
80 if (extra_space >= 0) {
81 ComputeGrow(elements, extra_space, flex_grow_sum);
82 } else if (flex_shrink_size + extra_space >= 0) {
83 ComputeShrinkEasy(elements, extra_space, flex_shrink_sum);
84
85 } else {
86 ComputeShrinkHard(elements, extra_space + flex_shrink_size,
87 size - flex_shrink_size);
88 }
89}
90
91} // namespace ftxui::box_helper
void Compute(std::vector< Element > *elements, int target_size)
Definition: box_helper.cpp:64
Decorator size(WidthOrHeight, Constraint, int value)
Apply a constraint on the size of an element.
Definition: size.cpp:90