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