1use emath::{vec2, Rect, Vec2};
2
3#[derive(Clone, Copy, Debug, Default, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
9pub struct Margin {
10 pub left: f32,
11 pub right: f32,
12 pub top: f32,
13 pub bottom: f32,
14}
15
16impl Margin {
17 pub const ZERO: Self = Self {
18 left: 0.0,
19 right: 0.0,
20 top: 0.0,
21 bottom: 0.0,
22 };
23
24 #[doc(alias = "symmetric")]
26 #[inline]
27 pub const fn same(margin: f32) -> Self {
28 Self {
29 left: margin,
30 right: margin,
31 top: margin,
32 bottom: margin,
33 }
34 }
35
36 #[inline]
38 pub const fn symmetric(x: f32, y: f32) -> Self {
39 Self {
40 left: x,
41 right: x,
42 top: y,
43 bottom: y,
44 }
45 }
46
47 #[inline]
49 pub fn sum(&self) -> Vec2 {
50 vec2(self.left + self.right, self.top + self.bottom)
51 }
52
53 #[inline]
54 pub const fn left_top(&self) -> Vec2 {
55 vec2(self.left, self.top)
56 }
57
58 #[inline]
59 pub const fn right_bottom(&self) -> Vec2 {
60 vec2(self.right, self.bottom)
61 }
62
63 #[doc(alias = "symmetric")]
65 #[inline]
66 pub fn is_same(&self) -> bool {
67 self.left == self.right && self.left == self.top && self.left == self.bottom
68 }
69
70 #[deprecated = "Use `rect + margin` instead"]
71 #[inline]
72 pub fn expand_rect(&self, rect: Rect) -> Rect {
73 Rect::from_min_max(rect.min - self.left_top(), rect.max + self.right_bottom())
74 }
75
76 #[deprecated = "Use `rect - margin` instead"]
77 #[inline]
78 pub fn shrink_rect(&self, rect: Rect) -> Rect {
79 Rect::from_min_max(rect.min + self.left_top(), rect.max - self.right_bottom())
80 }
81}
82
83impl From<f32> for Margin {
84 #[inline]
85 fn from(v: f32) -> Self {
86 Self::same(v)
87 }
88}
89
90impl From<Vec2> for Margin {
91 #[inline]
92 fn from(v: Vec2) -> Self {
93 Self::symmetric(v.x, v.y)
94 }
95}
96
97impl std::ops::Add for Margin {
99 type Output = Self;
100
101 #[inline]
102 fn add(self, other: Self) -> Self {
103 Self {
104 left: self.left + other.left,
105 right: self.right + other.right,
106 top: self.top + other.top,
107 bottom: self.bottom + other.bottom,
108 }
109 }
110}
111
112impl std::ops::Add<f32> for Margin {
114 type Output = Self;
115
116 #[inline]
117 fn add(self, v: f32) -> Self {
118 Self {
119 left: self.left + v,
120 right: self.right + v,
121 top: self.top + v,
122 bottom: self.bottom + v,
123 }
124 }
125}
126
127impl std::ops::AddAssign<f32> for Margin {
129 #[inline]
130 fn add_assign(&mut self, v: f32) {
131 self.left += v;
132 self.right += v;
133 self.top += v;
134 self.bottom += v;
135 }
136}
137
138impl std::ops::Mul<f32> for Margin {
140 type Output = Self;
141
142 #[inline]
143 fn mul(self, v: f32) -> Self {
144 Self {
145 left: self.left * v,
146 right: self.right * v,
147 top: self.top * v,
148 bottom: self.bottom * v,
149 }
150 }
151}
152
153impl std::ops::MulAssign<f32> for Margin {
155 #[inline]
156 fn mul_assign(&mut self, v: f32) {
157 self.left *= v;
158 self.right *= v;
159 self.top *= v;
160 self.bottom *= v;
161 }
162}
163
164impl std::ops::Div<f32> for Margin {
166 type Output = Self;
167
168 #[inline]
169 fn div(self, v: f32) -> Self {
170 Self {
171 left: self.left / v,
172 right: self.right / v,
173 top: self.top / v,
174 bottom: self.bottom / v,
175 }
176 }
177}
178
179impl std::ops::DivAssign<f32> for Margin {
181 #[inline]
182 fn div_assign(&mut self, v: f32) {
183 self.left /= v;
184 self.right /= v;
185 self.top /= v;
186 self.bottom /= v;
187 }
188}
189
190impl std::ops::Sub for Margin {
192 type Output = Self;
193
194 #[inline]
195 fn sub(self, other: Self) -> Self {
196 Self {
197 left: self.left - other.left,
198 right: self.right - other.right,
199 top: self.top - other.top,
200 bottom: self.bottom - other.bottom,
201 }
202 }
203}
204
205impl std::ops::Sub<f32> for Margin {
207 type Output = Self;
208
209 #[inline]
210 fn sub(self, v: f32) -> Self {
211 Self {
212 left: self.left - v,
213 right: self.right - v,
214 top: self.top - v,
215 bottom: self.bottom - v,
216 }
217 }
218}
219
220impl std::ops::SubAssign<f32> for Margin {
222 #[inline]
223 fn sub_assign(&mut self, v: f32) {
224 self.left -= v;
225 self.right -= v;
226 self.top -= v;
227 self.bottom -= v;
228 }
229}
230
231impl std::ops::Add<Margin> for Rect {
233 type Output = Self;
234
235 #[inline]
236 fn add(self, margin: Margin) -> Self {
237 Self::from_min_max(
238 self.min - margin.left_top(),
239 self.max + margin.right_bottom(),
240 )
241 }
242}
243
244impl std::ops::AddAssign<Margin> for Rect {
246 #[inline]
247 fn add_assign(&mut self, margin: Margin) {
248 *self = *self + margin;
249 }
250}
251
252impl std::ops::Sub<Margin> for Rect {
254 type Output = Self;
255
256 #[inline]
257 fn sub(self, margin: Margin) -> Self {
258 Self::from_min_max(
259 self.min + margin.left_top(),
260 self.max - margin.right_bottom(),
261 )
262 }
263}
264
265impl std::ops::SubAssign<Margin> for Rect {
267 #[inline]
268 fn sub_assign(&mut self, margin: Margin) {
269 *self = *self - margin;
270 }
271}