raui_core/widget/component/containers/
context_box.rs

1use crate::{
2    PropsData, make_widget, pre_hooks, unpack_named_slots,
3    widget::{
4        component::containers::{
5            anchor_box::{AnchorProps, PivotBoxProps, pivot_to_anchor_and_align, use_anchor_box},
6            content_box::content_box,
7            portal_box::{portal_box, use_portals_container_relative_layout},
8        },
9        context::WidgetContext,
10        node::WidgetNode,
11        unit::{area::AreaBoxNode, content::ContentBoxItemLayout},
12        utils::{Rect, Vec2},
13    },
14};
15use serde::{Deserialize, Serialize};
16
17#[derive(PropsData, Debug, Default, Copy, Clone, Serialize, Deserialize)]
18#[props_data(crate::props::PropsData)]
19#[prefab(crate::Prefab)]
20pub struct ContextBoxProps {
21    #[serde(default)]
22    pub show: bool,
23}
24
25#[pre_hooks(use_anchor_box)]
26pub fn context_box(mut context: WidgetContext) -> WidgetNode {
27    let WidgetContext {
28        id,
29        idref,
30        key,
31        props,
32        state,
33        named_slots,
34        ..
35    } = context;
36    unpack_named_slots!(named_slots => {content, context, backdrop});
37
38    let ContextBoxProps { show } = props.read_cloned_or_default();
39    let anchor_state = state.read_cloned_or_default::<AnchorProps>();
40    let pivot_props = props.read_cloned_or_default::<PivotBoxProps>();
41    let (Vec2 { x, y }, align) = pivot_to_anchor_and_align(&pivot_props, &anchor_state);
42
43    let context = if show {
44        context.remap_props(|content_props| {
45            let mut item_props = content_props.read_cloned_or_default::<ContentBoxItemLayout>();
46            item_props.anchors = Rect {
47                left: x,
48                right: x,
49                top: y,
50                bottom: y,
51            };
52            item_props.align = align;
53            content_props.with(item_props)
54        });
55
56        make_widget!(portal_box)
57            .named_slot(
58                "content",
59                make_widget!(content_box)
60                    .key("content")
61                    .listed_slot(backdrop)
62                    .listed_slot(context),
63            )
64            .into()
65    } else {
66        WidgetNode::default()
67    };
68
69    let content = make_widget!(content_box)
70        .key(key)
71        .maybe_idref(idref.cloned())
72        .merge_props(props.clone())
73        .listed_slot(content)
74        .listed_slot(context)
75        .into();
76
77    AreaBoxNode {
78        id: id.to_owned(),
79        slot: Box::new(content),
80    }
81    .into()
82}
83
84#[pre_hooks(use_portals_container_relative_layout)]
85pub fn portals_context_box(mut context: WidgetContext) -> WidgetNode {
86    context_box(context)
87}