pax_std_primitives/
checkbox.rs

1use pax_message::{AnyCreatePatch, CheckboxPatch};
2use pax_runtime::api::{Layer, Property};
3use pax_runtime::{
4    BaseInstance, ExpandedNode, ExpandedNodeIdentifier, InstanceFlags, InstanceNode,
5    InstantiationArgs, RuntimeContext,
6};
7use_RefCell!();
8use pax_runtime_api::{borrow, borrow_mut, use_RefCell};
9use pax_std::primitives::Checkbox;
10use std::collections::HashMap;
11use std::rc::Rc;
12
13use crate::patch_if_needed;
14
15pub struct CheckboxInstance {
16    base: BaseInstance,
17    // Properties that listen to Text property changes, and computes
18    // a patch in the case that they have changed + sends it as a native
19    // message to the chassi. Since InstanceNode -> ExpandedNode has a one
20    // to many relationship, needs to be a hashmap
21    native_message_props: RefCell<HashMap<ExpandedNodeIdentifier, Property<()>>>,
22}
23
24impl InstanceNode for CheckboxInstance {
25    fn instantiate(args: InstantiationArgs) -> Rc<Self>
26    where
27        Self: Sized,
28    {
29        Rc::new(Self {
30            base: BaseInstance::new(
31                args,
32                InstanceFlags {
33                    invisible_to_slot: false,
34                    invisible_to_raycasting: false,
35                    layer: Layer::Native,
36                    is_component: false,
37                },
38            ),
39            native_message_props: Default::default(),
40        })
41    }
42
43    fn update(self: Rc<Self>, expanded_node: &Rc<ExpandedNode>, _context: &Rc<RuntimeContext>) {
44        //trigger computation of property that computes + sends native message update
45        borrow!(self.native_message_props)
46            .get(&expanded_node.id)
47            .unwrap()
48            .get();
49    }
50
51    fn handle_mount(
52        self: Rc<Self>,
53        expanded_node: &Rc<ExpandedNode>,
54        context: &Rc<RuntimeContext>,
55    ) {
56        let id = expanded_node.id.to_u32();
57        context.enqueue_native_message(pax_message::NativeMessage::CheckboxCreate(
58            AnyCreatePatch {
59                id,
60                parent_frame: expanded_node.parent_frame.get().map(|v| v.to_u32()),
61                occlusion_layer_id: 0,
62            },
63        ));
64        let weak_self_ref = Rc::downgrade(&expanded_node);
65        let context = Rc::clone(context);
66        let last_patch = Rc::new(RefCell::new(CheckboxPatch {
67            id,
68            ..Default::default()
69        }));
70
71        let deps: Vec<_> = borrow!(expanded_node.properties_scope)
72            .values()
73            .cloned()
74            .chain([expanded_node.transform_and_bounds.untyped()])
75            .collect();
76        borrow_mut!(self.native_message_props).insert(
77            expanded_node.id,
78            Property::computed(
79                move || {
80                    let Some(expanded_node) = weak_self_ref.upgrade() else {
81                        unreachable!()
82                    };
83                    let mut old_state = borrow_mut!(last_patch);
84
85                    let mut patch = CheckboxPatch {
86                        id,
87                        ..Default::default()
88                    };
89                    expanded_node.with_properties_unwrapped(|properties: &mut Checkbox| {
90                        let computed_tab = expanded_node.transform_and_bounds.get();
91                        let (width, height) = computed_tab.bounds;
92                        let updates = [
93                            patch_if_needed(
94                                &mut old_state.checked,
95                                &mut patch.checked,
96                                properties.checked.get(),
97                            ),
98                            patch_if_needed(&mut old_state.size_x, &mut patch.size_x, width),
99                            patch_if_needed(&mut old_state.size_y, &mut patch.size_y, height),
100                            patch_if_needed(
101                                &mut old_state.transform,
102                                &mut patch.transform,
103                                computed_tab.transform.coeffs().to_vec(),
104                            ),
105                        ];
106                        if updates.into_iter().any(|v| v == true) {
107                            context.enqueue_native_message(
108                                pax_message::NativeMessage::CheckboxUpdate(patch),
109                            );
110                        }
111                    });
112                    ()
113                },
114                &deps,
115            ),
116        );
117    }
118
119    fn handle_unmount(&self, expanded_node: &Rc<ExpandedNode>, context: &Rc<RuntimeContext>) {
120        let id = expanded_node.id.clone();
121        context.enqueue_native_message(pax_message::NativeMessage::CheckboxDelete(id.to_u32()));
122        // Reset so that native_message sending updates while unmounted
123        borrow_mut!(self.native_message_props).remove(&id);
124    }
125
126    fn base(&self) -> &BaseInstance {
127        &self.base
128    }
129
130    fn resolve_debug(
131        &self,
132        f: &mut std::fmt::Formatter,
133        _expanded_node: Option<&ExpandedNode>,
134    ) -> std::fmt::Result {
135        f.debug_struct("Checkbox").finish_non_exhaustive()
136    }
137}