raui_core/widget/component/containers/
context_box.rs

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