epaint/
margin.rs

1use emath::{vec2, Rect, Vec2};
2
3/// A value for all four sides of a rectangle,
4/// often used to express padding or spacing.
5///
6/// Can be added and subtracted to/from [`Rect`]s.
7#[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    /// The same margin on every side.
25    #[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    /// Margins with the same size on opposing sides
37    #[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    /// Total margins on both sides
48    #[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    /// Are the margin on every side the same?
64    #[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
97/// `Margin + Margin`
98impl 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
112/// `Margin + f32`
113impl 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
127/// `Margind += f32`
128impl 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
138/// `Margin * f32`
139impl 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
153/// `Margin *= f32`
154impl 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
164/// `Margin / f32`
165impl 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
179/// `Margin /= f32`
180impl 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
190/// `Margin - Margin`
191impl 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
205/// `Margin - f32`
206impl 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
220/// `Margin -= f32`
221impl 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
231/// `Rect + Margin`
232impl 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
244/// `Rect += Margin`
245impl std::ops::AddAssign<Margin> for Rect {
246    #[inline]
247    fn add_assign(&mut self, margin: Margin) {
248        *self = *self + margin;
249    }
250}
251
252/// `Rect - Margin`
253impl 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
265/// `Rect -= Margin`
266impl std::ops::SubAssign<Margin> for Rect {
267    #[inline]
268    fn sub_assign(&mut self, margin: Margin) {
269        *self = *self - margin;
270    }
271}