raui_material/component/containers/
paper.rs1use crate::theme::{ThemeColor, ThemeProps, ThemeVariant, ThemedImageMaterial, ThemedWidgetProps};
2use raui_core::{
3 PropsData, Scalar, make_widget,
4 props::Props,
5 widget::{
6 component::{
7 containers::content_box::content_box,
8 image_box::{ImageBoxProps, image_box},
9 },
10 context::WidgetContext,
11 node::WidgetNode,
12 unit::{
13 content::ContentBoxItemLayout,
14 image::{ImageBoxColor, ImageBoxFrame, ImageBoxImageScaling, ImageBoxMaterial},
15 },
16 },
17};
18use serde::{Deserialize, Serialize};
19
20#[derive(PropsData, Debug, Default, Clone, Serialize, Deserialize)]
21#[props_data(raui_core::props::PropsData)]
22#[prefab(raui_core::Prefab)]
23pub struct PaperProps {
24 #[serde(default)]
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub frame: Option<ImageBoxFrame>,
27 #[serde(default)]
28 pub variant: String,
29}
30
31#[derive(PropsData, Debug, Default, Clone, Serialize, Deserialize)]
32#[props_data(raui_core::props::PropsData)]
33#[prefab(raui_core::Prefab)]
34pub struct PaperContentLayoutProps(pub ContentBoxItemLayout);
35
36pub fn paper(context: WidgetContext) -> WidgetNode {
37 let WidgetContext {
38 idref,
39 key,
40 props,
41 shared_props,
42 listed_slots,
43 ..
44 } = context;
45
46 let paper_props = props.read_cloned_or_default::<PaperProps>();
47 let themed_props = props.read_cloned_or_default::<ThemedWidgetProps>();
48 let listed_slots = listed_slots
49 .into_iter()
50 .map(|mut item| {
51 item.remap_props(|mut props| {
52 if let Ok(PaperContentLayoutProps(layout)) = props.consume_unwrap_cloned() {
53 props.write(layout);
54 }
55 props
56 });
57 item
58 })
59 .collect::<Vec<_>>();
60
61 let items = match themed_props.variant {
62 ThemeVariant::ContentOnly => listed_slots,
63 ThemeVariant::Filled => {
64 let content_background = shared_props.map_or_default::<ThemeProps, _, _>(|props| {
65 props
66 .content_backgrounds
67 .get(&paper_props.variant)
68 .cloned()
69 .unwrap_or_default()
70 });
71 let background_colors = shared_props
72 .map_or_default::<ThemeProps, _, _>(|props| props.background_colors.clone());
73 let image = match content_background {
74 ThemedImageMaterial::Color => {
75 let color = match themed_props.color {
76 ThemeColor::Default => background_colors.main.default.main,
77 ThemeColor::Primary => background_colors.main.primary.main,
78 ThemeColor::Secondary => background_colors.main.secondary.main,
79 };
80 ImageBoxProps {
81 material: ImageBoxMaterial::Color(ImageBoxColor {
82 color,
83 ..Default::default()
84 }),
85 ..Default::default()
86 }
87 }
88 ThemedImageMaterial::Image(material) => ImageBoxProps {
89 material: ImageBoxMaterial::Image(material),
90 ..Default::default()
91 },
92 ThemedImageMaterial::Procedural(material) => ImageBoxProps {
93 material: ImageBoxMaterial::Procedural(material),
94 ..Default::default()
95 },
96 };
97 let props = Props::new(ContentBoxItemLayout {
98 depth: Scalar::NEG_INFINITY,
99 ..Default::default()
100 })
101 .with(image);
102 let background = make_widget!(image_box)
103 .key("background")
104 .merge_props(props)
105 .into();
106 if let Some(frame) = paper_props.frame {
107 let color = match themed_props.color {
108 ThemeColor::Default => background_colors.main.default.dark,
109 ThemeColor::Primary => background_colors.main.primary.dark,
110 ThemeColor::Secondary => background_colors.main.secondary.dark,
111 };
112 let props = Props::new(ContentBoxItemLayout {
113 depth: Scalar::NEG_INFINITY,
114 ..Default::default()
115 })
116 .with(ImageBoxProps {
117 material: ImageBoxMaterial::Color(ImageBoxColor {
118 color,
119 scaling: ImageBoxImageScaling::Frame(frame),
120 }),
121 ..Default::default()
122 });
123 let frame = make_widget!(image_box)
124 .key("frame")
125 .merge_props(props)
126 .into();
127 std::iter::once(background)
128 .chain(std::iter::once(frame))
129 .chain(listed_slots)
130 .collect::<Vec<_>>()
131 } else {
132 std::iter::once(background)
133 .chain(listed_slots)
134 .collect::<Vec<_>>()
135 }
136 }
137 ThemeVariant::Outline => {
138 if let Some(frame) = paper_props.frame {
139 let background_colors = shared_props
140 .map_or_default::<ThemeProps, _, _>(|props| props.background_colors.clone());
141 let color = match themed_props.color {
142 ThemeColor::Default => background_colors.main.default.dark,
143 ThemeColor::Primary => background_colors.main.primary.dark,
144 ThemeColor::Secondary => background_colors.main.secondary.dark,
145 };
146 let props = Props::new(ContentBoxItemLayout {
147 depth: Scalar::NEG_INFINITY,
148 ..Default::default()
149 })
150 .with(ImageBoxProps {
151 material: ImageBoxMaterial::Color(ImageBoxColor {
152 color,
153 scaling: ImageBoxImageScaling::Frame(frame),
154 }),
155 ..Default::default()
156 });
157 let frame = make_widget!(image_box)
158 .key("frame")
159 .merge_props(props)
160 .into();
161 std::iter::once(frame)
162 .chain(listed_slots)
163 .collect::<Vec<_>>()
164 } else {
165 listed_slots
166 }
167 }
168 };
169
170 make_widget!(content_box)
171 .key(key)
172 .maybe_idref(idref.cloned())
173 .merge_props(props.clone())
174 .listed_slots(items)
175 .into()
176}