ratatui_widgets/block/
padding.rs

1/// Defines the padding for a [`Block`].
2///
3/// See the [`padding`] method of [`Block`] to configure its padding.
4///
5/// This concept is similar to [CSS padding].
6///
7/// **NOTE**: Terminal cells are often taller than they are wide, so to make horizontal and vertical
8/// padding seem equal, doubling the horizontal padding is usually pretty good.
9///
10/// # Example
11///
12/// ```
13/// use ratatui::widgets::Padding;
14///
15/// Padding::uniform(1);
16/// Padding::horizontal(2);
17/// Padding::left(3);
18/// Padding::proportional(4);
19/// Padding::symmetric(5, 6);
20/// ```
21///
22/// [`Block`]: crate::block::Block
23/// [`padding`]: crate::block::Block::padding
24/// [CSS padding]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
25#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub struct Padding {
28    /// Left padding
29    pub left: u16,
30    /// Right padding
31    pub right: u16,
32    /// Top padding
33    pub top: u16,
34    /// Bottom padding
35    pub bottom: u16,
36}
37
38impl Padding {
39    /// `Padding` with all fields set to `0`
40    pub const ZERO: Self = Self {
41        left: 0,
42        right: 0,
43        top: 0,
44        bottom: 0,
45    };
46
47    /// Creates a new `Padding` by specifying every field individually.
48    ///
49    /// Note: the order of the fields does not match the order of the CSS properties.
50    pub const fn new(left: u16, right: u16, top: u16, bottom: u16) -> Self {
51        Self {
52            left,
53            right,
54            top,
55            bottom,
56        }
57    }
58
59    /// Creates a `Padding` with all fields set to `0`.
60    #[deprecated = "use `Padding::ZERO` instead"]
61    pub const fn zero() -> Self {
62        Self::ZERO
63    }
64
65    /// Creates a `Padding` with the same value for `left` and `right`.
66    pub const fn horizontal(value: u16) -> Self {
67        Self {
68            left: value,
69            right: value,
70            top: 0,
71            bottom: 0,
72        }
73    }
74
75    /// Creates a `Padding` with the same value for `top` and `bottom`.
76    pub const fn vertical(value: u16) -> Self {
77        Self {
78            left: 0,
79            right: 0,
80            top: value,
81            bottom: value,
82        }
83    }
84
85    /// Creates a `Padding` with the same value for all fields.
86    pub const fn uniform(value: u16) -> Self {
87        Self {
88            left: value,
89            right: value,
90            top: value,
91            bottom: value,
92        }
93    }
94
95    /// Creates a `Padding` that is visually proportional to the terminal.
96    ///
97    /// This represents a padding of 2x the value for `left` and `right` and 1x the value for
98    /// `top` and `bottom`.
99    pub const fn proportional(value: u16) -> Self {
100        Self {
101            left: 2 * value,
102            right: 2 * value,
103            top: value,
104            bottom: value,
105        }
106    }
107
108    /// Creates a `Padding` that is symmetric.
109    ///
110    /// The `x` value is used for `left` and `right` and the `y` value is used for `top` and
111    /// `bottom`.
112    pub const fn symmetric(x: u16, y: u16) -> Self {
113        Self {
114            left: x,
115            right: x,
116            top: y,
117            bottom: y,
118        }
119    }
120
121    /// Creates a `Padding` that only sets the `left` padding.
122    pub const fn left(value: u16) -> Self {
123        Self {
124            left: value,
125            right: 0,
126            top: 0,
127            bottom: 0,
128        }
129    }
130
131    /// Creates a `Padding` that only sets the `right` padding.
132    pub const fn right(value: u16) -> Self {
133        Self {
134            left: 0,
135            right: value,
136            top: 0,
137            bottom: 0,
138        }
139    }
140
141    /// Creates a `Padding` that only sets the `top` padding.
142    pub const fn top(value: u16) -> Self {
143        Self {
144            left: 0,
145            right: 0,
146            top: value,
147            bottom: 0,
148        }
149    }
150
151    /// Creates a `Padding` that only sets the `bottom` padding.
152    pub const fn bottom(value: u16) -> Self {
153        Self {
154            left: 0,
155            right: 0,
156            top: 0,
157            bottom: value,
158        }
159    }
160}
161
162#[cfg(test)]
163mod tests {
164    use super::*;
165
166    #[test]
167    fn new() {
168        assert_eq!(
169            Padding::new(1, 2, 3, 4),
170            Padding {
171                left: 1,
172                right: 2,
173                top: 3,
174                bottom: 4
175            }
176        );
177    }
178
179    #[test]
180    fn constructors() {
181        assert_eq!(Padding::horizontal(1), Padding::new(1, 1, 0, 0));
182        assert_eq!(Padding::vertical(1), Padding::new(0, 0, 1, 1));
183        assert_eq!(Padding::uniform(1), Padding::new(1, 1, 1, 1));
184        assert_eq!(Padding::proportional(1), Padding::new(2, 2, 1, 1));
185        assert_eq!(Padding::symmetric(1, 2), Padding::new(1, 1, 2, 2));
186        assert_eq!(Padding::left(1), Padding::new(1, 0, 0, 0));
187        assert_eq!(Padding::right(1), Padding::new(0, 1, 0, 0));
188        assert_eq!(Padding::top(1), Padding::new(0, 0, 1, 0));
189        assert_eq!(Padding::bottom(1), Padding::new(0, 0, 0, 1));
190    }
191
192    #[test]
193    const fn can_be_const() {
194        const _PADDING: Padding = Padding::new(1, 1, 1, 1);
195        const _UNI_PADDING: Padding = Padding::uniform(1);
196        const _HORIZONTAL: Padding = Padding::horizontal(1);
197        const _VERTICAL: Padding = Padding::vertical(1);
198        const _PROPORTIONAL: Padding = Padding::proportional(1);
199        const _SYMMETRIC: Padding = Padding::symmetric(1, 1);
200        const _LEFT: Padding = Padding::left(1);
201        const _RIGHT: Padding = Padding::right(1);
202        const _TOP: Padding = Padding::top(1);
203        const _BOTTOM: Padding = Padding::bottom(1);
204    }
205}