use std::rc::{Rc, Weak};
use_RefCell!();
use pax_runtime_api::{use_RefCell, ImplToFromPaxAny, Numeric, Property};
use crate::api::Layer;
use crate::{
BaseInstance, ExpandedNode, InstanceFlags, InstanceNode, InstantiationArgs, RuntimeContext,
};
pub struct SlotInstance {
base: BaseInstance,
}
impl ImplToFromPaxAny for Slot {}
#[derive(Default)]
pub struct Slot {
pub index: Property<Numeric>,
pub last_node_id: Property<usize>,
pub showing_node: Property<Weak<ExpandedNode>>,
}
impl InstanceNode for SlotInstance {
fn instantiate(args: InstantiationArgs) -> Rc<Self>
where
Self: Sized,
{
Rc::new(Self {
base: BaseInstance::new(
args,
InstanceFlags {
invisible_to_slot: false,
invisible_to_raycasting: true,
layer: Layer::DontCare,
is_component: false,
},
),
})
}
fn handle_mount(
self: Rc<Self>,
expanded_node: &Rc<ExpandedNode>,
context: &Rc<RuntimeContext>,
) {
let weak_ref_self = Rc::downgrade(expanded_node);
let cloned_context = Rc::clone(context);
let showing_node = expanded_node
.with_properties_unwrapped(|properties: &mut Slot| properties.showing_node.clone());
let deps = vec![showing_node.untyped()];
expanded_node
.children
.replace_with(Property::computed_with_name(
move || {
let Some(cloned_expanded_node) = weak_ref_self.upgrade() else {
panic!("ran evaluator after expanded node dropped (repeat elem)")
};
cloned_expanded_node.attach_children(
showing_node.get().upgrade().as_slice().to_vec(),
&cloned_context,
&cloned_expanded_node.parent_frame,
)
},
&deps,
&format!("slot_children (node id: {})", expanded_node.id.0),
));
}
fn update(self: Rc<Self>, expanded_node: &Rc<ExpandedNode>, _context: &Rc<RuntimeContext>) {
let containing = expanded_node.containing_component.upgrade();
let nodes = &containing
.as_ref()
.expect("slot to have a containing component")
.expanded_and_flattened_slot_children;
expanded_node.with_properties_unwrapped(|properties: &mut Slot| {
let node_rc =
nodes.read(|nodes| nodes.get(properties.index.get().to_int() as usize).cloned());
let node = match &node_rc {
Some(rc) => Rc::downgrade(rc),
None => Weak::new(),
};
if properties.showing_node.get().upgrade().map(|v| v.id) != node.upgrade().map(|v| v.id)
{
properties.showing_node.set(node);
}
});
}
fn resolve_debug(
&self,
f: &mut std::fmt::Formatter,
_expanded_node: Option<&ExpandedNode>,
) -> std::fmt::Result {
f.debug_struct("Slot").finish()
}
fn base(&self) -> &BaseInstance {
&self.base
}
}