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