1use crate::color::Color;
4use crate::device_scale::device_scale;
5use crate::draw_ctx::DrawCtx;
6use crate::event::{Event, EventResult};
7use crate::geometry::{Rect, Size};
8use crate::layout_props::{resolve_fit_or_stretch, HAnchor, Insets, VAnchor, WidgetBase};
9use crate::widget::Widget;
10
11pub struct Stack {
20 bounds: Rect,
21 children: Vec<Box<dyn Widget>>,
22 base: WidgetBase,
23}
24
25impl Stack {
26 pub fn new() -> Self {
27 Self {
28 bounds: Rect::default(),
29 children: Vec::new(),
30 base: WidgetBase::new(),
31 }
32 }
33
34 pub fn add(mut self, child: Box<dyn Widget>) -> Self {
35 self.children.push(child);
36 self
37 }
38
39 pub fn with_margin(mut self, m: Insets) -> Self {
40 self.base.margin = m;
41 self
42 }
43 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
44 self.base.h_anchor = h;
45 self
46 }
47 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
48 self.base.v_anchor = v;
49 self
50 }
51 pub fn with_min_size(mut self, s: Size) -> Self {
52 self.base.min_size = s;
53 self
54 }
55 pub fn with_max_size(mut self, s: Size) -> Self {
56 self.base.max_size = s;
57 self
58 }
59}
60
61impl Default for Stack {
62 fn default() -> Self {
63 Self::new()
64 }
65}
66
67impl Widget for Stack {
68 fn type_name(&self) -> &'static str {
69 "Stack"
70 }
71 fn bounds(&self) -> Rect {
72 self.bounds
73 }
74 fn set_bounds(&mut self, b: Rect) {
75 self.bounds = b;
76 }
77 fn children(&self) -> &[Box<dyn Widget>] {
78 &self.children
79 }
80 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
81 &mut self.children
82 }
83
84 fn margin(&self) -> Insets {
85 self.base.margin
86 }
87 fn h_anchor(&self) -> HAnchor {
88 self.base.h_anchor
89 }
90 fn v_anchor(&self) -> VAnchor {
91 self.base.v_anchor
92 }
93 fn min_size(&self) -> Size {
94 self.base.min_size
95 }
96 fn max_size(&self) -> Size {
97 self.base.max_size
98 }
99
100 fn layout(&mut self, available: Size) -> Size {
101 for child in &mut self.children {
102 child.layout(available);
103 child.set_bounds(Rect::new(0.0, 0.0, available.width, available.height));
104 }
105
106 let mut i = 0;
125 let mut raised: Vec<Box<dyn Widget>> = Vec::new();
126 while i < self.children.len() {
127 if self.children[i].take_raise_request() {
128 raised.push(self.children.remove(i));
129 } else {
131 i += 1;
132 }
133 }
134 for r in raised {
135 self.children.push(r);
136 }
137
138 available
139 }
140
141 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
142
143 fn on_event(&mut self, _: &Event) -> EventResult {
144 EventResult::Ignored
145 }
146}
147
148pub struct Padding {
154 bounds: Rect,
155 children: Vec<Box<dyn Widget>>,
156 base: WidgetBase,
157 insets: Insets,
158}
159
160impl Padding {
161 pub fn new(insets: Insets, child: Box<dyn Widget>) -> Self {
163 Self {
164 bounds: Rect::default(),
165 children: vec![child],
166 base: WidgetBase::new(),
167 insets,
168 }
169 }
170
171 pub fn uniform(amount: f64, child: Box<dyn Widget>) -> Self {
173 Self::new(Insets::all(amount), child)
174 }
175
176 pub fn with_margin(mut self, m: Insets) -> Self {
177 self.base.margin = m;
178 self
179 }
180 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
181 self.base.h_anchor = h;
182 self
183 }
184 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
185 self.base.v_anchor = v;
186 self
187 }
188 pub fn with_min_size(mut self, s: Size) -> Self {
189 self.base.min_size = s;
190 self
191 }
192 pub fn with_max_size(mut self, s: Size) -> Self {
193 self.base.max_size = s;
194 self
195 }
196}
197
198impl Widget for Padding {
199 fn type_name(&self) -> &'static str {
200 "Padding"
201 }
202 fn bounds(&self) -> Rect {
203 self.bounds
204 }
205 fn set_bounds(&mut self, b: Rect) {
206 self.bounds = b;
207 }
208 fn children(&self) -> &[Box<dyn Widget>] {
209 &self.children
210 }
211 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
212 &mut self.children
213 }
214
215 fn margin(&self) -> Insets {
216 self.base.margin
217 }
218 fn h_anchor(&self) -> HAnchor {
219 self.base.h_anchor
220 }
221 fn v_anchor(&self) -> VAnchor {
222 self.base.v_anchor
223 }
224 fn min_size(&self) -> Size {
225 self.base.min_size
226 }
227 fn max_size(&self) -> Size {
228 self.base.max_size
229 }
230
231 fn layout(&mut self, available: Size) -> Size {
232 let p = &self.insets;
233 let inner = Size::new(
234 (available.width - p.left - p.right).max(0.0),
235 (available.height - p.top - p.bottom).max(0.0),
236 );
237 if let Some(child) = self.children.first_mut() {
238 let desired = child.layout(inner);
239 child.set_bounds(Rect::new(p.left, p.bottom, desired.width, desired.height));
241 }
242 let content_w = self.children.first().map_or(0.0, |c| c.bounds().width);
244 let content_h = self.children.first().map_or(0.0, |c| c.bounds().height);
245 Size::new(content_w + p.left + p.right, content_h + p.top + p.bottom)
246 }
247
248 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
249
250 fn on_event(&mut self, _: &Event) -> EventResult {
251 EventResult::Ignored
252 }
253}
254
255pub struct SizedBox {
265 bounds: Rect,
266 children: Vec<Box<dyn Widget>>,
267 base: WidgetBase,
268 pub width: Option<f64>,
269 pub height: Option<f64>,
270}
271
272impl SizedBox {
273 pub fn new() -> Self {
274 Self {
275 bounds: Rect::default(),
276 children: Vec::new(),
277 base: WidgetBase::new(),
278 width: None,
279 height: None,
280 }
281 }
282
283 pub fn with_width(mut self, w: f64) -> Self {
284 self.width = Some(w);
285 self
286 }
287 pub fn with_height(mut self, h: f64) -> Self {
288 self.height = Some(h);
289 self
290 }
291
292 pub fn with_child(mut self, child: Box<dyn Widget>) -> Self {
293 self.children.clear();
294 self.children.push(child);
295 self
296 }
297
298 pub fn fixed(width: f64, height: f64) -> Self {
300 Self::new().with_width(width).with_height(height)
301 }
302
303 pub fn with_margin(mut self, m: Insets) -> Self {
304 self.base.margin = m;
305 self
306 }
307 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
308 self.base.h_anchor = h;
309 self
310 }
311 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
312 self.base.v_anchor = v;
313 self
314 }
315 pub fn with_min_size(mut self, s: Size) -> Self {
316 self.base.min_size = s;
317 self
318 }
319 pub fn with_max_size(mut self, s: Size) -> Self {
320 self.base.max_size = s;
321 self
322 }
323}
324
325impl Default for SizedBox {
326 fn default() -> Self {
327 Self::new()
328 }
329}
330
331impl Widget for SizedBox {
332 fn type_name(&self) -> &'static str {
333 "SizedBox"
334 }
335 fn bounds(&self) -> Rect {
336 self.bounds
337 }
338 fn set_bounds(&mut self, b: Rect) {
339 self.bounds = b;
340 }
341 fn children(&self) -> &[Box<dyn Widget>] {
342 &self.children
343 }
344 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
345 &mut self.children
346 }
347
348 fn margin(&self) -> Insets {
349 self.base.margin
350 }
351 fn h_anchor(&self) -> HAnchor {
352 self.base.h_anchor
353 }
354 fn v_anchor(&self) -> VAnchor {
355 self.base.v_anchor
356 }
357 fn min_size(&self) -> Size {
358 self.base.min_size
359 }
360 fn max_size(&self) -> Size {
361 self.base.max_size
362 }
363
364 fn layout(&mut self, available: Size) -> Size {
365 let w = self.width.unwrap_or(available.width);
376 let mut h = self.height.unwrap_or_else(|| {
377 if self.children.is_empty() {
378 0.0
379 } else {
380 available.height
381 }
382 });
383
384 if let Some(child) = self.children.first_mut() {
385 let scale = device_scale();
386 let m = child.margin().scale(scale);
387 let slot_w = (w - m.left - m.right).max(0.0);
388 let slot_h = (h - m.top - m.bottom).max(0.0);
389
390 let desired = child.layout(Size::new(slot_w, slot_h));
391
392 if self.height.is_none() {
395 h = (desired.height + m.vertical())
396 .clamp(self.base.min_size.height, self.base.max_size.height);
397 }
398
399 let h_anchor = child.h_anchor();
401 let min_w = child.min_size().width;
402 let max_w = child.max_size().width;
403 let child_w = if h_anchor.is_stretch() {
404 slot_w.clamp(min_w, max_w)
405 } else if h_anchor == HAnchor::MAX_FIT_OR_STRETCH {
406 resolve_fit_or_stretch(desired.width, slot_w, true).clamp(min_w, max_w)
407 } else if h_anchor == HAnchor::MIN_FIT_OR_STRETCH {
408 resolve_fit_or_stretch(desired.width, slot_w, false).clamp(min_w, max_w)
409 } else {
410 desired.width.clamp(min_w, max_w)
411 };
412
413 let child_x = if h_anchor.contains(HAnchor::RIGHT) && !h_anchor.contains(HAnchor::LEFT)
414 {
415 (w - m.right - child_w).max(0.0)
416 } else if h_anchor.contains(HAnchor::CENTER) && !h_anchor.is_stretch() {
417 m.left + (slot_w - child_w) * 0.5
418 } else {
419 m.left
420 };
421
422 let v_anchor = child.v_anchor();
424 let min_h = child.min_size().height;
425 let max_h = child.max_size().height;
426 let child_h = if v_anchor.is_stretch() {
427 slot_h.clamp(min_h, max_h)
428 } else if v_anchor == VAnchor::MAX_FIT_OR_STRETCH {
429 resolve_fit_or_stretch(desired.height, slot_h, true).clamp(min_h, max_h)
430 } else if v_anchor == VAnchor::MIN_FIT_OR_STRETCH {
431 resolve_fit_or_stretch(desired.height, slot_h, false).clamp(min_h, max_h)
432 } else {
433 desired.height.clamp(min_h, max_h)
434 };
435
436 let child_w = if self.width.is_some() {
443 child_w.min(slot_w)
444 } else {
445 child_w
446 };
447 let child_h = if self.height.is_some() {
448 child_h.min(slot_h)
449 } else {
450 child_h
451 };
452
453 let child_y = if v_anchor.contains(VAnchor::TOP) && !v_anchor.contains(VAnchor::BOTTOM)
454 {
455 (h - m.top - child_h).max(0.0)
456 } else if v_anchor.contains(VAnchor::CENTER) && !v_anchor.is_stretch() {
457 m.bottom + (slot_h - child_h) * 0.5
458 } else {
459 m.bottom
460 };
461
462 child.set_bounds(Rect::new(child_x, child_y, child_w, child_h));
463 }
464
465 Size::new(w, h)
466 }
467
468 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
469
470 fn on_event(&mut self, _: &Event) -> EventResult {
471 EventResult::Ignored
472 }
473}
474
475pub struct Spacer {
484 bounds: Rect,
485 children: Vec<Box<dyn Widget>>,
486 base: WidgetBase,
487}
488
489impl Spacer {
490 pub fn new() -> Self {
491 Self {
492 bounds: Rect::default(),
493 children: Vec::new(),
494 base: WidgetBase::new(),
495 }
496 }
497
498 pub fn with_margin(mut self, m: Insets) -> Self {
499 self.base.margin = m;
500 self
501 }
502 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
503 self.base.h_anchor = h;
504 self
505 }
506 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
507 self.base.v_anchor = v;
508 self
509 }
510 pub fn with_min_size(mut self, s: Size) -> Self {
511 self.base.min_size = s;
512 self
513 }
514 pub fn with_max_size(mut self, s: Size) -> Self {
515 self.base.max_size = s;
516 self
517 }
518}
519
520impl Default for Spacer {
521 fn default() -> Self {
522 Self::new()
523 }
524}
525
526impl Widget for Spacer {
527 fn type_name(&self) -> &'static str {
528 "Spacer"
529 }
530 fn bounds(&self) -> Rect {
531 self.bounds
532 }
533 fn set_bounds(&mut self, b: Rect) {
534 self.bounds = b;
535 }
536 fn children(&self) -> &[Box<dyn Widget>] {
537 &self.children
538 }
539 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
540 &mut self.children
541 }
542
543 fn margin(&self) -> Insets {
544 self.base.margin
545 }
546 fn h_anchor(&self) -> HAnchor {
547 self.base.h_anchor
548 }
549 fn v_anchor(&self) -> VAnchor {
550 self.base.v_anchor
551 }
552 fn min_size(&self) -> Size {
553 self.base.min_size
554 }
555 fn max_size(&self) -> Size {
556 self.base.max_size
557 }
558
559 fn layout(&mut self, available: Size) -> Size {
560 available
561 }
562
563 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
564
565 fn on_event(&mut self, _: &Event) -> EventResult {
566 EventResult::Ignored
567 }
568}
569
570pub struct Separator {
580 bounds: Rect,
581 children: Vec<Box<dyn Widget>>,
582 base: WidgetBase,
583 vertical: bool,
584 line_inset: f64,
585 color: Option<Color>,
587}
588
589impl Separator {
590 pub fn horizontal() -> Self {
592 Self {
593 bounds: Rect::default(),
594 children: Vec::new(),
595 base: WidgetBase::new(),
596 vertical: false,
597 line_inset: 4.0,
598 color: None,
599 }
600 }
601
602 pub fn vertical() -> Self {
604 Self {
605 vertical: true,
606 ..Self::horizontal()
607 }
608 }
609
610 pub fn with_line_inset(mut self, m: f64) -> Self {
611 self.line_inset = m;
612 self
613 }
614 pub fn with_color(mut self, c: Color) -> Self {
615 self.color = Some(c);
616 self
617 }
618
619 pub fn with_margin(mut self, m: Insets) -> Self {
620 self.base.margin = m;
621 self
622 }
623 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
624 self.base.h_anchor = h;
625 self
626 }
627 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
628 self.base.v_anchor = v;
629 self
630 }
631 pub fn with_min_size(mut self, s: Size) -> Self {
632 self.base.min_size = s;
633 self
634 }
635 pub fn with_max_size(mut self, s: Size) -> Self {
636 self.base.max_size = s;
637 self
638 }
639}
640
641impl Widget for Separator {
642 fn type_name(&self) -> &'static str {
643 "Separator"
644 }
645 fn bounds(&self) -> Rect {
646 self.bounds
647 }
648 fn set_bounds(&mut self, b: Rect) {
649 self.bounds = b;
650 }
651 fn children(&self) -> &[Box<dyn Widget>] {
652 &self.children
653 }
654 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
655 &mut self.children
656 }
657
658 fn margin(&self) -> Insets {
659 self.base.margin
660 }
661 fn h_anchor(&self) -> HAnchor {
662 self.base.h_anchor
663 }
664 fn v_anchor(&self) -> VAnchor {
665 self.base.v_anchor
666 }
667 fn min_size(&self) -> Size {
668 self.base.min_size
669 }
670 fn max_size(&self) -> Size {
671 self.base.max_size
672 }
673
674 fn layout(&mut self, available: Size) -> Size {
675 if self.vertical {
676 Size::new(1.0 + self.line_inset * 2.0, available.height)
677 } else {
678 Size::new(available.width, 1.0 + self.line_inset * 2.0)
679 }
680 }
681
682 fn paint(&mut self, ctx: &mut dyn DrawCtx) {
683 let w = self.bounds.width;
684 let h = self.bounds.height;
685 let color = self.color.unwrap_or_else(|| ctx.visuals().separator);
686 ctx.set_fill_color(color);
687 ctx.begin_path();
688 if self.vertical {
689 ctx.rect(self.line_inset, 0.0, 1.0, h);
690 } else {
691 ctx.rect(0.0, self.line_inset, w, 1.0);
692 }
693 ctx.fill();
694 }
695
696 fn on_event(&mut self, _: &Event) -> EventResult {
697 EventResult::Ignored
698 }
699}