Skip to main content

sequoia_view/
backdrop.rs

1#![forbid(unsafe_code)]
2
3use sequoia_core::Length;
4use sequoia_layout::LayoutStyle;
5use sequoia_style::Backdrop;
6
7use crate::any::AnyView;
8use crate::view::{PaintCtx, View};
9
10#[derive(Clone)]
11pub struct BackdropBlur {
12    child: AnyView,
13    backdrop: Backdrop,
14}
15
16impl BackdropBlur {
17    pub fn new<V: View + 'static>(child: V, backdrop: Backdrop) -> Self {
18        Self {
19            child: AnyView::new(child),
20            backdrop,
21        }
22    }
23
24    pub fn blurred<V: View + 'static>(child: V, radius: f32) -> Self {
25        Self::new(child, Backdrop::blur(radius))
26    }
27
28    pub fn style(&self) -> Backdrop {
29        self.backdrop
30    }
31}
32
33impl View for BackdropBlur {
34    fn body(&self) -> impl View + 'static {
35        crate::views::Unit
36    }
37
38    fn children_override(&self) -> Option<Vec<AnyView>> {
39        Some(vec![self.child.clone()])
40    }
41
42    fn layout_style(&self) -> LayoutStyle {
43        LayoutStyle {
44            width: Length::Fit,
45            height: Length::Fit,
46            ..LayoutStyle::default()
47        }
48    }
49
50    fn paint_self(&self, ctx: &mut PaintCtx) {
51        ctx.push_backdrop(ctx.rect, self.backdrop);
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use crate::filter_view::FilterExt;
59    use sequoia_core::{Color, Rect, RenderList, SpanMask};
60
61    #[test]
62    fn wrapper_paints_marker_before_child() {
63        let v = BackdropBlur::blurred(crate::views::Unit, 16.0);
64        let mut list = RenderList::new();
65
66        let rect = Rect::from_xywh(10.0, 20.0, 200.0, 100.0);
67
68        list.push_backdrop(rect, 0.0, 16.0, Color::TRANSPARENT, 0.0, SpanMask::None);
69        assert!(list.has_backdrops());
70        let span = list.backdrops()[0];
71        assert_eq!(span.at, 0, "marker before child content");
72        assert_eq!(span.draw.rect, rect);
73        assert_eq!(span.draw.blur, 16.0);
74        let _ = v;
75    }
76
77    #[test]
78    fn blur_behind_is_canonical() {
79        let w = crate::views::Unit.blur_behind(16.0);
80        assert_eq!(w.style(), Backdrop::blur(16.0));
81    }
82
83    #[test]
84    fn wrapper_is_fit_like_opacity() {
85        let style = BackdropBlur::blurred(crate::views::Unit, 8.0).layout_style();
86        assert_eq!(style.width, Length::Fit);
87        assert_eq!(style.height, Length::Fit);
88    }
89}