raui_material/component/
switch_paper.rs

1use crate::theme::{ThemeColor, ThemeProps, ThemedImageMaterial, ThemedWidgetProps};
2use raui_core::{
3    PropsData, Scalar, make_widget,
4    widget::{
5        component::image_box::{ImageBoxProps, image_box},
6        context::WidgetContext,
7        node::WidgetNode,
8        unit::image::{ImageBoxColor, ImageBoxImageScaling, ImageBoxMaterial, ImageBoxSizeValue},
9    },
10};
11use serde::{Deserialize, Serialize};
12
13#[derive(PropsData, Debug, Default, Clone, Serialize, Deserialize)]
14#[props_data(raui_core::props::PropsData)]
15#[prefab(raui_core::Prefab)]
16pub struct SwitchPaperProps {
17    #[serde(default)]
18    pub on: bool,
19    #[serde(default)]
20    pub variant: String,
21    #[serde(default)]
22    pub size_level: usize,
23}
24
25pub fn switch_paper(context: WidgetContext) -> WidgetNode {
26    let WidgetContext {
27        idref,
28        key,
29        props,
30        shared_props,
31        ..
32    } = context;
33
34    let SwitchPaperProps {
35        on,
36        variant,
37        size_level,
38    } = props.read_cloned_or_default();
39    let themed_props = props.read_cloned_or_default::<ThemedWidgetProps>();
40    let color = match shared_props.read::<ThemeProps>() {
41        Ok(props) => match themed_props.color {
42            ThemeColor::Default => props.active_colors.main.default.main,
43            ThemeColor::Primary => props.active_colors.main.primary.main,
44            ThemeColor::Secondary => props.active_colors.main.secondary.main,
45        },
46        Err(_) => Default::default(),
47    };
48    let (size, material) = match shared_props.read::<ThemeProps>() {
49        Ok(props) => {
50            let size = props
51                .icons_level_sizes
52                .get(size_level)
53                .copied()
54                .unwrap_or(24.0);
55            let material = if let Some(material) = props.switch_variants.get(&variant) {
56                if on {
57                    material.on.clone()
58                } else {
59                    material.off.clone()
60                }
61            } else {
62                Default::default()
63            };
64            (size, material)
65        }
66        Err(_) => (24.0, Default::default()),
67    };
68    let image = match material {
69        ThemedImageMaterial::Color => ImageBoxProps {
70            material: ImageBoxMaterial::Color(ImageBoxColor {
71                color,
72                scaling: if on {
73                    ImageBoxImageScaling::Stretch
74                } else {
75                    ImageBoxImageScaling::Frame((size_level as Scalar, true).into())
76                },
77            }),
78            width: ImageBoxSizeValue::Exact(size),
79            height: ImageBoxSizeValue::Exact(size),
80            ..Default::default()
81        },
82        ThemedImageMaterial::Image(mut data) => {
83            data.tint = color;
84            ImageBoxProps {
85                material: ImageBoxMaterial::Image(data),
86                width: ImageBoxSizeValue::Exact(size),
87                height: ImageBoxSizeValue::Exact(size),
88                ..Default::default()
89            }
90        }
91        ThemedImageMaterial::Procedural(data) => ImageBoxProps {
92            material: ImageBoxMaterial::Procedural(data),
93            width: ImageBoxSizeValue::Exact(size),
94            height: ImageBoxSizeValue::Exact(size),
95            ..Default::default()
96        },
97    };
98
99    make_widget!(image_box)
100        .key(key)
101        .maybe_idref(idref.cloned())
102        .with_props(image)
103        .into()
104}