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}