1use crate::lengths::{LogicalPoint, LogicalRect, LogicalSize};
9
10pub enum Placement {
12 Fixed(LogicalRect),
14}
15
16pub fn place_popup(placement: Placement, clip_region: &Option<LogicalRect>) -> LogicalRect {
20 match placement {
21 Placement::Fixed(rect) => {
22 let clip = clip_region.unwrap_or(rect);
23 if clip.contains_rect(&rect) {
24 rect
25 } else {
26 let size = LogicalSize::new(
27 crate::Coord::min(rect.size.width, clip.size.width),
28 crate::Coord::min(rect.size.height, clip.size.height),
29 );
30 let origin = LogicalPoint::new(
31 rect.origin
32 .x
33 .clamp(clip.origin.x, clip.origin.x + clip.size.width - size.width),
34 rect.origin
35 .y
36 .clamp(clip.origin.y, clip.origin.y + clip.size.height - size.height),
37 );
38 LogicalRect::new(origin, size)
39 }
40 }
41 }
42}
43
44#[cfg(test)]
45fn r(x: i32, y: i32, w: i32, h: i32) -> LogicalRect {
46 LogicalRect::new(LogicalPoint::new(x as f32, y as f32), LogicalSize::new(w as f32, h as f32))
47}
48
49#[cfg(test)]
50#[track_caller]
51fn fixed_placement(input: LogicalRect, expected: LogicalRect, clip: Option<LogicalRect>) {
52 std::eprintln!("fixed: {input:?}, clip({clip:?}) => {expected:?}");
53 let result = place_popup(Placement::Fixed(input), &clip);
54 if let Some(clip) = clip {
55 clip.contains_rect(&result);
56 }
57 assert_eq!(result, expected);
58}
59
60#[test]
61fn test_place_popup_fixed_unclipped() {
62 let data = r(5, 5, 100, 100);
63 fixed_placement(data, data, None);
64
65 let data = r(5, -20, 100, 100);
66 fixed_placement(data, data, None);
67 let data = r(2000, -20, 100, 100);
68 fixed_placement(data, data, None);
69 let data = r(2000, 5, 100, 100);
70 fixed_placement(data, data, None);
71 let data = r(2000, 2000, 100, 100);
72 fixed_placement(data, data, None);
73 let data = r(5, 2000, 100, 100);
74 fixed_placement(data, data, None);
75 let data = r(-20, 2000, 100, 100);
76 fixed_placement(data, data, None);
77 let data = r(-20, 5, 100, 100);
78 fixed_placement(data, data, None);
79 let data = r(-20, -20, 100, 100);
80 fixed_placement(data, data, None);
81
82 let data = r(-20, -20, 2000, 2000);
83 fixed_placement(data, data, None);
84}
85
86#[test]
87fn test_place_popup_fixed_clipped() {
88 for (clip_offset_x, clip_offset_y) in [
89 (-200, -200),
90 (-200, 0),
91 (-200, 200),
92 (0, -200),
93 (0, 0),
94 (0, 200),
95 (200, -200),
96 (200, 0),
97 (200, 200),
98 ] {
99 for (clip_width, clip_height) in [(110, 110), (800, 600)] {
100 let clip = r(clip_offset_x, clip_offset_y, clip_width, clip_height);
101
102 let x_w = clip_offset_x - 10;
103 let x_c = clip_offset_x + 5;
104 let x_e = clip_offset_x + clip_width - 80;
105
106 let y_n = clip_offset_y - 10;
107 let y_c = clip_offset_y + 5;
108 let y_s = clip_offset_y + clip_height - 80;
109
110 let x_min = clip_offset_x;
111 let x_max = clip_offset_x + clip_width;
112 let y_min = clip_offset_y;
113 let y_max = clip_offset_y + clip_height;
114
115 assert!(clip_width > 105 && clip_width < 1000);
116 assert!(clip_height > 105 && clip_height < 1000);
117
118 fixed_placement(r(x_c, y_c, 100, 100), r(x_c, y_c, 100, 100), Some(clip));
120
121 fixed_placement(r(x_c, y_n, 100, 100), r(x_c, y_min, 100, 100), Some(clip));
123 fixed_placement(r(x_e, y_n, 100, 100), r(x_max - 100, y_min, 100, 100), Some(clip));
124 fixed_placement(r(x_e, y_c, 100, 100), r(x_max - 100, y_c, 100, 100), Some(clip));
125 fixed_placement(
126 r(x_e, y_s, 100, 100),
127 r(x_max - 100, y_max - 100, 100, 100),
128 Some(clip),
129 );
130 fixed_placement(r(x_c, y_s, 100, 100), r(x_c, y_max - 100, 100, 100), Some(clip));
131 fixed_placement(r(x_c, y_s, 100, 100), r(x_c, y_max - 100, 100, 100), Some(clip));
132 fixed_placement(r(x_w, y_s, 100, 100), r(x_min, y_max - 100, 100, 100), Some(clip));
133 fixed_placement(r(x_w, y_c, 100, 100), r(x_min, y_c, 100, 100), Some(clip));
134 fixed_placement(r(x_w, y_n, 100, 100), r(x_min, y_min, 100, 100), Some(clip));
135
136 fixed_placement(r(x_c, -2000, 100, 100), r(x_c, y_min, 100, 100), Some(clip));
138 fixed_placement(r(2000, -2000, 100, 100), r(x_max - 100, y_min, 100, 100), Some(clip));
139 fixed_placement(r(2000, y_c, 100, 100), r(x_max - 100, y_c, 100, 100), Some(clip));
140 fixed_placement(
141 r(2000, 2000, 100, 100),
142 r(x_max - 100, y_max - 100, 100, 100),
143 Some(clip),
144 );
145 fixed_placement(r(x_c, 2000, 100, 100), r(x_c, y_max - 100, 100, 100), Some(clip));
146 fixed_placement(r(-2000, 2000, 100, 100), r(x_min, y_max - 100, 100, 100), Some(clip));
147 fixed_placement(r(-2000, y_c, 100, 100), r(x_min, y_c, 100, 100), Some(clip));
148 fixed_placement(r(-2000, -2000, 100, 100), r(x_min, y_min, 100, 100), Some(clip));
149
150 fixed_placement(
152 r(x_min, y_min, clip_width, clip_height),
153 r(x_min, y_min, clip_width, clip_height),
154 Some(clip),
155 );
156
157 fixed_placement(
159 r(x_c, y_c, clip_width, clip_height),
160 r(x_min, y_min, clip_width, clip_height),
161 Some(clip),
162 );
163 fixed_placement(
164 r(x_c, y_n, clip_width, clip_height),
165 r(x_min, y_min, clip_width, clip_height),
166 Some(clip),
167 );
168
169 fixed_placement(
170 r(x_e, y_n, clip_width, clip_height),
171 r(x_min, y_min, clip_width, clip_height),
172 Some(clip),
173 );
174 fixed_placement(
175 r(x_e, y_c, clip_width, clip_height),
176 r(x_min, y_min, clip_width, clip_height),
177 Some(clip),
178 );
179 fixed_placement(
180 r(x_e, y_s, clip_width, clip_height),
181 r(x_min, y_min, clip_width, clip_height),
182 Some(clip),
183 );
184 fixed_placement(
185 r(x_c, y_s, clip_width, clip_height),
186 r(x_min, y_min, clip_width, clip_height),
187 Some(clip),
188 );
189 fixed_placement(
190 r(x_w, y_s, clip_width, clip_height),
191 r(x_min, y_min, clip_width, clip_height),
192 Some(clip),
193 );
194 fixed_placement(
195 r(x_w, y_c, clip_width, clip_height),
196 r(x_min, y_min, clip_width, clip_height),
197 Some(clip),
198 );
199 fixed_placement(
200 r(x_w, y_n, clip_width, clip_height),
201 r(x_min, y_min, clip_width, clip_height),
202 Some(clip),
203 );
204
205 fixed_placement(
207 r(x_c, y_c, clip_width + 5, clip_height + 5),
208 r(x_min, y_min, clip_width, clip_height),
209 Some(clip),
210 );
211 fixed_placement(
212 r(x_c, y_n, clip_width + 5, clip_height + 5),
213 r(x_min, y_min, clip_width, clip_height),
214 Some(clip),
215 );
216 fixed_placement(
217 r(x_e, y_n, clip_width + 5, clip_height + 5),
218 r(x_min, y_min, clip_width, clip_height),
219 Some(clip),
220 );
221 fixed_placement(
222 r(x_e, y_c, clip_width + 5, clip_height + 5),
223 r(x_min, y_min, clip_width, clip_height),
224 Some(clip),
225 );
226 fixed_placement(
227 r(x_e, y_s, clip_width + 5, clip_height + 5),
228 r(x_min, y_min, clip_width, clip_height),
229 Some(clip),
230 );
231 fixed_placement(
232 r(x_c, y_s, clip_width + 5, clip_height + 5),
233 r(x_min, y_min, clip_width, clip_height),
234 Some(clip),
235 );
236 fixed_placement(
237 r(x_w, y_s, clip_width + 5, clip_height + 5),
238 r(x_min, y_min, clip_width, clip_height),
239 Some(clip),
240 );
241 fixed_placement(
242 r(x_w, y_c, clip_width + 5, clip_height + 5),
243 r(x_min, y_min, clip_width, clip_height),
244 Some(clip),
245 );
246 fixed_placement(
247 r(x_w, y_n, clip_width + 5, clip_height + 5),
248 r(x_min, y_min, clip_width, clip_height),
249 Some(clip),
250 );
251
252 fixed_placement(
254 r(x_c, -3000, clip_width + 5, clip_height + 5),
255 r(x_min, y_min, clip_width, clip_height),
256 Some(clip),
257 );
258 fixed_placement(
259 r(3000, -3000, clip_width + 5, clip_height + 5),
260 r(x_min, y_min, clip_width, clip_height),
261 Some(clip),
262 );
263 fixed_placement(
264 r(3000, y_c, clip_width + 5, clip_height + 5),
265 r(x_min, y_min, clip_width, clip_height),
266 Some(clip),
267 );
268 fixed_placement(
269 r(3000, 3000, clip_width + 5, clip_height + 5),
270 r(x_min, y_min, clip_width, clip_height),
271 Some(clip),
272 );
273 fixed_placement(
274 r(x_c, 3000, clip_width + 5, clip_height + 5),
275 r(x_min, y_min, clip_width, clip_height),
276 Some(clip),
277 );
278 fixed_placement(
279 r(-3000, 3000, clip_width + 5, clip_height + 5),
280 r(x_min, y_min, clip_width, clip_height),
281 Some(clip),
282 );
283 fixed_placement(
284 r(-3000, y_c, clip_width + 5, clip_height + 5),
285 r(x_min, y_min, clip_width, clip_height),
286 Some(clip),
287 );
288 fixed_placement(
289 r(-3000, -3000, clip_width + 5, clip_height + 5),
290 r(x_min, y_min, clip_width, clip_height),
291 Some(clip),
292 );
293 }
294 }
295}