1use crate::core::Rectangle;
2
3#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
5pub enum Axis {
6 Horizontal,
8 Vertical,
10}
11
12impl Axis {
13 pub fn split(
16 &self,
17 rectangle: &Rectangle,
18 ratio: f32,
19 spacing: f32,
20 min_size_a: f32,
21 min_size_b: f32,
22 ) -> (Rectangle, Rectangle, f32) {
23 match self {
24 Axis::Horizontal => {
25 let height_top = (rectangle.height * ratio - spacing / 2.0)
26 .round()
27 .max(min_size_a)
28 .min(rectangle.height - min_size_b - spacing);
29
30 let height_bottom =
31 (rectangle.height - height_top - spacing).max(min_size_b);
32
33 let ratio = (height_top + spacing / 2.0) / rectangle.height;
34
35 (
36 Rectangle {
37 height: height_top,
38 ..*rectangle
39 },
40 Rectangle {
41 y: rectangle.y + height_top + spacing,
42 height: height_bottom,
43 ..*rectangle
44 },
45 ratio,
46 )
47 }
48 Axis::Vertical => {
49 let width_left = (rectangle.width * ratio - spacing / 2.0)
50 .round()
51 .max(min_size_a)
52 .min(rectangle.width - min_size_b - spacing);
53
54 let width_right =
55 (rectangle.width - width_left - spacing).max(min_size_b);
56
57 let ratio = (width_left + spacing / 2.0) / rectangle.width;
58
59 (
60 Rectangle {
61 width: width_left,
62 ..*rectangle
63 },
64 Rectangle {
65 x: rectangle.x + width_left + spacing,
66 width: width_right,
67 ..*rectangle
68 },
69 ratio,
70 )
71 }
72 }
73 }
74
75 pub fn split_line_bounds(
77 &self,
78 rectangle: Rectangle,
79 ratio: f32,
80 spacing: f32,
81 ) -> Rectangle {
82 match self {
83 Axis::Horizontal => Rectangle {
84 x: rectangle.x,
85 y: (rectangle.y + rectangle.height * ratio - spacing / 2.0)
86 .round(),
87 width: rectangle.width,
88 height: spacing,
89 },
90 Axis::Vertical => Rectangle {
91 x: (rectangle.x + rectangle.width * ratio - spacing / 2.0)
92 .round(),
93 y: rectangle.y,
94 width: spacing,
95 height: rectangle.height,
96 },
97 }
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 enum Case {
106 Horizontal {
107 overall_height: f32,
108 spacing: f32,
109 top_height: f32,
110 bottom_y: f32,
111 bottom_height: f32,
112 },
113 Vertical {
114 overall_width: f32,
115 spacing: f32,
116 left_width: f32,
117 right_x: f32,
118 right_width: f32,
119 },
120 }
121
122 #[test]
123 fn split() {
124 let cases = vec![
125 Case::Horizontal {
127 overall_height: 10.0,
128 spacing: 2.0,
129 top_height: 4.0,
130 bottom_y: 6.0,
131 bottom_height: 4.0,
132 },
133 Case::Horizontal {
135 overall_height: 9.0,
136 spacing: 2.0,
137 top_height: 4.0,
138 bottom_y: 6.0,
139 bottom_height: 3.0,
140 },
141 Case::Horizontal {
143 overall_height: 10.0,
144 spacing: 1.0,
145 top_height: 5.0,
146 bottom_y: 6.0,
147 bottom_height: 4.0,
148 },
149 Case::Horizontal {
151 overall_height: 9.0,
152 spacing: 1.0,
153 top_height: 4.0,
154 bottom_y: 5.0,
155 bottom_height: 4.0,
156 },
157 Case::Vertical {
159 overall_width: 10.0,
160 spacing: 2.0,
161 left_width: 4.0,
162 right_x: 6.0,
163 right_width: 4.0,
164 },
165 Case::Vertical {
167 overall_width: 9.0,
168 spacing: 2.0,
169 left_width: 4.0,
170 right_x: 6.0,
171 right_width: 3.0,
172 },
173 Case::Vertical {
175 overall_width: 10.0,
176 spacing: 1.0,
177 left_width: 5.0,
178 right_x: 6.0,
179 right_width: 4.0,
180 },
181 Case::Vertical {
183 overall_width: 9.0,
184 spacing: 1.0,
185 left_width: 4.0,
186 right_x: 5.0,
187 right_width: 4.0,
188 },
189 ];
190 for case in cases {
191 match case {
192 Case::Horizontal {
193 overall_height,
194 spacing,
195 top_height,
196 bottom_y,
197 bottom_height,
198 } => {
199 let a = Axis::Horizontal;
200 let r = Rectangle {
201 x: 0.0,
202 y: 0.0,
203 width: 10.0,
204 height: overall_height,
205 };
206 let (top, bottom, _ratio) =
207 a.split(&r, 0.5, spacing, 0.0, 0.0);
208 assert_eq!(
209 top,
210 Rectangle {
211 height: top_height,
212 ..r
213 }
214 );
215 assert_eq!(
216 bottom,
217 Rectangle {
218 y: bottom_y,
219 height: bottom_height,
220 ..r
221 }
222 );
223 }
224 Case::Vertical {
225 overall_width,
226 spacing,
227 left_width,
228 right_x,
229 right_width,
230 } => {
231 let a = Axis::Vertical;
232 let r = Rectangle {
233 x: 0.0,
234 y: 0.0,
235 width: overall_width,
236 height: 10.0,
237 };
238 let (left, right, _ratio) =
239 a.split(&r, 0.5, spacing, 0.0, 0.0);
240 assert_eq!(
241 left,
242 Rectangle {
243 width: left_width,
244 ..r
245 }
246 );
247 assert_eq!(
248 right,
249 Rectangle {
250 x: right_x,
251 width: right_width,
252 ..r
253 }
254 );
255 }
256 }
257 }
258 }
259}