torin/values/
position.rs

1use crate::{
2    prelude::{
3        Area,
4        Point2D,
5        Size2D,
6    },
7    scaled::Scaled,
8};
9
10#[derive(Default, PartialEq, Clone, Debug)]
11pub struct PositionSides {
12    pub top: Option<f32>,
13    pub right: Option<f32>,
14    pub bottom: Option<f32>,
15    pub left: Option<f32>,
16}
17
18#[derive(PartialEq, Clone, Debug)]
19pub enum Position {
20    Stacked(Box<PositionSides>),
21
22    Absolute(Box<PositionSides>),
23    Global(Box<PositionSides>),
24}
25
26impl Default for Position {
27    fn default() -> Self {
28        Self::new_stacked()
29    }
30}
31
32impl Position {
33    pub fn swap_for(&mut self, mut other: Self) {
34        let old_positions = match self {
35            Self::Global(positions) | Self::Absolute(positions) | Self::Stacked(positions) => {
36                positions.clone()
37            }
38        };
39
40        match &mut other {
41            Self::Absolute(_) => {
42                *self = Self::new_absolute();
43            }
44            Self::Global(_) => {
45                *self = Self::new_global();
46            }
47            Self::Stacked(_) => {
48                *self = Self::new_stacked();
49            }
50        };
51
52        match self {
53            Self::Absolute(positions) | Self::Global(positions) | Self::Stacked(positions) => {
54                *positions = old_positions;
55            }
56        };
57    }
58
59    pub fn new_absolute() -> Self {
60        Self::Absolute(Box::new(PositionSides {
61            top: None,
62            right: None,
63            bottom: None,
64            left: None,
65        }))
66    }
67
68    pub fn new_global() -> Self {
69        Self::Global(Box::new(PositionSides {
70            top: None,
71            right: None,
72            bottom: None,
73            left: None,
74        }))
75    }
76
77    pub fn new_stacked() -> Self {
78        Self::Stacked(Box::new(PositionSides {
79            top: None,
80            right: None,
81            bottom: None,
82            left: None,
83        }))
84    }
85
86    pub fn is_stacked(&self) -> bool {
87        matches!(self, Self::Stacked { .. })
88    }
89
90    pub fn is_absolute(&self) -> bool {
91        matches!(self, Self::Absolute { .. })
92    }
93
94    pub fn is_global(&self) -> bool {
95        matches!(self, Self::Global { .. })
96    }
97
98    pub fn set_top(&mut self, value: f32) {
99        match self {
100            Self::Absolute(position) | Self::Global(position) | Self::Stacked(position) => {
101                position.top = Some(value);
102            }
103        }
104    }
105
106    pub fn set_right(&mut self, value: f32) {
107        match self {
108            Self::Absolute(position) | Self::Global(position) | Self::Stacked(position) => {
109                position.right = Some(value);
110            }
111        }
112    }
113
114    pub fn set_bottom(&mut self, value: f32) {
115        match self {
116            Self::Absolute(position) | Self::Global(position) | Self::Stacked(position) => {
117                position.bottom = Some(value);
118            }
119        }
120    }
121
122    pub fn set_left(&mut self, value: f32) {
123        match self {
124            Self::Absolute(position) | Self::Global(position) | Self::Stacked(position) => {
125                position.left = Some(value);
126            }
127        }
128    }
129
130    pub fn get_origin(
131        &self,
132        available_parent_area: &Area,
133        parent_area: &Area,
134        area_size: &Size2D,
135        root_area: &Area,
136    ) -> Point2D {
137        match self {
138            Self::Stacked(_) => available_parent_area.origin,
139            Self::Absolute(absolute_position) => {
140                let PositionSides {
141                    top,
142                    right,
143                    bottom,
144                    left,
145                } = &**absolute_position;
146                let y = {
147                    let mut y = parent_area.min_y();
148                    if let Some(top) = top {
149                        y += top;
150                    } else if let Some(bottom) = bottom {
151                        y = parent_area.max_y() - bottom - area_size.height;
152                    }
153                    y
154                };
155                let x = {
156                    let mut x = parent_area.min_x();
157                    if let Some(left) = left {
158                        x += left;
159                    } else if let Some(right) = right {
160                        x = parent_area.max_x() - right - area_size.width;
161                    }
162                    x
163                };
164                Point2D::new(x, y)
165            }
166            Self::Global(global_position) => {
167                let PositionSides {
168                    top,
169                    right,
170                    bottom,
171                    left,
172                } = &**global_position;
173                let y = {
174                    let mut y = 0.;
175                    if let Some(top) = top {
176                        y = *top;
177                    } else if let Some(bottom) = bottom {
178                        y = root_area.max_y() - bottom - area_size.height;
179                    }
180                    y
181                };
182                let x = {
183                    let mut x = 0.;
184                    if let Some(left) = left {
185                        x = *left;
186                    } else if let Some(right) = right {
187                        x = root_area.max_x() - right - area_size.width;
188                    }
189                    x
190                };
191                Point2D::new(x, y)
192            }
193        }
194    }
195}
196
197impl Scaled for Position {
198    fn scale(&mut self, scale_factor: f32) {
199        match self {
200            Self::Absolute(position) | Self::Global(position) => {
201                if let Some(top) = &mut position.top {
202                    *top *= scale_factor;
203                }
204                if let Some(right) = &mut position.right {
205                    *right *= scale_factor;
206                }
207                if let Some(bottom) = &mut position.bottom {
208                    *bottom *= scale_factor;
209                }
210                if let Some(left) = &mut position.left {
211                    *left *= scale_factor;
212                }
213            }
214            Self::Stacked(_) => {}
215        }
216    }
217}
218
219impl Position {
220    pub fn pretty(&self) -> String {
221        match self {
222            Self::Stacked(_) => "stacked".to_string(),
223            Self::Absolute(positions) | Self::Global(positions) => format!(
224                "{}, {}, {}, {}",
225                positions.top.unwrap_or_default(),
226                positions.right.unwrap_or_default(),
227                positions.bottom.unwrap_or_default(),
228                positions.left.unwrap_or_default()
229            ),
230        }
231    }
232}