HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
grid_layout.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../required.hpp"
8#include "../assert.hpp"
9#include "../math.hpp"
10#include <tuple>
11#include <vector>
12#include <cstddef>
13#include <functional>
14
15namespace hi::inline v1 {
16
23public:
24 grid_layout(grid_layout const &) = delete;
25 grid_layout(grid_layout &&) = delete;
26 grid_layout &operator=(grid_layout const &) = delete;
27 grid_layout &operator=(grid_layout &&) = delete;
28
29 grid_layout() noexcept {}
30
33 void clear() noexcept
34 {
35 _num_cells = 0;
36 _constraints.clear();
37 _cells.clear();
38 }
39
50 void add_constraint(std::size_t first, std::size_t last, float minimum, float preferred, float maximum, float margin_before, float margin_after) noexcept
51 {
52 _num_cells = std::max(_num_cells, last);
53 _constraints.emplace_back(first, last, minimum, preferred, maximum, margin_before, margin_after);
54 }
55
65 void add_constraint(std::size_t index, float minimum, float preferred, float maximum, float margin_before, float margin_after) noexcept
66 {
67 return add_constraint(index, index + 1, minimum, preferred, maximum, margin_before, margin_after);
68 }
69
78 void commit_constraints() noexcept;
79
84 [[nodiscard]] std::size_t num_cells() const noexcept
85 {
86 return _num_cells;
87 }
88
93 [[nodiscard]] float minimum() const noexcept
94 {
95 return _minimum;
96 }
97
102 [[nodiscard]] float preferred() const noexcept
103 {
104 return _preferred;
105 }
106
111 [[nodiscard]] float maximum() const noexcept
112 {
113 return _maximum;
114 }
115
116 [[nodiscard]] float margin_before() const noexcept
117 {
118 return _cells.front().margin;
119 }
120
121 [[nodiscard]] float margin_after() const noexcept
122 {
123 return _cells.back().margin;
124 }
125
130 void layout(float size) noexcept;
131
137 [[nodiscard]] float get_position(std::size_t index) const noexcept
138 {
139 hi_axiom(index < num_cells());
140 return get_position(_cells.begin(), _cells.begin() + index);
141 }
142
149 [[nodiscard]] float get_size(std::size_t first, std::size_t last) const noexcept
150 {
151 hi_axiom(first <= last);
152 hi_axiom(last <= _cells.size());
153 return get_size(_cells.begin() + first, _cells.begin() + last);
154 }
155
161 [[nodiscard]] float get_size(std::size_t index) const noexcept
162 {
163 return get_size(index, index + 1);
164 }
165
173 {
174 return {get_position(first), get_size(first, last)};
175 }
176
183 {
184 return get_position_and_size(index, index + 1);
185 }
186
194 {
195 hilet position = get_position(first);
196 hilet size = get_size(first, last);
197 return {position, position + size};
198 }
199
207 {
208 return get_positions(index, index + 1);
209 }
210
211private:
212 struct constraint_type {
213 std::size_t first;
214 std::size_t last;
215 float minimum;
216 float preferred;
217 float maximum;
218 float margin_before;
219 float margin_after;
220
221 [[nodiscard]] bool is_single_cell() const noexcept
222 {
223 return first == last - 1;
224 }
225
226 [[nodiscard]] bool is_span() const noexcept
227 {
228 return not is_single_cell();
229 }
230 };
231
232 struct cell_type {
235 float size;
236
239 float margin;
240
243 float minimum;
244
247 float preferred;
248
251 float maximum;
252
253 cell_type() noexcept :
254 size(0.0f), margin(0.0f), minimum(0.0f), preferred(0.0f), maximum(std::numeric_limits<float>::infinity())
255 {
256 }
257
258 void fix_constraint() noexcept
259 {
260 inplace_max(maximum, minimum);
261 inplace_clamp(preferred, minimum, maximum);
262 }
263
264 void set_constraint(constraint_type const &constraint) noexcept
265 {
266 inplace_max(minimum, constraint.minimum);
267 inplace_max(preferred, constraint.preferred);
268 inplace_min(maximum, constraint.maximum);
269 }
270
271 [[nodiscard]] bool holds_invariant() const noexcept
272 {
273 return minimum <= preferred and preferred <= maximum;
274 }
275 };
276
277 using contraint_vector_type = std::vector<constraint_type>;
278 using cell_vector_type = std::vector<cell_type>;
279 using cell_iterator = cell_vector_type::iterator;
280 using cell_const_iterator = cell_vector_type::const_iterator;
281
282 std::size_t _num_cells = 0;
283 float _minimum = 0.0f;
284 float _preferred = 0.0f;
285 float _maximum = 0.0f;
286 contraint_vector_type _constraints;
287 cell_vector_type _cells;
288
295 [[nodiscard]] float get_position(cell_const_iterator begin, cell_const_iterator first) const noexcept
296 {
297 auto it = begin;
298 auto position = 0.0f;
299 while (it != first) {
300 position += it->size;
301 ++it;
302 position += it->margin;
303 }
304 return position;
305 }
306
313 [[nodiscard]] static float get_size(cell_const_iterator first, cell_const_iterator last) noexcept
314 {
315 if (first == last) {
316 return 0.0f;
317 }
318
319 auto it = first;
320 auto size = it->size;
321 ++it;
322 for (; it != last; ++it) {
323 size += it->margin;
324 size += it->size;
325 }
326 return size;
327 }
328
329 void constrain_cells_by_singles() noexcept;
330 void constrain_cells_by_spans(std::function<float(constraint_type const &)> const &predicate) noexcept;
331 [[nodiscard]] bool holds_invariant() const noexcept;
332};
333
334} // namespace hi::inline v1
This file includes required definitions.
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
STL namespace.
Grid layout is used to layout widgets along an axis.
Definition grid_layout.hpp:22
float minimum() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:93
float maximum() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:111
void commit_constraints() noexcept
Commit all the constraints.
float preferred() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:102
void add_constraint(std::size_t first, std::size_t last, float minimum, float preferred, float maximum, float margin_before, float margin_after) noexcept
Add a constraint for a widget.
Definition grid_layout.hpp:50
void clear() noexcept
Clear the list of widgets in the layout.
Definition grid_layout.hpp:33
std::pair< float, float > get_positions(std::size_t first, std::size_t last) const noexcept
Get the start and end position of the cells.
Definition grid_layout.hpp:193
std::pair< float, float > get_positions(std::size_t index) const noexcept
Get the start and end position of a cell.
Definition grid_layout.hpp:206
float get_size(std::size_t index) const noexcept
Get size of the cell.
Definition grid_layout.hpp:161
void layout(float size) noexcept
Layout the cells based on the total size.
float get_size(std::size_t first, std::size_t last) const noexcept
Get size of the cells.
Definition grid_layout.hpp:149
std::pair< float, float > get_position_and_size(std::size_t first, std::size_t last) const noexcept
Get the position and size of a cell-span.
Definition grid_layout.hpp:172
float get_position(std::size_t index) const noexcept
Get position of cell.
Definition grid_layout.hpp:137
void add_constraint(std::size_t index, float minimum, float preferred, float maximum, float margin_before, float margin_after) noexcept
Add a constraint for a widget.
Definition grid_layout.hpp:65
std::pair< float, float > get_position_and_size(std::size_t index) const noexcept
Get the position and size of cell.
Definition grid_layout.hpp:182
T begin(T... args)
T max(T... args)