1use crate::RenderModifier;
2use ratatui::layout::Rect;
3
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31#[cfg_attr(feature = "serde", serde(default))]
32#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
33pub struct Padding {
34 pub left: u16,
36 pub right: u16,
38 pub top: u16,
40 pub bottom: u16,
42}
43
44impl Padding {
45 pub const ZERO: Self = Self {
47 left: 0,
48 right: 0,
49 top: 0,
50 bottom: 0,
51 };
52
53 #[must_use = "constructor returns a new instance"]
57 pub const fn new(left: u16, right: u16, top: u16, bottom: u16) -> Self {
58 Self {
59 left,
60 right,
61 top,
62 bottom,
63 }
64 }
65
66 #[must_use = "constructor returns a new instance"]
68 pub const fn horizontal(value: u16) -> Self {
69 Self {
70 left: value,
71 right: value,
72 top: 0,
73 bottom: 0,
74 }
75 }
76
77 #[must_use = "constructor returns a new instance"]
79 pub const fn vertical(value: u16) -> Self {
80 Self {
81 left: 0,
82 right: 0,
83 top: value,
84 bottom: value,
85 }
86 }
87
88 #[must_use = "constructor returns a new instance"]
90 pub const fn uniform(value: u16) -> Self {
91 Self {
92 left: value,
93 right: value,
94 top: value,
95 bottom: value,
96 }
97 }
98
99 #[must_use = "constructor returns a new instance"]
104 pub const fn proportional(value: u16) -> Self {
105 Self {
106 left: 2 * value,
107 right: 2 * value,
108 top: value,
109 bottom: value,
110 }
111 }
112
113 #[must_use = "constructor returns a new instance"]
118 pub const fn symmetric(x: u16, y: u16) -> Self {
119 Self {
120 left: x,
121 right: x,
122 top: y,
123 bottom: y,
124 }
125 }
126
127 #[must_use = "constructor returns a new instance"]
129 pub const fn left(value: u16) -> Self {
130 Self {
131 left: value,
132 right: 0,
133 top: 0,
134 bottom: 0,
135 }
136 }
137
138 #[must_use = "constructor returns a new instance"]
140 pub const fn right(value: u16) -> Self {
141 Self {
142 left: 0,
143 right: value,
144 top: 0,
145 bottom: 0,
146 }
147 }
148
149 #[must_use = "constructor returns a new instance"]
151 pub const fn top(value: u16) -> Self {
152 Self {
153 left: 0,
154 right: 0,
155 top: value,
156 bottom: 0,
157 }
158 }
159
160 #[must_use = "constructor returns a new instance"]
162 pub const fn bottom(value: u16) -> Self {
163 Self {
164 left: 0,
165 right: 0,
166 top: 0,
167 bottom: value,
168 }
169 }
170}
171
172impl RenderModifier for Padding {
173 fn modify_area(&self, area: Rect) -> Rect {
174 Rect {
175 x: area.x + self.left,
176 y: area.y + self.top,
177 width: area.width.saturating_sub(self.left + self.right),
178 height: area.height.saturating_sub(self.top + self.bottom),
179 }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 #[test]
188 fn new() {
189 assert_eq!(
190 Padding::new(1, 2, 3, 4),
191 Padding {
192 left: 1,
193 right: 2,
194 top: 3,
195 bottom: 4
196 }
197 );
198 }
199
200 #[test]
201 fn constructors() {
202 assert_eq!(Padding::horizontal(1), Padding::new(1, 1, 0, 0));
203 assert_eq!(Padding::vertical(1), Padding::new(0, 0, 1, 1));
204 assert_eq!(Padding::uniform(1), Padding::new(1, 1, 1, 1));
205 assert_eq!(Padding::proportional(1), Padding::new(2, 2, 1, 1));
206 assert_eq!(Padding::symmetric(1, 2), Padding::new(1, 1, 2, 2));
207 assert_eq!(Padding::left(1), Padding::new(1, 0, 0, 0));
208 assert_eq!(Padding::right(1), Padding::new(0, 1, 0, 0));
209 assert_eq!(Padding::top(1), Padding::new(0, 0, 1, 0));
210 assert_eq!(Padding::bottom(1), Padding::new(0, 0, 0, 1));
211 }
212
213 #[test]
214 const fn can_be_const() {
215 const _PADDING: Padding = Padding::new(1, 1, 1, 1);
216 const _UNI_PADDING: Padding = Padding::uniform(1);
217 const _HORIZONTAL: Padding = Padding::horizontal(1);
218 const _VERTICAL: Padding = Padding::vertical(1);
219 const _PROPORTIONAL: Padding = Padding::proportional(1);
220 const _SYMMETRIC: Padding = Padding::symmetric(1, 1);
221 const _LEFT: Padding = Padding::left(1);
222 const _RIGHT: Padding = Padding::right(1);
223 const _TOP: Padding = Padding::top(1);
224 const _BOTTOM: Padding = Padding::bottom(1);
225 }
226}