HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
grid_layout.hpp
1// Copyright Take Vos 2021-2022.
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 "../utility.hpp"
8#include "../assert.hpp"
9#include "../math.hpp"
10#include "widget_baseline.hpp"
11#include <tuple>
12#include <vector>
13#include <cstddef>
14#include <functional>
15
16namespace hi { inline namespace v1 {
17
24public:
25 grid_layout(grid_layout const&) = delete;
26 grid_layout(grid_layout&&) = delete;
27 grid_layout& operator=(grid_layout const&) = delete;
28 grid_layout& operator=(grid_layout&&) = delete;
29
30 grid_layout() noexcept {}
31
34 void clear() noexcept
35 {
36 _num_cells = 0;
37 _constraints.clear();
38 _cells.clear();
39 }
40
53 std::size_t first,
54 std::size_t last,
55 float minimum,
56 float preferred,
57 float maximum,
58 float margin_before,
59 float margin_after,
60 widget_baseline baseline = widget_baseline{}) noexcept
61 {
62 _num_cells = std::max(_num_cells, last);
63 _constraints.emplace_back(first, last, minimum, preferred, maximum, margin_before, margin_after, baseline);
64 }
65
77 std::size_t index,
78 float minimum,
79 float preferred,
80 float maximum,
81 float margin_before,
82 float margin_after,
83 widget_baseline baseline = widget_baseline{}) noexcept
84 {
85 return add_constraint(index, index + 1, minimum, preferred, maximum, margin_before, margin_after, baseline);
86 }
87
96 void commit_constraints() noexcept;
97
102 [[nodiscard]] std::size_t num_cells() const noexcept
103 {
104 return _num_cells;
105 }
106
111 [[nodiscard]] float minimum() const noexcept
112 {
113 return _minimum;
114 }
115
120 [[nodiscard]] float preferred() const noexcept
121 {
122 return _preferred;
123 }
124
129 [[nodiscard]] float maximum() const noexcept
130 {
131 return _maximum;
132 }
133
134 [[nodiscard]] float margin_before() const noexcept
135 {
136 return _cells.front().margin;
137 }
138
139 [[nodiscard]] float margin_after() const noexcept
140 {
141 return _cells.back().margin;
142 }
143
148 void layout(float size) noexcept;
149
155 [[nodiscard]] float get_position(std::size_t index) const noexcept
156 {
157 hi_assert(index < num_cells());
158 return get_position(_cells.begin(), _cells.begin() + index);
159 }
160
167 [[nodiscard]] float get_size(std::size_t first, std::size_t last) const noexcept
168 {
169 hi_assert(first <= last);
170 hi_assert(last <= _cells.size());
171 return get_size(_cells.begin() + first, _cells.begin() + last);
172 }
173
179 [[nodiscard]] float get_size(std::size_t index) const noexcept
180 {
181 return get_size(index, index + 1);
182 }
183
191 {
192 return {get_position(first), get_size(first, last)};
193 }
194
201 {
202 return get_position_and_size(index, index + 1);
203 }
204
212 {
213 hilet position = get_position(first);
214 hilet size = get_size(first, last);
215 return {position, position + size};
216 }
217
225 {
226 return get_positions(index, index + 1);
227 }
228
229 [[nodiscard]] widget_baseline get_baseline(std::size_t first, std::size_t last) const noexcept
230 {
231 for (auto i = first; i != last; ++i) {
232 if (_cells[i].baseline) {
233 return _cells[i].baseline;
234 }
235 }
236 return {};
237 }
238
239 [[nodiscard]] widget_baseline get_baseline(std::size_t index) const noexcept
240 {
241 return get_baseline(index, index + 1);
242 }
243
244private:
245 struct constraint_type {
246 std::size_t first;
247 std::size_t last;
248 float minimum;
249 float preferred;
250 float maximum;
251 float margin_before;
252 float margin_after;
253 widget_baseline baseline;
254
255 [[nodiscard]] bool is_single_cell() const noexcept
256 {
257 return first == last - 1;
258 }
259
260 [[nodiscard]] bool is_span() const noexcept
261 {
262 return not is_single_cell();
263 }
264 };
265
266 struct cell_type {
269 float size;
270
273 float margin;
274
277 float minimum;
278
281 float preferred;
282
285 float maximum;
286
289 widget_baseline baseline;
290
291 cell_type() noexcept :
292 size(0.0f), margin(0.0f), minimum(0.0f), preferred(0.0f), maximum(std::numeric_limits<float>::infinity()), baseline()
293 {
294 }
295
296 void fix_constraint() noexcept
297 {
298 inplace_max(maximum, minimum);
299 inplace_clamp(preferred, minimum, maximum);
300 }
301
302 void set_constraint(constraint_type const& constraint) noexcept
303 {
304 inplace_max(minimum, constraint.minimum);
305 inplace_max(preferred, constraint.preferred);
306 inplace_min(maximum, constraint.maximum);
307 }
308
309 [[nodiscard]] bool holds_invariant() const noexcept
310 {
311 return minimum <= preferred and preferred <= maximum;
312 }
313 };
314
315 using contraint_vector_type = std::vector<constraint_type>;
316 using cell_vector_type = std::vector<cell_type>;
317 using cell_iterator = cell_vector_type::iterator;
318 using cell_const_iterator = cell_vector_type::const_iterator;
319
320 std::size_t _num_cells = 0;
321 float _minimum = 0.0f;
322 float _preferred = 0.0f;
323 float _maximum = 0.0f;
324 contraint_vector_type _constraints;
325 cell_vector_type _cells;
326
333 [[nodiscard]] float get_position(cell_const_iterator begin, cell_const_iterator first) const noexcept
334 {
335 auto it = begin;
336 auto position = 0.0f;
337 while (it != first) {
338 position += it->size;
339 ++it;
340 position += it->margin;
341 }
342 return position;
343 }
344
351 [[nodiscard]] static float get_size(cell_const_iterator first, cell_const_iterator last) noexcept
352 {
353 if (first == last) {
354 return 0.0f;
355 }
356
357 auto it = first;
358 auto size = it->size;
359 ++it;
360 for (; it != last; ++it) {
361 size += it->margin;
362 size += it->size;
363 }
364 return size;
365 }
366
367 void constrain_cells_by_singles() noexcept;
368 void constrain_cells_by_spans(std::function<float(constraint_type const&)> const& predicate) noexcept;
369 [[nodiscard]] bool holds_invariant() const noexcept;
370};
371
372}} // namespace hi::v1
Utilities to assert and bound check.
#define hi_assert(expression)
Assert if expression is true.
Definition assert.hpp:86
Miscellaneous math functions.
Utilities used by the HikoGUI library itself.
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Defines widget_baseline.
@ begin
Start from the beginning of the file.
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:15
The HikoGUI namespace.
Definition ascii.hpp:19
Grid layout is used to layout widgets along an axis.
Definition grid_layout.hpp:23
float get_size(std::size_t index) const noexcept
Get size of the cell.
Definition grid_layout.hpp:179
void add_constraint(std::size_t first, std::size_t last, float minimum, float preferred, float maximum, float margin_before, float margin_after, widget_baseline baseline=widget_baseline{}) noexcept
Add a constraint for a widget.
Definition grid_layout.hpp:52
void commit_constraints() noexcept
Commit all the constraints.
float maximum() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:129
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:200
void clear() noexcept
Clear the list of widgets in the layout.
Definition grid_layout.hpp:34
void layout(float size) noexcept
Layout the cells based on the total size.
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:224
void add_constraint(std::size_t index, float minimum, float preferred, float maximum, float margin_before, float margin_after, widget_baseline baseline=widget_baseline{}) noexcept
Add a constraint for a widget.
Definition grid_layout.hpp:76
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:190
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:211
float get_size(std::size_t first, std::size_t last) const noexcept
Get size of the cells.
Definition grid_layout.hpp:167
float get_position(std::size_t index) const noexcept
Get position of cell.
Definition grid_layout.hpp:155
float preferred() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:120
float minimum() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:111
std::size_t num_cells() const noexcept
The number of cells of the grid_layout.
Definition grid_layout.hpp:102
The base-line of a widget on which to set the text and graphics.
Definition widget_baseline.hpp:19
T back(T... args)
T begin(T... args)
T clear(T... args)
T emplace_back(T... args)
T front(T... args)
T max(T... args)
T size(T... args)