1use crate::{Pixels, Size};
3
4#[derive(Debug, Copy, Clone, PartialEq, Default)]
36pub struct Padding {
37    pub top: f32,
39    pub right: f32,
41    pub bottom: f32,
43    pub left: f32,
45}
46
47pub fn all(padding: impl Into<Pixels>) -> Padding {
49    Padding::new(padding.into().0)
50}
51
52pub fn top(padding: impl Into<Pixels>) -> Padding {
54    Padding::default().top(padding)
55}
56
57pub fn bottom(padding: impl Into<Pixels>) -> Padding {
59    Padding::default().bottom(padding)
60}
61
62pub fn left(padding: impl Into<Pixels>) -> Padding {
64    Padding::default().left(padding)
65}
66
67pub fn right(padding: impl Into<Pixels>) -> Padding {
69    Padding::default().right(padding)
70}
71
72impl Padding {
73    pub const ZERO: Padding = Padding {
75        top: 0.0,
76        right: 0.0,
77        bottom: 0.0,
78        left: 0.0,
79    };
80
81    pub const fn new(padding: f32) -> Padding {
83        Padding {
84            top: padding,
85            right: padding,
86            bottom: padding,
87            left: padding,
88        }
89    }
90
91    pub fn top(self, top: impl Into<Pixels>) -> Self {
95        Self {
96            top: top.into().0,
97            ..self
98        }
99    }
100
101    pub fn bottom(self, bottom: impl Into<Pixels>) -> Self {
105        Self {
106            bottom: bottom.into().0,
107            ..self
108        }
109    }
110
111    pub fn left(self, left: impl Into<Pixels>) -> Self {
115        Self {
116            left: left.into().0,
117            ..self
118        }
119    }
120
121    pub fn right(self, right: impl Into<Pixels>) -> Self {
125        Self {
126            right: right.into().0,
127            ..self
128        }
129    }
130
131    pub fn vertical(self) -> f32 {
133        self.top + self.bottom
134    }
135
136    pub fn horizontal(self) -> f32 {
138        self.left + self.right
139    }
140
141    pub fn fit(self, inner: Size, outer: Size) -> Self {
143        let available = (outer - inner).max(Size::ZERO);
144        let new_top = self.top.min(available.height);
145        let new_left = self.left.min(available.width);
146
147        Padding {
148            top: new_top,
149            bottom: self.bottom.min(available.height - new_top),
150            left: new_left,
151            right: self.right.min(available.width - new_left),
152        }
153    }
154}
155
156impl From<u16> for Padding {
157    fn from(p: u16) -> Self {
158        Padding {
159            top: f32::from(p),
160            right: f32::from(p),
161            bottom: f32::from(p),
162            left: f32::from(p),
163        }
164    }
165}
166
167impl From<[u16; 2]> for Padding {
168    fn from(p: [u16; 2]) -> Self {
169        Padding {
170            top: f32::from(p[0]),
171            right: f32::from(p[1]),
172            bottom: f32::from(p[0]),
173            left: f32::from(p[1]),
174        }
175    }
176}
177
178impl From<f32> for Padding {
179    fn from(p: f32) -> Self {
180        Padding {
181            top: p,
182            right: p,
183            bottom: p,
184            left: p,
185        }
186    }
187}
188
189impl From<[f32; 2]> for Padding {
190    fn from(p: [f32; 2]) -> Self {
191        Padding {
192            top: p[0],
193            right: p[1],
194            bottom: p[0],
195            left: p[1],
196        }
197    }
198}
199
200impl From<Padding> for Size {
201    fn from(padding: Padding) -> Self {
202        Self::new(padding.horizontal(), padding.vertical())
203    }
204}
205
206impl From<Pixels> for Padding {
207    fn from(pixels: Pixels) -> Self {
208        Self::from(pixels.0)
209    }
210}