raui_material/component/containers/
window_paper.rs

1use crate::{
2    component::containers::wrap_paper::wrap_paper,
3    theme::{ThemeColor, ThemedWidgetProps},
4};
5use raui_core::{
6    PropsData, Scalar, make_widget, unpack_named_slots,
7    widget::{
8        component::containers::{
9            horizontal_box::horizontal_box, vertical_box::vertical_box, wrap_box::WrapBoxProps,
10        },
11        context::WidgetContext,
12        node::WidgetNode,
13        unit::flex::FlexBoxItemLayout,
14        utils::Rect,
15    },
16};
17use serde::{Deserialize, Serialize};
18
19#[derive(PropsData, Debug, Clone, Serialize, Deserialize)]
20#[props_data(raui_core::props::PropsData)]
21#[prefab(raui_core::Prefab)]
22pub struct WindowPaperProps {
23    #[serde(default)]
24    pub bar_color: ThemeColor,
25    #[serde(default = "WindowPaperProps::default_bar_margin")]
26    pub bar_margin: Rect,
27    #[serde(default = "WindowPaperProps::default_bar_height")]
28    pub bar_height: Option<Scalar>,
29    #[serde(default = "WindowPaperProps::default_content_margin")]
30    pub content_margin: Rect,
31}
32
33impl Default for WindowPaperProps {
34    fn default() -> Self {
35        Self {
36            bar_color: ThemeColor::Primary,
37            bar_margin: Self::default_bar_margin(),
38            bar_height: Self::default_bar_height(),
39            content_margin: Self::default_content_margin(),
40        }
41    }
42}
43
44impl WindowPaperProps {
45    fn default_bar_margin() -> Rect {
46        Rect {
47            left: 10.0,
48            right: 10.0,
49            top: 4.0,
50            bottom: 4.0,
51        }
52    }
53
54    fn default_bar_height() -> Option<Scalar> {
55        Some(32.0)
56    }
57
58    fn default_content_margin() -> Rect {
59        10.0.into()
60    }
61}
62
63pub fn window_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, bar});
72
73    let window_props = props.read_cloned_or_default::<WindowPaperProps>();
74
75    make_widget!(vertical_box)
76        .key(key)
77        .maybe_idref(idref.cloned())
78        .merge_props(props.clone())
79        .listed_slot(
80            make_widget!(wrap_paper)
81                .key("bar")
82                .with_props(ThemedWidgetProps {
83                    color: window_props.bar_color,
84                    ..Default::default()
85                })
86                .with_props(WrapBoxProps {
87                    margin: window_props.bar_margin,
88                    ..Default::default()
89                })
90                .with_props(FlexBoxItemLayout {
91                    basis: window_props.bar_height,
92                    grow: 0.0,
93                    shrink: 0.0,
94                    ..Default::default()
95                })
96                .named_slot("content", bar),
97        )
98        .listed_slot(
99            make_widget!(wrap_paper)
100                .key("content")
101                .with_props(WrapBoxProps {
102                    margin: window_props.content_margin,
103                    ..Default::default()
104                })
105                .named_slot("content", content),
106        )
107        .into()
108}
109
110pub fn window_title_controls_paper(context: WidgetContext) -> WidgetNode {
111    let WidgetContext {
112        key, named_slots, ..
113    } = context;
114    unpack_named_slots!(named_slots => {content, title, controls});
115
116    let mut controls = if let WidgetNode::Tuple(nodes) = controls {
117        make_widget!(horizontal_box).listed_slots(nodes).into()
118    } else {
119        controls
120    };
121    controls.remap_props(|p| {
122        if p.has::<FlexBoxItemLayout>() {
123            p
124        } else {
125            p.with(FlexBoxItemLayout {
126                grow: 0.0,
127                shrink: 0.0,
128                ..Default::default()
129            })
130        }
131    });
132
133    make_widget!(window_paper)
134        .key(key)
135        .named_slot(
136            "bar",
137            make_widget!(horizontal_box)
138                .key("bar")
139                .listed_slot(title)
140                .listed_slot(controls),
141        )
142        .named_slot("content", content)
143        .into()
144}