HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
box_constraints.hpp
1// Copyright Take Vos 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
8#include "../geometry/margins.hpp"
10#include "../assert.hpp"
11#include "../cast.hpp"
12#include <cstdint>
13#include <limits>
14#include <concepts>
15
16namespace hi { inline namespace v1 {
17
26 extent2i minimum = {};
27 extent2i preferred = {};
28 extent2i maximum = {};
29 marginsi margins = {};
30 marginsi padding = {};
31
32 hi::alignment alignment = hi::alignment{};
33
34 constexpr box_constraints() noexcept = default;
35 constexpr box_constraints(box_constraints const&) noexcept = default;
36 constexpr box_constraints(box_constraints&&) noexcept = default;
37 constexpr box_constraints& operator=(box_constraints const&) noexcept = default;
38 constexpr box_constraints& operator=(box_constraints&&) noexcept = default;
39 [[nodiscard]] constexpr friend bool operator==(box_constraints const&, box_constraints const&) noexcept = default;
40
41 constexpr box_constraints(
42 extent2i minimum,
43 extent2i preferred,
44 extent2i maximum,
45 hi::alignment alignment = hi::alignment{},
47 hi::marginsi padding = hi::marginsi{}) noexcept :
48 minimum(minimum), preferred(preferred), maximum(maximum), margins(margins), padding(padding), alignment(alignment)
49 {
50 hi_axiom(holds_invariant());
51 }
52
53 [[nodiscard]] constexpr box_constraints internalize_margins() const noexcept
54 {
55 auto r = *this;
56 r.padding += r.margins;
57
58 r.minimum.width() += r.margins.left() + r.margins.right();
59 r.preferred.width() += r.margins.left() + r.margins.right();
60 r.maximum.width() += r.margins.left() + r.margins.right();
61
62 r.minimum.height() += r.margins.bottom() + r.margins.top();
63 r.preferred.height() += r.margins.bottom() + r.margins.top();
64 r.maximum.height() += r.margins.bottom() + r.margins.top();
65
66 r.margins = 0;
67 hi_axiom(r.holds_invariant());
68 return r;
69 }
70
71 [[nodiscard]] constexpr box_constraints constrain(extent2i new_minimum, extent2i new_maximum) const noexcept
72 {
73 hi_assert(new_minimum <= new_maximum);
74
75 auto r = *this;
76
77 inplace_max(r.minimum, new_minimum);
78 inplace_min(r.maximum, new_maximum);
79
80 inplace_max(r.preferred, r.minimum);
81 inplace_max(r.maximum, r.preferred);
82 hi_axiom(r.holds_invariant());
83 return r;
84 }
85
86 constexpr box_constraints& operator+=(extent2i const& rhs) noexcept
87 {
88 minimum.width() += rhs.width();
89 preferred.width() += rhs.width();
90 maximum.width() += rhs.width();
91 minimum.height() += rhs.height();
92 preferred.height() += rhs.height();
93 maximum.height() += rhs.height();
94
95 hi_axiom(holds_invariant());
96 return *this;
97 }
98
99 [[nodiscard]] constexpr box_constraints operator+(extent2i const& rhs) const noexcept
100 {
101 auto r = *this;
102 r += rhs;
103 return r;
104 }
105
106 [[deprecated]] constexpr box_constraints& operator+=(extent2 const& rhs) noexcept
107 {
108 *this += narrow_cast<extent2i>(rhs);
109 return *this;
110 }
111
112 [[nodiscard]] constexpr bool holds_invariant() const noexcept
113 {
114 if (alignment == horizontal_alignment::flush or alignment == horizontal_alignment::justified) {
115 return false;
116 }
117 if (minimum > preferred or preferred > maximum) {
118 return false;
119 }
120 return true;
121 }
122
123 [[nodiscard]] friend constexpr box_constraints max(box_constraints const& lhs, extent2i const& rhs) noexcept
124 {
125 auto r = lhs;
126 inplace_max(r.minimum, rhs);
127 inplace_max(r.preferred, rhs);
128 inplace_max(r.maximum, rhs);
129
130 hi_axiom(r.holds_invariant());
131 return r;
132 }
133
141 [[nodiscard]] friend constexpr box_constraints max(box_constraints const& lhs, box_constraints const& rhs) noexcept
142 {
143 auto r = lhs;
144 inplace_max(r.minimum, rhs.minimum);
145 inplace_max(r.preferred, rhs.preferred);
146 inplace_max(r.maximum, rhs.maximum);
147 inplace_max(r.margins, rhs.margins);
148 inplace_max(r.padding, rhs.padding);
149
150 hi_axiom(r.holds_invariant());
151 return r;
152 }
153
154 template<std::convertible_to<box_constraints>... Args>
155 [[nodiscard]] friend constexpr box_constraints
156 max(box_constraints const& first, box_constraints const& second, box_constraints const& third, Args const&...args) noexcept
157 {
158 return max(first, max(second, third, args...));
159 }
160};
161
162}} // namespace hi::v1
Utilities to assert and bound check.
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:87
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
Defined the geo::extent, extent2 and extent3 types.
types and utilities for alignment.
geo::extent< int, 2 > extent2i
A 2D extent.
Definition extent.hpp:513
DOXYGEN BUG.
Definition algorithm.hpp:15
geometry/margins.hpp
Definition assert.hpp:18
2D constraints.
Definition box_constraints.hpp:25
friend constexpr box_constraints max(box_constraints const &lhs, box_constraints const &rhs) noexcept
Makes a constraint that encompasses both given constraints.
Definition box_constraints.hpp:141