leftwm_layouts/geometry/
size.rs

1use serde::{Deserialize, Serialize};
2
3/// Helper enum to represent a size which can be
4/// an absolute pixel value or a relative ratio value
5#[derive(Debug, Clone, PartialEq, Copy, Serialize, Deserialize)]
6#[serde(untagged)]
7pub enum Size {
8    /// Size in pixels (ie. 10 means 10 pixels)
9    Pixel(i32),
10
11    /// Relative size as a ratio between 0 to 1 (ie. 0.5 means 50%)
12    Ratio(f32),
13}
14
15impl Size {
16    /// Turn the size into an absolute value.
17    ///
18    /// A pixel value will be returned as is, a ratio
19    /// value will be multiplied by the provided
20    /// `whole` to calculate the absolute value.
21    ///
22    /// ## Hint
23    /// A negative ratio value will be converted into
24    /// an absolute number before being applied.
25    pub fn into_absolute(self, whole: u32) -> i32 {
26        match self {
27            Size::Pixel(x) => x,
28            Size::Ratio(x) => (whole as f32 * x.abs()).round() as i32,
29        }
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::Size;
36
37    #[test]
38    fn absolute_size_into_absolute_stays_same() {
39        let i = 256i32;
40        let size = Size::Pixel(i);
41        let absolute = size.into_absolute(1000);
42        assert_eq!(absolute, i);
43    }
44
45    #[test]
46    fn relative_size_into_absolute() {
47        let size = Size::Ratio(0.6);
48        let absolute = size.into_absolute(1000);
49        assert_eq!(absolute, 600);
50    }
51
52    #[test]
53    fn relative_size_of_small_whole_is_rounded() {
54        let size = Size::Ratio(0.6);
55        let absolute = size.into_absolute(1);
56        assert_eq!(absolute, 1);
57    }
58
59    #[test]
60    fn relative_size_of_zero_doesnt_panic() {
61        let size = Size::Ratio(0.6);
62        let absolute = size.into_absolute(0);
63        assert_eq!(absolute, 0);
64    }
65
66    #[test]
67    fn negative_relative_size_must_return_same_as_positive() {
68        let whole = 1000;
69        let pos_ratio = Size::Ratio(0.6);
70        let neg_ratio = Size::Ratio(-0.6);
71        let pos_absolute = pos_ratio.into_absolute(whole);
72        let neg_absolute = neg_ratio.into_absolute(whole);
73        assert_eq!(pos_absolute, neg_absolute);
74    }
75
76    #[test]
77    fn relative_size_into_absolute_is_rounded() {
78        let size = Size::Ratio(0.5);
79        let absolute = size.into_absolute(33);
80        assert_eq!(absolute, 17);
81    }
82}