raui_material/component/containers/
context_paper.rs

1use crate::{
2    component::containers::{paper::PaperProps, wrap_paper::wrap_paper},
3    theme::{ThemeColor, ThemedWidgetProps},
4};
5use raui_core::{
6    PropsData, Scalar, make_widget, unpack_named_slots,
7    widget::{
8        WidgetIdOrRef,
9        component::{
10            containers::{
11                context_box::portals_context_box,
12                size_box::{SizeBoxProps, size_box},
13                wrap_box::WrapBoxProps,
14            },
15            interactive::button::{ButtonNotifyProps, button},
16        },
17        context::WidgetContext,
18        node::WidgetNode,
19        unit::{image::ImageBoxFrame, size::SizeBoxSizeValue},
20        utils::Rect,
21    },
22};
23use serde::{Deserialize, Serialize};
24
25#[derive(PropsData, Debug, Clone, Serialize, Deserialize)]
26#[props_data(raui_core::props::PropsData)]
27#[prefab(raui_core::Prefab)]
28pub struct ContextPaperProps {
29    #[serde(default = "ContextPaperProps::default_margin")]
30    pub margin: Rect,
31    #[serde(default = "ContextPaperProps::default_frame")]
32    pub frame: Option<Scalar>,
33    #[serde(default)]
34    pub notify_backdrop_accept: WidgetIdOrRef,
35}
36
37impl Default for ContextPaperProps {
38    fn default() -> Self {
39        Self {
40            margin: Self::default_margin(),
41            frame: Self::default_frame(),
42            notify_backdrop_accept: Default::default(),
43        }
44    }
45}
46
47impl ContextPaperProps {
48    fn default_margin() -> Rect {
49        Rect {
50            left: 10.0,
51            right: 10.0,
52            top: 10.0,
53            bottom: 10.0,
54        }
55    }
56
57    #[allow(clippy::unnecessary_wraps)]
58    fn default_frame() -> Option<Scalar> {
59        Some(2.0)
60    }
61}
62
63pub fn context_paper(context: WidgetContext) -> WidgetNode {
64    let WidgetContext {
65        idref,
66        key,
67        props,
68        named_slots,
69        ..
70    } = context;
71    unpack_named_slots!(named_slots => {content, context});
72
73    let ContextPaperProps {
74        margin,
75        frame,
76        notify_backdrop_accept,
77    } = props.read_cloned_or_default();
78
79    let context_size_props = SizeBoxProps {
80        width: SizeBoxSizeValue::Content,
81        height: SizeBoxSizeValue::Content,
82        ..Default::default()
83    };
84    let themed_props = props.read_cloned_or_else(|| ThemedWidgetProps {
85        color: ThemeColor::Primary,
86        ..Default::default()
87    });
88    let paper_props = props.read_cloned_or_else(|| PaperProps {
89        frame: frame.map(|v| ImageBoxFrame::from((v, true))),
90        ..Default::default()
91    });
92    let wrap_props = props
93        .clone()
94        .with(themed_props)
95        .with(paper_props)
96        .with(WrapBoxProps {
97            margin,
98            fill: false,
99        });
100    let backdrop_size_props = SizeBoxProps {
101        width: SizeBoxSizeValue::Fill,
102        height: SizeBoxSizeValue::Fill,
103        ..Default::default()
104    };
105
106    make_widget!(portals_context_box)
107        .key(key)
108        .maybe_idref(idref.cloned())
109        .merge_props(props.clone())
110        .named_slot("content", content)
111        .named_slot(
112            "context",
113            make_widget!(size_box)
114                .key("size")
115                .with_props(context_size_props)
116                .named_slot(
117                    "content",
118                    make_widget!(wrap_paper)
119                        .key("wrap")
120                        .merge_props(wrap_props)
121                        .named_slot("content", context),
122                ),
123        )
124        .named_slot(
125            "backdrop",
126            make_widget!(button)
127                .key("button")
128                .with_props(ButtonNotifyProps(notify_backdrop_accept))
129                .named_slot(
130                    "content",
131                    make_widget!(size_box)
132                        .key("size")
133                        .with_props(backdrop_size_props),
134                ),
135        )
136        .into()
137}