Euphoria
layout.cc
Go to the documentation of this file.
1 #include "gui/layout.h"
2 
3 #include "base/numeric.h"
4 #include "log/log.h"
5 #include "base/stringmerger.h"
6 #include "base/stringutils.h"
7 #include "base/cint.h"
8 
9 #include "gui/widget.h"
10 
11 #include <numeric>
12 #include <algorithm>
13 
14 
15 namespace eu::gui
16 {
17  Layout::Layout() = default;
18 
19 
20  Layout::~Layout() = default;
21 
22 
24  (
25  const std::vector<bool>& er,
26  const std::vector<bool>& ec,
27  float cp
28  )
29  : expandable_rows(er)
30  , expandable_cols(ec)
31  , combined_padding(cp)
32  {
33  }
34 
35 
36  namespace
37  {
38  template <typename T>
39  void
40  update_max(T* t, T value)
41  {
42  *t = max(*t, value);
43  }
44  }
45 
46 
47  size2f
49  (
50  const std::vector<std::shared_ptr<Widget>>& widgets
51  ) const
52  {
53  // todo(Gustav): include padding
54  std::vector<float> width(expandable_cols.size(), 0.0f);
55  std::vector<float> height(expandable_rows.size(), 0.0f);
56 
57  for(const auto& w: widgets)
58  {
59  const auto& d = w->layout;
60  const auto& s = w->get_preferred_size();
61  update_max(&width[d.column], s.width);
62  update_max(&height[d.row], s.height);
63  }
64 
66  (
67  std::accumulate(width.begin(), width.end(), 0.0f),
68  std::accumulate(height.begin(), height.end(), 0.0f)
69  );
70 
71  return s;
72  }
73 
74 
75  void
77  (
78  std::vector<std::shared_ptr<Widget>>* widgets,
79  const Rectf& area
80  ) const
81  {
82  // todo(Gustav): include padding
83  std::vector<float> width(expandable_cols.size(), 0.0f);
84  std::vector<float> height(expandable_rows.size(), 0.0f);
85 
86  for(const auto& w: *widgets)
87  {
88  const auto& d = w->layout;
89  const auto& s = w->get_preferred_size();
90  update_max(&width[d.column], s.width);
91  update_max(&height[d.row], s.height);
92  }
93 
94  const float total_width = std::accumulate(width.begin(), width.end(), 0.0f);
95  const float total_height = std::accumulate(height.begin(), height.end(), 0.0f);
96 
97  const float leftover_width = area.get_width() - total_width;
98  const float leftover_height = area.get_height() - total_height;
99 
100  const int expandable_rows_count = c_sizet_to_int
101  (
102  std::count(expandable_rows.begin(), expandable_rows.end(), true)
103  );
104  const int expandable_cols_count = c_sizet_to_int
105  (
106  std::count(expandable_cols.begin(), expandable_cols.end(), true)
107  );
108 
109  if(expandable_rows_count != 0)
110  {
111  const float extra = leftover_height / c_int_to_float(expandable_rows_count);
112  for(unsigned int row_index = 0; row_index < expandable_rows.size(); ++row_index)
113  {
114  if(expandable_rows[row_index])
115  {
116  height[row_index] += extra;
117  }
118  }
119  }
120 
121  if(expandable_cols_count != 0)
122  {
123  const float extra = leftover_width / c_int_to_float(expandable_cols_count);
124  for(unsigned int column_index = 0; column_index < expandable_cols.size(); ++column_index)
125  {
126  if(expandable_cols[column_index])
127  {
128  width[column_index] += extra;
129  }
130  }
131  }
132 
133  for(const auto& w: *widgets)
134  {
135  const LayoutData& d = w->layout;
136  const auto topleft = area.get_top_left();
137  float x = topleft.x;
138  float y = topleft.y;
139 
140  for(int column_index = 0; column_index < d.column; ++column_index)
141  {
142  x += width[column_index];
143  }
144  for(int row_index = 0; row_index < d.row; ++row_index)
145  {
146  y -= height[row_index];
147  }
148 
149  w->set_rect
150  (
152  (
153  vec2f{x, y},
154  width[d.column],
155  height[d.row]
156  )
157  );
158  }
159  }
160 
161 
163  : padding(p)
164  {
165  }
166 
167 
168  size2f
170  (
171  const std::vector<std::shared_ptr<Widget>>& widgets
172  ) const
173  {
174  float width = 0;
175  float height = 0;
176  bool first = false;
177 
178  for(const auto& w: widgets)
179  {
180  const auto& s = w->get_preferred_size();
181  width += s.width;
182  if(!first)
183  {
184  width += padding;
185  }
186  first = false;
187  update_max(&height, s.height);
188  }
189 
190  const auto s = size2f::create_from_width_height(width, height);
191  return s;
192  }
193 
194 
195  void
197  (
198  std::vector<std::shared_ptr<Widget>>* widgets,
199  const Rectf& area
200  ) const
201  {
202  const auto tl = area.get_top_left();
203  float x = tl.x;
204  for(const auto& w: *widgets)
205  {
206  const auto& s = w->get_preferred_size();
207  w->set_rect
208  (
210  (
211  vec2f{x, tl.y},
212  s.width,
213  s.height
214  )
215  );
216  x += s.width + padding;
217  }
218  }
219 }
220 
int c_sizet_to_int(size_t t)
Definition: cint.cc:11
constexpr float c_int_to_float(int i)
Definition: cint.h:50
size2f max(const size2f lhs, const size2f rhs)
Definition: size2.cc:149
String utility functions.
Definition: rect.h:27
float get_width() const
Definition: rect.cc:436
float get_height() const
Definition: rect.cc:430
vec2f get_top_left() const
Definition: rect.cc:461
static Rectf from_top_left_width_height(const vec2f &topleft, float width, float height)
Definition: rect.cc:86
virtual ~Layout()
size2f calc_minimum_area(const std::vector< std::shared_ptr< Widget >> &widgets) const override
Definition: layout.cc:170
void lay_out(std::vector< std::shared_ptr< Widget >> *widgets, const Rectf &area) const override
Definition: layout.cc:197
SingleRowLayout(float padding)
Definition: layout.cc:162
size2f calc_minimum_area(const std::vector< std::shared_ptr< Widget >> &widgets) const override
Definition: layout.cc:49
std::vector< bool > expandable_rows
Definition: layout.h:74
TableLayout(const std::vector< bool > &er, const std::vector< bool > &ec, float cp)
Definition: layout.cc:24
void lay_out(std::vector< std::shared_ptr< Widget >> *widgets, const Rectf &area) const override
Definition: layout.cc:77
std::vector< bool > expandable_cols
Definition: layout.h:75
static size2f create_from_width_height(float w, float h)
Definition: size2.cc:15
Definition: vec2.h:33