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 "widget_baseline.hpp"
11#include <tuple>
12#include <vector>
13#include <cstddef>
14#include <functional>
15
16namespace hi::inline 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
52 std::size_t first,
53 std::size_t last,
54 float minimum,
55 float preferred,
56 float maximum,
57 float margin_before,
58 float margin_after,
59 widget_baseline baseline = widget_baseline{}) noexcept
60 {
61 _num_cells = std::max(_num_cells, last);
62 _constraints.emplace_back(first, last, minimum, preferred, maximum, margin_before, margin_after, baseline);
63 }
64
75 std::size_t index,
76 float minimum,
77 float preferred,
78 float maximum,
79 float margin_before,
80 float margin_after,
81 widget_baseline baseline = widget_baseline{}) noexcept
82 {
83 return add_constraint(index, index + 1, minimum, preferred, maximum, margin_before, margin_after, baseline);
84 }
85
94 void commit_constraints() noexcept;
95
100 [[nodiscard]] std::size_t num_cells() const noexcept
101 {
102 return _num_cells;
103 }
104
109 [[nodiscard]] float minimum() const noexcept
110 {
111 return _minimum;
112 }
113
118 [[nodiscard]] float preferred() const noexcept
119 {
120 return _preferred;
121 }
122
127 [[nodiscard]] float maximum() const noexcept
128 {
129 return _maximum;
130 }
131
132 [[nodiscard]] float margin_before() const noexcept
133 {
134 return _cells.front().margin;
135 }
136
137 [[nodiscard]] float margin_after() const noexcept
138 {
139 return _cells.back().margin;
140 }
141
146 void layout(float size) noexcept;
147
153 [[nodiscard]] float get_position(std::size_t index) const noexcept
154 {
155 hi_axiom(index < num_cells());
156 return get_position(_cells.begin(), _cells.begin() + index);
157 }
158
165 [[nodiscard]] float get_size(std::size_t first, std::size_t last) const noexcept
166 {
167 hi_axiom(first <= last);
168 hi_axiom(last <= _cells.size());
169 return get_size(_cells.begin() + first, _cells.begin() + last);
170 }
171
177 [[nodiscard]] float get_size(std::size_t index) const noexcept
178 {
179 return get_size(index, index + 1);
180 }
181
189 {
190 return {get_position(first), get_size(first, last)};
191 }
192
199 {
200 return get_position_and_size(index, index + 1);
201 }
202
210 {
211 hilet position = get_position(first);
212 hilet size = get_size(first, last);
213 return {position, position + size};
214 }
215
223 {
224 return get_positions(index, index + 1);
225 }
226
227 [[nodiscard]] widget_baseline get_baseline(std::size_t first, std::size_t last) const noexcept
228 {
229 for (auto i = first; i != last; ++i) {
230 if (_cells[i].baseline) {
231 return _cells[i].baseline;
232 }
233 }
234 return {};
235 }
236
237 [[nodiscard]] widget_baseline get_baseline(std::size_t index) const noexcept
238 {
239 return get_baseline(index, index + 1);
240 }
241
242private:
243 struct constraint_type {
244 std::size_t first;
245 std::size_t last;
246 float minimum;
247 float preferred;
248 float maximum;
249 float margin_before;
250 float margin_after;
251 widget_baseline baseline;
252
253 [[nodiscard]] bool is_single_cell() const noexcept
254 {
255 return first == last - 1;
256 }
257
258 [[nodiscard]] bool is_span() const noexcept
259 {
260 return not is_single_cell();
261 }
262 };
263
264 struct cell_type {
267 float size;
268
271 float margin;
272
275 float minimum;
276
279 float preferred;
280
283 float maximum;
284
287 widget_baseline baseline;
288
289 cell_type() noexcept :
290 size(0.0f),
291 margin(0.0f),
292 minimum(0.0f),
293 preferred(0.0f),
294 maximum(std::numeric_limits<float>::infinity()),
295 baseline()
296 {
297 }
298
299 void fix_constraint() noexcept
300 {
301 inplace_max(maximum, minimum);
302 inplace_clamp(preferred, minimum, maximum);
303 }
304
305 void set_constraint(constraint_type const& constraint) noexcept
306 {
307 inplace_max(minimum, constraint.minimum);
308 inplace_max(preferred, constraint.preferred);
309 inplace_min(maximum, constraint.maximum);
310 }
311
312 [[nodiscard]] bool holds_invariant() const noexcept
313 {
314 return minimum <= preferred and preferred <= maximum;
315 }
316 };
317
318 using contraint_vector_type = std::vector<constraint_type>;
319 using cell_vector_type = std::vector<cell_type>;
320 using cell_iterator = cell_vector_type::iterator;
321 using cell_const_iterator = cell_vector_type::const_iterator;
322
323 std::size_t _num_cells = 0;
324 float _minimum = 0.0f;
325 float _preferred = 0.0f;
326 float _maximum = 0.0f;
327 contraint_vector_type _constraints;
328 cell_vector_type _cells;
329
336 [[nodiscard]] float get_position(cell_const_iterator begin, cell_const_iterator first) const noexcept
337 {
338 auto it = begin;
339 auto position = 0.0f;
340 while (it != first) {
341 position += it->size;
342 ++it;
343 position += it->margin;
344 }
345 return position;
346 }
347
354 [[nodiscard]] static float get_size(cell_const_iterator first, cell_const_iterator last) noexcept
355 {
356 if (first == last) {
357 return 0.0f;
358 }
359
360 auto it = first;
361 auto size = it->size;
362 ++it;
363 for (; it != last; ++it) {
364 size += it->margin;
365 size += it->size;
366 }
367 return size;
368 }
369
370 void constrain_cells_by_singles() noexcept;
371 void constrain_cells_by_spans(std::function<float(constraint_type const&)> const& predicate) noexcept;
372 [[nodiscard]] bool holds_invariant() const noexcept;
373};
374
375} // 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:23
float minimum() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:109
float maximum() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:127
void commit_constraints() noexcept
Commit all the constraints.
float preferred() const noexcept
The minimum size of the total grid_layout.
Definition grid_layout.hpp:118
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:74
void clear() noexcept
Clear the list of widgets in the layout.
Definition grid_layout.hpp:34
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:209
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:222
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:51
float get_size(std::size_t index) const noexcept
Get size of the cell.
Definition grid_layout.hpp:177
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:165
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:188
float get_position(std::size_t index) const noexcept
Get position of cell.
Definition grid_layout.hpp:153
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:198
The base-line of a widget on which to set the text and graphics.
Definition widget_baseline.hpp:13
T begin(T... args)
T max(T... args)