raui_core/widget/component/containers/
content_box.rs

1//! A generic container for content with optional clipping and transforms
2
3use crate::{
4    PropsData, make_widget, pre_hooks,
5    widget::{
6        component::interactive::navigation::{
7            NavContainerActive, NavItemActive, NavJumpActive, use_nav_container_active,
8            use_nav_item, use_nav_jump_direction_active,
9        },
10        context::WidgetContext,
11        node::WidgetNode,
12        unit::content::{
13            ContentBoxContentReposition, ContentBoxItemLayout, ContentBoxItemNode, ContentBoxNode,
14        },
15        utils::Transform,
16    },
17};
18use serde::{Deserialize, Serialize};
19
20/// The properties of a [`content_box`] component
21#[derive(PropsData, Debug, Default, Clone, Serialize, Deserialize)]
22#[props_data(crate::props::PropsData)]
23#[prefab(crate::Prefab)]
24pub struct ContentBoxProps {
25    /// Whether or not to clip the parts of items that overflow outside of the box bounds
26    #[serde(default)]
27    pub clipping: bool,
28    /// The content repositioning strategy to use.
29    pub content_reposition: ContentBoxContentReposition,
30    /// The transform to apply to the box and it's contents
31    #[serde(default)]
32    pub transform: Transform,
33}
34
35#[pre_hooks(use_nav_container_active, use_nav_jump_direction_active, use_nav_item)]
36pub fn nav_content_box(mut context: WidgetContext) -> WidgetNode {
37    let WidgetContext {
38        key,
39        props,
40        listed_slots,
41        ..
42    } = context;
43
44    let props = props
45        .clone()
46        .without::<NavContainerActive>()
47        .without::<NavJumpActive>()
48        .without::<NavItemActive>();
49
50    make_widget!(content_box)
51        .key(key)
52        .merge_props(props)
53        .listed_slots(listed_slots)
54        .into()
55}
56
57/// A generic container for other widgets
58///
59/// [`content_box`]'s serve two basic purposes: allowing you to apply transformations and clipping
60/// to all contained widgets and giving contained widgets more control over their layout inside of
61/// the box.
62///
63/// # Transform & Clipping
64///
65/// The transformation and clipping options on the [`content_box`] can be set by setting the
66/// [`ContentBoxProps`] on the component.
67///
68/// # Child Widget Layout
69///
70/// With a [`content_box`] you can get more control over the layout of it's children by adding the
71/// [`ContentBoxItemLayout`] properties to any of it's children.
72pub fn content_box(context: WidgetContext) -> WidgetNode {
73    let WidgetContext {
74        id,
75        props,
76        listed_slots,
77        ..
78    } = context;
79
80    let ContentBoxProps {
81        clipping,
82        transform,
83        content_reposition,
84    } = props.read_cloned_or_default();
85
86    let items = listed_slots
87        .into_iter()
88        .filter_map(|slot| {
89            if let Some(props) = slot.props() {
90                let layout = props.read_cloned_or_default::<ContentBoxItemLayout>();
91                Some(ContentBoxItemNode { slot, layout })
92            } else {
93                None
94            }
95        })
96        .collect::<Vec<_>>();
97
98    ContentBoxNode {
99        id: id.to_owned(),
100        props: props.clone(),
101        items,
102        clipping,
103        content_reposition,
104        transform,
105    }
106    .into()
107}