raui_material/component/containers/
context_paper.rs1use 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}