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 
8 namespace ftxui::box_helper {
9 
10 namespace {
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.
14 void 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.
29 void 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.
45 void 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 
64 void 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