1use crate::draw_ctx::DrawCtx;
4use crate::event::{Event, EventResult};
5use crate::geometry::{Rect, Size};
6use crate::layout_props::{resolve_fit_or_stretch, HAnchor, Insets, VAnchor, WidgetBase};
7use crate::widget::Widget;
8
9pub struct Stack {
27 bounds: Rect,
28 children: Vec<Box<dyn Widget>>,
29 aligned: Vec<bool>,
32 base: WidgetBase,
33}
34
35impl Stack {
36 pub fn new() -> Self {
37 Self {
38 bounds: Rect::default(),
39 children: Vec::new(),
40 aligned: Vec::new(),
41 base: WidgetBase::new(),
42 }
43 }
44
45 pub fn add(mut self, child: Box<dyn Widget>) -> Self {
47 self.children.push(child);
48 self.aligned.push(false);
49 self
50 }
51
52 pub fn add_aligned(mut self, child: Box<dyn Widget>) -> Self {
56 self.children.push(child);
57 self.aligned.push(true);
58 self
59 }
60
61 pub fn with_margin(mut self, m: Insets) -> Self {
62 self.base.margin = m;
63 self
64 }
65 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
66 self.base.h_anchor = h;
67 self
68 }
69 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
70 self.base.v_anchor = v;
71 self
72 }
73 pub fn with_min_size(mut self, s: Size) -> Self {
74 self.base.min_size = s;
75 self
76 }
77 pub fn with_max_size(mut self, s: Size) -> Self {
78 self.base.max_size = s;
79 self
80 }
81}
82
83impl Default for Stack {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl Widget for Stack {
90 fn type_name(&self) -> &'static str {
91 "Stack"
92 }
93 fn bounds(&self) -> Rect {
94 self.bounds
95 }
96 fn set_bounds(&mut self, b: Rect) {
97 self.bounds = b;
98 }
99 fn children(&self) -> &[Box<dyn Widget>] {
100 &self.children
101 }
102 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
103 &mut self.children
104 }
105
106 fn margin(&self) -> Insets {
107 self.base.margin
108 }
109 fn widget_base(&self) -> Option<&WidgetBase> {
110 Some(&self.base)
111 }
112 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
113 Some(&mut self.base)
114 }
115 fn h_anchor(&self) -> HAnchor {
116 self.base.h_anchor
117 }
118 fn v_anchor(&self) -> VAnchor {
119 self.base.v_anchor
120 }
121 fn min_size(&self) -> Size {
122 self.base.min_size
123 }
124 fn max_size(&self) -> Size {
125 self.base.max_size
126 }
127
128 fn layout(&mut self, available: Size) -> Size {
129 for idx in 0..self.children.len() {
130 if self.aligned.get(idx).copied().unwrap_or(false) {
131 let child = &mut self.children[idx];
132 let desired = child.layout(available);
136 let m = child.margin();
139 let slot_w = (available.width - m.left - m.right).max(0.0);
143 let slot_h = (available.height - m.top - m.bottom).max(0.0);
144 let w = desired
145 .width
146 .clamp(child.min_size().width, child.max_size().width)
147 .min(slot_w);
148 let h = desired
149 .height
150 .clamp(child.min_size().height, child.max_size().height)
151 .min(slot_h);
152 child.layout(Size::new(w, h));
153
154 let ha = child.h_anchor();
155 let x = if ha.contains(HAnchor::RIGHT) && !ha.contains(HAnchor::LEFT) {
156 (available.width - m.right - w).max(0.0)
157 } else if ha.contains(HAnchor::CENTER) && !ha.is_stretch() {
158 m.left + (available.width - m.left - m.right - w) * 0.5
159 } else {
160 m.left
161 };
162
163 let va = child.v_anchor();
165 let y = if va.contains(VAnchor::TOP) && !va.contains(VAnchor::BOTTOM) {
166 (available.height - m.top - h).max(0.0)
167 } else if va.contains(VAnchor::CENTER) && !va.is_stretch() {
168 m.bottom + (available.height - m.bottom - m.top - h) * 0.5
169 } else {
170 m.bottom
171 };
172
173 child.set_bounds(Rect::new(x, y, w, h));
174 } else {
175 let child = &mut self.children[idx];
176 child.layout(available);
177 child.set_bounds(Rect::new(0.0, 0.0, available.width, available.height));
178 }
179 }
180
181 let mut i = 0;
200 let mut raised: Vec<(Box<dyn Widget>, bool)> = Vec::new();
201 while i < self.children.len() {
202 if self.children[i].take_raise_request() {
203 let child = self.children.remove(i);
204 let aligned = if i < self.aligned.len() {
212 self.aligned.remove(i)
213 } else {
214 false
215 };
216 raised.push((child, aligned));
217 } else {
219 i += 1;
220 }
221 }
222 for (r, a) in raised {
223 self.children.push(r);
224 self.aligned.push(a);
225 }
226
227 available
228 }
229
230 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
231
232 fn on_event(&mut self, _: &Event) -> EventResult {
233 EventResult::Ignored
234 }
235}
236
237pub struct Padding {
243 bounds: Rect,
244 children: Vec<Box<dyn Widget>>,
245 base: WidgetBase,
246 insets: Insets,
247}
248
249impl Padding {
250 pub fn new(insets: Insets, child: Box<dyn Widget>) -> Self {
252 Self {
253 bounds: Rect::default(),
254 children: vec![child],
255 base: WidgetBase::new(),
256 insets,
257 }
258 }
259
260 pub fn uniform(amount: f64, child: Box<dyn Widget>) -> Self {
262 Self::new(Insets::all(amount), child)
263 }
264
265 pub fn with_margin(mut self, m: Insets) -> Self {
266 self.base.margin = m;
267 self
268 }
269 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
270 self.base.h_anchor = h;
271 self
272 }
273 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
274 self.base.v_anchor = v;
275 self
276 }
277 pub fn with_min_size(mut self, s: Size) -> Self {
278 self.base.min_size = s;
279 self
280 }
281 pub fn with_max_size(mut self, s: Size) -> Self {
282 self.base.max_size = s;
283 self
284 }
285}
286
287impl Widget for Padding {
288 fn type_name(&self) -> &'static str {
289 "Padding"
290 }
291 fn bounds(&self) -> Rect {
292 self.bounds
293 }
294 fn set_bounds(&mut self, b: Rect) {
295 self.bounds = b;
296 }
297 fn children(&self) -> &[Box<dyn Widget>] {
298 &self.children
299 }
300 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
301 &mut self.children
302 }
303
304 fn margin(&self) -> Insets {
305 self.base.margin
306 }
307 fn widget_base(&self) -> Option<&WidgetBase> {
308 Some(&self.base)
309 }
310 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
311 Some(&mut self.base)
312 }
313 fn h_anchor(&self) -> HAnchor {
314 self.base.h_anchor
315 }
316 fn v_anchor(&self) -> VAnchor {
317 self.base.v_anchor
318 }
319 fn min_size(&self) -> Size {
320 self.base.min_size
321 }
322 fn max_size(&self) -> Size {
323 self.base.max_size
324 }
325
326 fn layout(&mut self, available: Size) -> Size {
327 let p = &self.insets;
328 let inner = Size::new(
329 (available.width - p.left - p.right).max(0.0),
330 (available.height - p.top - p.bottom).max(0.0),
331 );
332 if let Some(child) = self.children.first_mut() {
333 let desired = child.layout(inner);
334 child.set_bounds(Rect::new(p.left, p.bottom, desired.width, desired.height));
336 }
337 let content_w = self.children.first().map_or(0.0, |c| c.bounds().width);
339 let content_h = self.children.first().map_or(0.0, |c| c.bounds().height);
340 Size::new(content_w + p.left + p.right, content_h + p.top + p.bottom)
341 }
342
343 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
344
345 fn on_event(&mut self, _: &Event) -> EventResult {
346 EventResult::Ignored
347 }
348}
349
350pub struct SizedBox {
360 bounds: Rect,
361 children: Vec<Box<dyn Widget>>,
362 base: WidgetBase,
363 pub width: Option<f64>,
364 pub height: Option<f64>,
365}
366
367impl SizedBox {
368 pub fn new() -> Self {
369 Self {
370 bounds: Rect::default(),
371 children: Vec::new(),
372 base: WidgetBase::new(),
373 width: None,
374 height: None,
375 }
376 }
377
378 pub fn with_width(mut self, w: f64) -> Self {
379 self.width = Some(w);
380 self
381 }
382 pub fn with_height(mut self, h: f64) -> Self {
383 self.height = Some(h);
384 self
385 }
386
387 pub fn with_child(mut self, child: Box<dyn Widget>) -> Self {
388 self.children.clear();
389 self.children.push(child);
390 self
391 }
392
393 pub fn fixed(width: f64, height: f64) -> Self {
395 Self::new().with_width(width).with_height(height)
396 }
397
398 pub fn with_margin(mut self, m: Insets) -> Self {
399 self.base.margin = m;
400 self
401 }
402 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
403 self.base.h_anchor = h;
404 self
405 }
406 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
407 self.base.v_anchor = v;
408 self
409 }
410 pub fn with_min_size(mut self, s: Size) -> Self {
411 self.base.min_size = s;
412 self
413 }
414 pub fn with_max_size(mut self, s: Size) -> Self {
415 self.base.max_size = s;
416 self
417 }
418}
419
420impl Default for SizedBox {
421 fn default() -> Self {
422 Self::new()
423 }
424}
425
426impl Widget for SizedBox {
427 fn type_name(&self) -> &'static str {
428 "SizedBox"
429 }
430 fn bounds(&self) -> Rect {
431 self.bounds
432 }
433 fn set_bounds(&mut self, b: Rect) {
434 self.bounds = b;
435 }
436 fn children(&self) -> &[Box<dyn Widget>] {
437 &self.children
438 }
439 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
440 &mut self.children
441 }
442
443 fn margin(&self) -> Insets {
444 self.base.margin
445 }
446 fn widget_base(&self) -> Option<&WidgetBase> {
447 Some(&self.base)
448 }
449 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
450 Some(&mut self.base)
451 }
452 fn h_anchor(&self) -> HAnchor {
453 self.base.h_anchor
454 }
455 fn v_anchor(&self) -> VAnchor {
456 self.base.v_anchor
457 }
458 fn min_size(&self) -> Size {
459 self.base.min_size
460 }
461 fn max_size(&self) -> Size {
462 self.base.max_size
463 }
464
465 fn measure_min_height(&self, available_w: f64) -> f64 {
472 if let Some(h) = self.height {
473 return h;
474 }
475 if let Some(child) = self.children.first() {
476 let m = child.margin();
477 let w = self.width.unwrap_or(available_w);
478 let slot_w = (w - m.left - m.right).max(0.0);
479 return (child.measure_min_height(slot_w) + m.vertical())
480 .clamp(self.base.min_size.height, self.base.max_size.height);
481 }
482 self.base.min_size.height
483 }
484
485 fn layout(&mut self, available: Size) -> Size {
486 let w = self.width.unwrap_or(available.width);
497 let mut h = self.height.unwrap_or_else(|| {
498 if self.children.is_empty() {
499 0.0
500 } else {
501 available.height
502 }
503 });
504
505 if let Some(child) = self.children.first_mut() {
506 let m = child.margin();
507 let slot_w = (w - m.left - m.right).max(0.0);
508 let slot_h = (h - m.top - m.bottom).max(0.0);
509
510 let desired = child.layout(Size::new(slot_w, slot_h));
511
512 if self.height.is_none() {
515 h = (desired.height + m.vertical())
516 .clamp(self.base.min_size.height, self.base.max_size.height);
517 }
518
519 let h_anchor = child.h_anchor();
521 let min_w = child.min_size().width;
522 let max_w = child.max_size().width;
523 let child_w = if h_anchor.is_stretch() {
524 slot_w.clamp(min_w, max_w)
525 } else if h_anchor == HAnchor::MAX_FIT_OR_STRETCH {
526 resolve_fit_or_stretch(desired.width, slot_w, true).clamp(min_w, max_w)
527 } else if h_anchor == HAnchor::MIN_FIT_OR_STRETCH {
528 resolve_fit_or_stretch(desired.width, slot_w, false).clamp(min_w, max_w)
529 } else {
530 desired.width.clamp(min_w, max_w)
531 };
532
533 let child_x = if h_anchor.contains(HAnchor::RIGHT) && !h_anchor.contains(HAnchor::LEFT)
534 {
535 (w - m.right - child_w).max(0.0)
536 } else if h_anchor.contains(HAnchor::CENTER) && !h_anchor.is_stretch() {
537 m.left + (slot_w - child_w) * 0.5
538 } else {
539 m.left
540 };
541
542 let v_anchor = child.v_anchor();
544 let min_h = child.min_size().height;
545 let max_h = child.max_size().height;
546 let child_h = if v_anchor.is_stretch() {
547 slot_h.clamp(min_h, max_h)
548 } else if v_anchor == VAnchor::MAX_FIT_OR_STRETCH {
549 resolve_fit_or_stretch(desired.height, slot_h, true).clamp(min_h, max_h)
550 } else if v_anchor == VAnchor::MIN_FIT_OR_STRETCH {
551 resolve_fit_or_stretch(desired.height, slot_h, false).clamp(min_h, max_h)
552 } else {
553 desired.height.clamp(min_h, max_h)
554 };
555
556 let child_w = if self.width.is_some() {
563 child_w.min(slot_w)
564 } else {
565 child_w
566 };
567 let child_h = if self.height.is_some() {
568 child_h.min(slot_h)
569 } else {
570 child_h
571 };
572
573 let child_y = if v_anchor.contains(VAnchor::TOP) && !v_anchor.contains(VAnchor::BOTTOM)
574 {
575 (h - m.top - child_h).max(0.0)
576 } else if v_anchor.contains(VAnchor::CENTER) && !v_anchor.is_stretch() {
577 m.bottom + (slot_h - child_h) * 0.5
578 } else {
579 m.bottom
580 };
581
582 child.set_bounds(Rect::new(child_x, child_y, child_w, child_h));
583 }
584
585 Size::new(w, h)
586 }
587
588 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
589
590 fn on_event(&mut self, _: &Event) -> EventResult {
591 EventResult::Ignored
592 }
593}