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 widget_base(&self) -> Option<&WidgetBase> {
88 Some(&self.base)
89 }
90 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
91 Some(&mut self.base)
92 }
93 fn h_anchor(&self) -> HAnchor {
94 self.base.h_anchor
95 }
96 fn v_anchor(&self) -> VAnchor {
97 self.base.v_anchor
98 }
99 fn min_size(&self) -> Size {
100 self.base.min_size
101 }
102 fn max_size(&self) -> Size {
103 self.base.max_size
104 }
105
106 fn layout(&mut self, available: Size) -> Size {
107 for child in &mut self.children {
108 child.layout(available);
109 child.set_bounds(Rect::new(0.0, 0.0, available.width, available.height));
110 }
111
112 let mut i = 0;
131 let mut raised: Vec<Box<dyn Widget>> = Vec::new();
132 while i < self.children.len() {
133 if self.children[i].take_raise_request() {
134 raised.push(self.children.remove(i));
135 } else {
137 i += 1;
138 }
139 }
140 for r in raised {
141 self.children.push(r);
142 }
143
144 available
145 }
146
147 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
148
149 fn on_event(&mut self, _: &Event) -> EventResult {
150 EventResult::Ignored
151 }
152}
153
154pub struct Padding {
160 bounds: Rect,
161 children: Vec<Box<dyn Widget>>,
162 base: WidgetBase,
163 insets: Insets,
164}
165
166impl Padding {
167 pub fn new(insets: Insets, child: Box<dyn Widget>) -> Self {
169 Self {
170 bounds: Rect::default(),
171 children: vec![child],
172 base: WidgetBase::new(),
173 insets,
174 }
175 }
176
177 pub fn uniform(amount: f64, child: Box<dyn Widget>) -> Self {
179 Self::new(Insets::all(amount), child)
180 }
181
182 pub fn with_margin(mut self, m: Insets) -> Self {
183 self.base.margin = m;
184 self
185 }
186 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
187 self.base.h_anchor = h;
188 self
189 }
190 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
191 self.base.v_anchor = v;
192 self
193 }
194 pub fn with_min_size(mut self, s: Size) -> Self {
195 self.base.min_size = s;
196 self
197 }
198 pub fn with_max_size(mut self, s: Size) -> Self {
199 self.base.max_size = s;
200 self
201 }
202}
203
204impl Widget for Padding {
205 fn type_name(&self) -> &'static str {
206 "Padding"
207 }
208 fn bounds(&self) -> Rect {
209 self.bounds
210 }
211 fn set_bounds(&mut self, b: Rect) {
212 self.bounds = b;
213 }
214 fn children(&self) -> &[Box<dyn Widget>] {
215 &self.children
216 }
217 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
218 &mut self.children
219 }
220
221 fn margin(&self) -> Insets {
222 self.base.margin
223 }
224 fn widget_base(&self) -> Option<&WidgetBase> {
225 Some(&self.base)
226 }
227 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
228 Some(&mut self.base)
229 }
230 fn h_anchor(&self) -> HAnchor {
231 self.base.h_anchor
232 }
233 fn v_anchor(&self) -> VAnchor {
234 self.base.v_anchor
235 }
236 fn min_size(&self) -> Size {
237 self.base.min_size
238 }
239 fn max_size(&self) -> Size {
240 self.base.max_size
241 }
242
243 fn layout(&mut self, available: Size) -> Size {
244 let p = &self.insets;
245 let inner = Size::new(
246 (available.width - p.left - p.right).max(0.0),
247 (available.height - p.top - p.bottom).max(0.0),
248 );
249 if let Some(child) = self.children.first_mut() {
250 let desired = child.layout(inner);
251 child.set_bounds(Rect::new(p.left, p.bottom, desired.width, desired.height));
253 }
254 let content_w = self.children.first().map_or(0.0, |c| c.bounds().width);
256 let content_h = self.children.first().map_or(0.0, |c| c.bounds().height);
257 Size::new(content_w + p.left + p.right, content_h + p.top + p.bottom)
258 }
259
260 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
261
262 fn on_event(&mut self, _: &Event) -> EventResult {
263 EventResult::Ignored
264 }
265}
266
267pub struct SizedBox {
277 bounds: Rect,
278 children: Vec<Box<dyn Widget>>,
279 base: WidgetBase,
280 pub width: Option<f64>,
281 pub height: Option<f64>,
282}
283
284impl SizedBox {
285 pub fn new() -> Self {
286 Self {
287 bounds: Rect::default(),
288 children: Vec::new(),
289 base: WidgetBase::new(),
290 width: None,
291 height: None,
292 }
293 }
294
295 pub fn with_width(mut self, w: f64) -> Self {
296 self.width = Some(w);
297 self
298 }
299 pub fn with_height(mut self, h: f64) -> Self {
300 self.height = Some(h);
301 self
302 }
303
304 pub fn with_child(mut self, child: Box<dyn Widget>) -> Self {
305 self.children.clear();
306 self.children.push(child);
307 self
308 }
309
310 pub fn fixed(width: f64, height: f64) -> Self {
312 Self::new().with_width(width).with_height(height)
313 }
314
315 pub fn with_margin(mut self, m: Insets) -> Self {
316 self.base.margin = m;
317 self
318 }
319 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
320 self.base.h_anchor = h;
321 self
322 }
323 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
324 self.base.v_anchor = v;
325 self
326 }
327 pub fn with_min_size(mut self, s: Size) -> Self {
328 self.base.min_size = s;
329 self
330 }
331 pub fn with_max_size(mut self, s: Size) -> Self {
332 self.base.max_size = s;
333 self
334 }
335}
336
337impl Default for SizedBox {
338 fn default() -> Self {
339 Self::new()
340 }
341}
342
343impl Widget for SizedBox {
344 fn type_name(&self) -> &'static str {
345 "SizedBox"
346 }
347 fn bounds(&self) -> Rect {
348 self.bounds
349 }
350 fn set_bounds(&mut self, b: Rect) {
351 self.bounds = b;
352 }
353 fn children(&self) -> &[Box<dyn Widget>] {
354 &self.children
355 }
356 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
357 &mut self.children
358 }
359
360 fn margin(&self) -> Insets {
361 self.base.margin
362 }
363 fn widget_base(&self) -> Option<&WidgetBase> {
364 Some(&self.base)
365 }
366 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
367 Some(&mut self.base)
368 }
369 fn h_anchor(&self) -> HAnchor {
370 self.base.h_anchor
371 }
372 fn v_anchor(&self) -> VAnchor {
373 self.base.v_anchor
374 }
375 fn min_size(&self) -> Size {
376 self.base.min_size
377 }
378 fn max_size(&self) -> Size {
379 self.base.max_size
380 }
381
382 fn layout(&mut self, available: Size) -> Size {
383 let w = self.width.unwrap_or(available.width);
394 let mut h = self.height.unwrap_or_else(|| {
395 if self.children.is_empty() {
396 0.0
397 } else {
398 available.height
399 }
400 });
401
402 if let Some(child) = self.children.first_mut() {
403 let scale = device_scale();
404 let m = child.margin().scale(scale);
405 let slot_w = (w - m.left - m.right).max(0.0);
406 let slot_h = (h - m.top - m.bottom).max(0.0);
407
408 let desired = child.layout(Size::new(slot_w, slot_h));
409
410 if self.height.is_none() {
413 h = (desired.height + m.vertical())
414 .clamp(self.base.min_size.height, self.base.max_size.height);
415 }
416
417 let h_anchor = child.h_anchor();
419 let min_w = child.min_size().width;
420 let max_w = child.max_size().width;
421 let child_w = if h_anchor.is_stretch() {
422 slot_w.clamp(min_w, max_w)
423 } else if h_anchor == HAnchor::MAX_FIT_OR_STRETCH {
424 resolve_fit_or_stretch(desired.width, slot_w, true).clamp(min_w, max_w)
425 } else if h_anchor == HAnchor::MIN_FIT_OR_STRETCH {
426 resolve_fit_or_stretch(desired.width, slot_w, false).clamp(min_w, max_w)
427 } else {
428 desired.width.clamp(min_w, max_w)
429 };
430
431 let child_x = if h_anchor.contains(HAnchor::RIGHT) && !h_anchor.contains(HAnchor::LEFT)
432 {
433 (w - m.right - child_w).max(0.0)
434 } else if h_anchor.contains(HAnchor::CENTER) && !h_anchor.is_stretch() {
435 m.left + (slot_w - child_w) * 0.5
436 } else {
437 m.left
438 };
439
440 let v_anchor = child.v_anchor();
442 let min_h = child.min_size().height;
443 let max_h = child.max_size().height;
444 let child_h = if v_anchor.is_stretch() {
445 slot_h.clamp(min_h, max_h)
446 } else if v_anchor == VAnchor::MAX_FIT_OR_STRETCH {
447 resolve_fit_or_stretch(desired.height, slot_h, true).clamp(min_h, max_h)
448 } else if v_anchor == VAnchor::MIN_FIT_OR_STRETCH {
449 resolve_fit_or_stretch(desired.height, slot_h, false).clamp(min_h, max_h)
450 } else {
451 desired.height.clamp(min_h, max_h)
452 };
453
454 let child_w = if self.width.is_some() {
461 child_w.min(slot_w)
462 } else {
463 child_w
464 };
465 let child_h = if self.height.is_some() {
466 child_h.min(slot_h)
467 } else {
468 child_h
469 };
470
471 let child_y = if v_anchor.contains(VAnchor::TOP) && !v_anchor.contains(VAnchor::BOTTOM)
472 {
473 (h - m.top - child_h).max(0.0)
474 } else if v_anchor.contains(VAnchor::CENTER) && !v_anchor.is_stretch() {
475 m.bottom + (slot_h - child_h) * 0.5
476 } else {
477 m.bottom
478 };
479
480 child.set_bounds(Rect::new(child_x, child_y, child_w, child_h));
481 }
482
483 Size::new(w, h)
484 }
485
486 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
487
488 fn on_event(&mut self, _: &Event) -> EventResult {
489 EventResult::Ignored
490 }
491}
492
493pub struct Spacer {
502 bounds: Rect,
503 children: Vec<Box<dyn Widget>>,
504 base: WidgetBase,
505}
506
507impl Spacer {
508 pub fn new() -> Self {
509 Self {
510 bounds: Rect::default(),
511 children: Vec::new(),
512 base: WidgetBase::new(),
513 }
514 }
515
516 pub fn with_margin(mut self, m: Insets) -> Self {
517 self.base.margin = m;
518 self
519 }
520 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
521 self.base.h_anchor = h;
522 self
523 }
524 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
525 self.base.v_anchor = v;
526 self
527 }
528 pub fn with_min_size(mut self, s: Size) -> Self {
529 self.base.min_size = s;
530 self
531 }
532 pub fn with_max_size(mut self, s: Size) -> Self {
533 self.base.max_size = s;
534 self
535 }
536}
537
538impl Default for Spacer {
539 fn default() -> Self {
540 Self::new()
541 }
542}
543
544impl Widget for Spacer {
545 fn type_name(&self) -> &'static str {
546 "Spacer"
547 }
548 fn bounds(&self) -> Rect {
549 self.bounds
550 }
551 fn set_bounds(&mut self, b: Rect) {
552 self.bounds = b;
553 }
554 fn children(&self) -> &[Box<dyn Widget>] {
555 &self.children
556 }
557 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
558 &mut self.children
559 }
560
561 fn margin(&self) -> Insets {
562 self.base.margin
563 }
564 fn widget_base(&self) -> Option<&WidgetBase> {
565 Some(&self.base)
566 }
567 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
568 Some(&mut self.base)
569 }
570 fn h_anchor(&self) -> HAnchor {
571 self.base.h_anchor
572 }
573 fn v_anchor(&self) -> VAnchor {
574 self.base.v_anchor
575 }
576 fn min_size(&self) -> Size {
577 self.base.min_size
578 }
579 fn max_size(&self) -> Size {
580 self.base.max_size
581 }
582
583 fn layout(&mut self, available: Size) -> Size {
584 available
585 }
586
587 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
588
589 fn on_event(&mut self, _: &Event) -> EventResult {
590 EventResult::Ignored
591 }
592}
593
594pub struct Separator {
604 bounds: Rect,
605 children: Vec<Box<dyn Widget>>,
606 base: WidgetBase,
607 vertical: bool,
608 line_inset: f64,
609 color: Option<Color>,
611}
612
613impl Separator {
614 pub fn horizontal() -> Self {
616 Self {
617 bounds: Rect::default(),
618 children: Vec::new(),
619 base: WidgetBase::new(),
620 vertical: false,
621 line_inset: 4.0,
622 color: None,
623 }
624 }
625
626 pub fn vertical() -> Self {
628 Self {
629 vertical: true,
630 ..Self::horizontal()
631 }
632 }
633
634 pub fn with_line_inset(mut self, m: f64) -> Self {
635 self.line_inset = m;
636 self
637 }
638 pub fn with_color(mut self, c: Color) -> Self {
639 self.color = Some(c);
640 self
641 }
642
643 pub fn with_margin(mut self, m: Insets) -> Self {
644 self.base.margin = m;
645 self
646 }
647 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
648 self.base.h_anchor = h;
649 self
650 }
651 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
652 self.base.v_anchor = v;
653 self
654 }
655 pub fn with_min_size(mut self, s: Size) -> Self {
656 self.base.min_size = s;
657 self
658 }
659 pub fn with_max_size(mut self, s: Size) -> Self {
660 self.base.max_size = s;
661 self
662 }
663}
664
665impl Widget for Separator {
666 fn type_name(&self) -> &'static str {
667 "Separator"
668 }
669 fn bounds(&self) -> Rect {
670 self.bounds
671 }
672 fn set_bounds(&mut self, b: Rect) {
673 self.bounds = b;
674 }
675 fn children(&self) -> &[Box<dyn Widget>] {
676 &self.children
677 }
678 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
679 &mut self.children
680 }
681
682 fn margin(&self) -> Insets {
683 self.base.margin
684 }
685 fn widget_base(&self) -> Option<&WidgetBase> {
686 Some(&self.base)
687 }
688 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
689 Some(&mut self.base)
690 }
691 fn h_anchor(&self) -> HAnchor {
692 self.base.h_anchor
693 }
694 fn v_anchor(&self) -> VAnchor {
695 self.base.v_anchor
696 }
697 fn min_size(&self) -> Size {
698 self.base.min_size
699 }
700 fn max_size(&self) -> Size {
701 self.base.max_size
702 }
703
704 fn layout(&mut self, available: Size) -> Size {
705 if self.vertical {
706 Size::new(1.0 + self.line_inset * 2.0, available.height)
707 } else {
708 Size::new(available.width, 1.0 + self.line_inset * 2.0)
709 }
710 }
711
712 fn paint(&mut self, ctx: &mut dyn DrawCtx) {
713 let w = self.bounds.width;
714 let h = self.bounds.height;
715 let color = self.color.unwrap_or_else(|| ctx.visuals().separator);
716 ctx.set_fill_color(color);
717 ctx.begin_path();
718 if self.vertical {
719 ctx.rect(self.line_inset, 0.0, 1.0, h);
720 } else {
721 ctx.rect(0.0, self.line_inset, w, 1.0);
722 }
723 ctx.fill();
724 }
725
726 fn on_event(&mut self, _: &Event) -> EventResult {
727 EventResult::Ignored
728 }
729}
730