use crate::api::TextInput;
use crate::node_interface::NodeLocal;
use pax_runtime_api::pax_value::{ImplToFromPaxAny, PaxAny, ToFromPaxAny};
use pax_runtime_api::{
borrow, borrow_mut, use_RefCell, Interpolatable, Percent, Property, Variable,
};
use crate::api::math::Point2;
use crate::constants::{
BUTTON_CLICK_HANDLERS, CHECKBOX_CHANGE_HANDLERS, CLAP_HANDLERS, CLICK_HANDLERS,
CONTEXT_MENU_HANDLERS, DOUBLE_CLICK_HANDLERS, DROP_HANDLERS, KEY_DOWN_HANDLERS,
KEY_PRESS_HANDLERS, KEY_UP_HANDLERS, MOUSE_DOWN_HANDLERS, MOUSE_MOVE_HANDLERS,
MOUSE_OUT_HANDLERS, MOUSE_OVER_HANDLERS, MOUSE_UP_HANDLERS, SCROLL_HANDLERS,
TEXTBOX_CHANGE_HANDLERS, TEXTBOX_INPUT_HANDLERS, TEXT_INPUT_HANDLERS, TOUCH_END_HANDLERS,
TOUCH_MOVE_HANDLERS, TOUCH_START_HANDLERS, WHEEL_HANDLERS,
};
use_RefCell!();
use crate::{ExpandedNodeIdentifier, Globals, LayoutProperties, TransformAndBounds};
use core::fmt;
use std::cell::Cell;
use std::collections::HashMap;
use std::rc::{Rc, Weak};
use crate::api::{
ButtonClick, CheckboxChange, Clap, Click, CommonProperties, ContextMenu, DoubleClick, Drop,
Event, KeyDown, KeyPress, KeyUp, MouseDown, MouseMove, MouseOut, MouseOver, MouseUp,
NodeContext, RenderContext, Scroll, Size, TextboxChange, TextboxInput, TouchEnd, TouchMove,
TouchStart, Wheel, Window,
};
use crate::{
compute_tab, ComponentInstance, HandlerLocation, InstanceNode, InstanceNodePtr, RuntimeContext,
RuntimePropertiesStackFrame,
};
#[derive(Clone)]
pub struct ExpandedNode {
#[allow(dead_code)]
pub id: ExpandedNodeIdentifier,
pub instance_node: RefCell<InstanceNodePtr>,
pub render_parent: RefCell<Weak<ExpandedNode>>,
pub template_parent: Weak<ExpandedNode>,
pub parent_frame: Property<Option<ExpandedNodeIdentifier>>,
pub containing_component: Weak<ExpandedNode>,
pub stack: Rc<RuntimePropertiesStackFrame>,
pub children: Property<Vec<Rc<ExpandedNode>>>,
pub mounted_children: RefCell<Vec<Rc<ExpandedNode>>>,
pub properties: RefCell<Rc<RefCell<PaxAny>>>,
common_properties: RefCell<Rc<RefCell<CommonProperties>>>,
pub rendered_size: Property<Option<(f64, f64)>>,
pub transform_and_bounds: Property<TransformAndBounds<NodeLocal, Window>>,
pub expanded_slot_children: RefCell<Option<Vec<Rc<ExpandedNode>>>>,
pub expanded_and_flattened_slot_children: Property<Vec<Rc<ExpandedNode>>>,
pub flattened_slot_children_count: Property<usize>,
pub attached: Cell<u32>,
pub occlusion: Cell<Occlusion>,
pub properties_scope: RefCell<HashMap<String, Variable>>,
pub slot_index: Property<Option<usize>>,
pub suspended: Property<bool>,
}
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
pub struct Occlusion {
pub occlusion_layer_id: u32,
pub z_index: i32,
pub parent_frame: Option<u32>,
}
impl ImplToFromPaxAny for ExpandedNode {}
impl Interpolatable for ExpandedNode {}
macro_rules! dispatch_event_handler {
($fn_name:ident, $arg_type:ty, $handler_key:ident, $recurse:expr) => {
pub fn $fn_name(
&self,
event: Event<$arg_type>,
globals: &Globals,
ctx: &Rc<RuntimeContext>,
) -> bool {
if let Some(registry) = borrow!(self.instance_node).base().get_handler_registry() {
let borrowed_registry = &borrow!(*registry);
if let Some(handlers) = borrowed_registry.handlers.get($handler_key) {
if handlers.len() > 0 {
let component_properties =
if let Some(cc) = self.containing_component.upgrade() {
Rc::clone(&*borrow!(cc.properties))
} else {
Rc::clone(&*borrow!(self.properties))
};
let context = self.get_node_context(ctx);
handlers.iter().for_each(|handler| {
let properties = if let HandlerLocation::Component = &handler.location {
Rc::clone(&*borrow!(self.properties))
} else {
Rc::clone(&component_properties)
};
(handler.function)(
Rc::clone(&properties),
&context,
Some(event.clone().to_pax_any()),
);
});
}
};
}
if $recurse {
if let Some(parent) = self.template_parent.upgrade() {
return parent.$fn_name(event, globals, ctx);
}
}
event.cancelled()
}
};
}
impl ExpandedNode {
pub fn initialize_root(template: Rc<ComponentInstance>, ctx: &Rc<RuntimeContext>) -> Rc<Self> {
let root_env = RuntimePropertiesStackFrame::new(
HashMap::new(),
Rc::new(RefCell::new(().to_pax_any())),
);
let root_node = Self::new(template, root_env, ctx, Weak::new(), Weak::new());
Rc::clone(&root_node).recurse_mount(ctx);
root_node.bind_to_parent_bounds(ctx);
root_node
}
fn new(
template: Rc<dyn InstanceNode>,
env: Rc<RuntimePropertiesStackFrame>,
context: &Rc<RuntimeContext>,
containing_component: Weak<ExpandedNode>,
parent: Weak<ExpandedNode>,
) -> Rc<Self> {
let properties = (&template.base().instance_prototypical_properties_factory)(env.clone());
let common_properties =
(&template
.base()
.instance_prototypical_common_properties_factory)(env.clone());
let mut property_scope = borrow!(*common_properties).retrieve_property_scope();
if let Some(scope) = &template.base().properties_scope_factory {
property_scope.extend(scope(properties.clone()));
}
let id = context.gen_uid();
let res = Rc::new(ExpandedNode {
id,
stack: env,
instance_node: RefCell::new(Rc::clone(&template)),
attached: Cell::new(0),
properties: RefCell::new(properties),
common_properties: RefCell::new(common_properties),
rendered_size: Property::default(),
render_parent: Default::default(),
parent_frame: Default::default(),
template_parent: parent,
containing_component,
children: Property::new_with_name(
Vec::new(),
&format!("node children (node id: {})", id.0),
),
mounted_children: RefCell::new(Vec::new()),
transform_and_bounds: Property::new(TransformAndBounds::default()),
expanded_slot_children: Default::default(),
expanded_and_flattened_slot_children: Default::default(),
flattened_slot_children_count: Property::new(0),
occlusion: Default::default(),
properties_scope: RefCell::new(property_scope),
slot_index: Property::default(),
suspended: Property::new(false),
});
res
}
pub fn recreate_with_new_data(
self: &Rc<Self>,
template: Rc<dyn InstanceNode>,
context: &Rc<RuntimeContext>,
) {
Rc::clone(self).recurse_unmount(context);
let new_expanded_node = Self::new(
template.clone(),
Rc::clone(&self.stack),
context,
Weak::clone(&self.containing_component),
Weak::clone(&self.template_parent),
);
*borrow_mut!(self.instance_node) = Rc::clone(&*borrow!(new_expanded_node.instance_node));
*borrow_mut!(self.properties) = Rc::clone(&*borrow!(new_expanded_node.properties));
*borrow_mut!(self.properties_scope) = borrow!(new_expanded_node.properties_scope).clone();
*borrow_mut!(self.common_properties) =
Rc::clone(&*borrow!(new_expanded_node.common_properties));
self.occlusion.set(Default::default());
Rc::clone(self).recurse_mount(context);
Rc::clone(self).recurse_update(context);
self.bind_to_parent_bounds(context);
}
pub fn is_descendant_of(&self, other_expanded_node_id: &ExpandedNodeIdentifier) -> bool {
if let Some(parent) = borrow!(self.render_parent).upgrade() {
if parent.id.eq(other_expanded_node_id) {
true
} else {
parent.is_descendant_of(other_expanded_node_id)
}
} else {
false
}
}
pub fn create_children_detached(
self: &Rc<Self>,
templates: impl IntoIterator<Item = (Rc<dyn InstanceNode>, Rc<RuntimePropertiesStackFrame>)>,
context: &Rc<RuntimeContext>,
template_parent: &Weak<ExpandedNode>,
) -> Vec<Rc<ExpandedNode>> {
let containing_component = if borrow!(self.instance_node).base().flags().is_component {
Rc::downgrade(&self)
} else {
Weak::clone(&self.containing_component)
};
let mut children = Vec::new();
for (template, env) in templates {
children.push(Self::new(
template,
env,
context,
Weak::clone(&containing_component),
Weak::clone(&template_parent),
));
}
children
}
pub fn attach_children(
self: &Rc<Self>,
new_children: Vec<Rc<ExpandedNode>>,
context: &Rc<RuntimeContext>,
parent_frame: &Property<Option<ExpandedNodeIdentifier>>,
) -> Vec<Rc<ExpandedNode>> {
let mut curr_children = borrow_mut!(self.mounted_children);
for child in new_children.iter() {
*borrow_mut!(child.render_parent) = Rc::downgrade(self);
let parent_frame = parent_frame.clone();
let deps = [parent_frame.untyped()];
child
.parent_frame
.replace_with(Property::computed(move || parent_frame.get(), &deps));
let cp = self.get_common_properties();
let self_suspended = borrow!(cp)._suspended.clone();
let parent_suspended = self.suspended.clone();
let deps = [parent_suspended.untyped(), self_suspended.untyped()];
child.suspended.replace_with(Property::computed(
move || {
self_suspended
.get()
.unwrap_or_else(|| parent_suspended.get())
},
&deps,
));
}
if self.attached.get() > 0 {
for child in curr_children.iter() {
Rc::clone(child).recurse_unmount(context);
}
for child in new_children.iter() {
Rc::clone(child).recurse_mount(context);
child.bind_to_parent_bounds(context);
}
}
*curr_children = new_children.clone();
new_children
}
fn bind_to_parent_bounds(self: &Rc<Self>, ctx: &Rc<RuntimeContext>) {
let parent_transform_and_bounds = borrow!(self.render_parent)
.upgrade()
.map(|n| n.transform_and_bounds.clone())
.unwrap_or_else(|| ctx.globals().viewport);
let common_props = borrow!(self.common_properties);
let extra_transform = borrow!(common_props).transform.clone();
let transform_and_bounds = compute_tab(
self.layout_properties(),
extra_transform,
parent_transform_and_bounds,
);
self.transform_and_bounds.replace_with(transform_and_bounds);
}
pub fn generate_children(
self: &Rc<Self>,
templates: impl IntoIterator<Item = (Rc<dyn InstanceNode>, Rc<RuntimePropertiesStackFrame>)>,
context: &Rc<RuntimeContext>,
parent_frame: &Property<Option<ExpandedNodeIdentifier>>,
) -> Vec<Rc<ExpandedNode>> {
let new_children = self.create_children_detached(templates, context, &Rc::downgrade(&self));
let res = self.attach_children(new_children, context, parent_frame);
res
}
pub fn recurse_update(self: &Rc<Self>, context: &Rc<RuntimeContext>) {
if let Some(ref registry) = borrow!(self.instance_node).base().handler_registry {
if !self.suspended.get() {
for handler in borrow!(registry)
.handlers
.get("tick")
.unwrap_or(&Vec::new())
{
(handler.function)(
Rc::clone(&*borrow!(self.properties)),
&self.get_node_context(context),
None,
)
}
}
}
Rc::clone(&*borrow!(self.instance_node)).update(&self, context);
if let Some(ref registry) = borrow!(self.instance_node).base().handler_registry {
if !self.suspended.get() {
for handler in borrow!(registry)
.handlers
.get("pre_render")
.unwrap_or(&Vec::new())
{
(handler.function)(
Rc::clone(&*borrow!(self.properties)),
&self.get_node_context(context),
None,
)
}
}
}
for child in self.children.get().iter() {
child.recurse_update(context);
}
}
pub fn recurse_mount(self: &Rc<Self>, context: &Rc<RuntimeContext>) {
if self.attached.get() == 0 {
self.attached.set(self.attached.get() + 1);
context.add_to_cache(&self);
borrow!(self.instance_node)
.clone()
.handle_mount(&self, context);
if let Some(ref registry) = borrow!(self.instance_node).base().handler_registry {
for handler in borrow!(registry)
.handlers
.get("mount")
.unwrap_or(&Vec::new())
{
(handler.function)(
Rc::clone(&*borrow!(self.properties)),
&self.get_node_context(context),
None,
)
}
}
if let Some(slot_children) = borrow!(self.expanded_slot_children).as_ref() {
for slot_child in slot_children {
slot_child.recurse_mount(context);
}
}
self.recurse_update(context);
}
}
pub fn recurse_unmount(self: Rc<Self>, context: &Rc<RuntimeContext>) {
if self.attached.get() == 1 {
self.attached.set(self.attached.get() - 1);
context.remove_from_cache(&self);
for child in borrow!(self.mounted_children).iter() {
Rc::clone(child).recurse_unmount(context);
}
borrow!(self.instance_node).handle_unmount(&self, context);
if let Some(ref registry) = borrow!(self.instance_node).base().handler_registry {
for handler in borrow!(registry)
.handlers
.get("unmount")
.unwrap_or(&Vec::new())
{
(handler.function)(
Rc::clone(&*borrow!(self.properties)),
&self.get_node_context(context),
None,
)
}
}
self.occlusion.set(Default::default());
}
}
pub fn recurse_render_queue(
self: &Rc<Self>,
ctx: &Rc<RuntimeContext>,
rcs: &mut dyn RenderContext,
) {
let cp = self.get_common_properties();
let cp = borrow!(cp);
if cp.unclippable.get().unwrap_or(false) {
ctx.queue_render(Rc::clone(&self));
} else {
self.recurse_render(ctx, rcs);
}
}
pub fn recurse_render(self: &Rc<Self>, ctx: &Rc<RuntimeContext>, rcs: &mut dyn RenderContext) {
borrow!(self.instance_node).handle_pre_render(&self, ctx, rcs);
for child in self.children.get().iter().rev() {
child.recurse_render_queue(ctx, rcs);
}
borrow!(self.instance_node).render(&self, ctx, rcs);
borrow!(self.instance_node).handle_post_render(&self, ctx, rcs);
}
pub fn with_properties_unwrapped<T: ToFromPaxAny, R>(
&self,
callback: impl FnOnce(&mut T) -> R,
) -> R {
self.try_with_properties_unwrapped(callback)
.expect("properties not of expected type")
}
pub fn try_with_properties_unwrapped<T: ToFromPaxAny, R>(
&self,
callback: impl FnOnce(&mut T) -> R,
) -> Option<R> {
let properties = borrow_mut!(self.properties);
let mut borrowed = borrow_mut!(properties);
let Ok(mut val) = T::mut_from_pax_any(&mut *borrowed) else {
return None;
};
Some(callback(&mut val))
}
pub fn recurse_visit_postorder(self: &Rc<Self>, func: &mut impl FnMut(&Rc<Self>)) {
self.compute_flattened_slot_children();
for child in self.children.get().iter().rev() {
child.recurse_visit_postorder(func)
}
func(self);
}
pub fn get_node_context<'a>(&'a self, ctx: &Rc<RuntimeContext>) -> NodeContext {
let globals = ctx.globals();
let t_and_b = self.transform_and_bounds.clone();
let deps = [t_and_b.untyped()];
let bounds_self = Property::computed(move || t_and_b.get().bounds, &deps);
let t_and_b_parent = if let Some(parent) = borrow!(self.render_parent).upgrade() {
parent.transform_and_bounds.clone()
} else {
globals.viewport.clone()
};
let deps = [t_and_b_parent.untyped()];
let bounds_parent = Property::computed(move || t_and_b_parent.get().bounds, &deps);
let slot_children_count = if borrow!(self.instance_node).base().flags().is_component {
self.flattened_slot_children_count.clone()
} else {
self.containing_component
.upgrade()
.map(|v| v.flattened_slot_children_count.clone())
.unwrap_or_default()
};
NodeContext {
slot_index: self.slot_index.clone(),
local_stack_frame: Rc::clone(&self.stack),
component_origin: Weak::clone(&self.containing_component),
frames_elapsed: globals.frames_elapsed.clone(),
bounds_self,
bounds_parent,
runtime_context: ctx.clone(),
platform: globals.platform.clone(),
os: globals.os.clone(),
slot_children_count,
node_transform_and_bounds: self.transform_and_bounds.get(),
#[cfg(feature = "designtime")]
designtime: globals.designtime.clone(),
}
}
pub fn get_common_properties(&self) -> Rc<RefCell<CommonProperties>> {
Rc::clone(&*borrow!(self.common_properties))
}
pub fn ray_cast_test(&self, ray: Point2<Window>) -> bool {
let cp = borrow!(self.common_properties);
if !borrow!(&*cp)._raycastable.get().unwrap_or(true) {
return false;
}
let t_and_b = self.transform_and_bounds.get();
let inverted_transform = t_and_b.transform.inverse();
let transformed_ray = inverted_transform * ray;
let (width, height) = t_and_b.bounds;
let res = transformed_ray.x > 0.0
&& transformed_ray.y > 0.0
&& transformed_ray.x < width
&& transformed_ray.y < height;
res
}
pub fn compute_flattened_slot_children(&self) {
if let Some(slot_children) = borrow!(self.expanded_slot_children).as_ref() {
let new_flattened = flatten_expanded_nodes_for_slot(&slot_children);
let old_and_new_filtered_same =
self.expanded_and_flattened_slot_children.read(|flattened| {
flattened
.iter()
.map(|n| n.id)
.eq(new_flattened.iter().map(|n| n.id))
});
if !old_and_new_filtered_same {
self.flattened_slot_children_count.set(new_flattened.len());
self.expanded_and_flattened_slot_children.set(new_flattened);
for (i, slot_child) in self
.expanded_and_flattened_slot_children
.get()
.iter()
.enumerate()
{
if slot_child.slot_index.get() != Some(i) {
slot_child.slot_index.set(Some(i));
};
}
}
}
}
dispatch_event_handler!(dispatch_scroll, Scroll, SCROLL_HANDLERS, true);
dispatch_event_handler!(dispatch_clap, Clap, CLAP_HANDLERS, true);
dispatch_event_handler!(dispatch_touch_start, TouchStart, TOUCH_START_HANDLERS, true);
dispatch_event_handler!(dispatch_touch_move, TouchMove, TOUCH_MOVE_HANDLERS, true);
dispatch_event_handler!(dispatch_touch_end, TouchEnd, TOUCH_END_HANDLERS, true);
dispatch_event_handler!(dispatch_key_down, KeyDown, KEY_DOWN_HANDLERS, false);
dispatch_event_handler!(dispatch_key_up, KeyUp, KEY_UP_HANDLERS, false);
dispatch_event_handler!(dispatch_key_press, KeyPress, KEY_PRESS_HANDLERS, false);
dispatch_event_handler!(
dispatch_checkbox_change,
CheckboxChange,
CHECKBOX_CHANGE_HANDLERS,
true
);
dispatch_event_handler!(
dispatch_textbox_change,
TextboxChange,
TEXTBOX_CHANGE_HANDLERS,
true
);
dispatch_event_handler!(dispatch_text_input, TextInput, TEXT_INPUT_HANDLERS, true);
dispatch_event_handler!(
dispatch_textbox_input,
TextboxInput,
TEXTBOX_INPUT_HANDLERS,
true
);
dispatch_event_handler!(
dispatch_button_click,
ButtonClick,
BUTTON_CLICK_HANDLERS,
true
);
dispatch_event_handler!(dispatch_mouse_down, MouseDown, MOUSE_DOWN_HANDLERS, true);
dispatch_event_handler!(dispatch_mouse_up, MouseUp, MOUSE_UP_HANDLERS, true);
dispatch_event_handler!(dispatch_mouse_move, MouseMove, MOUSE_MOVE_HANDLERS, true);
dispatch_event_handler!(dispatch_mouse_over, MouseOver, MOUSE_OVER_HANDLERS, true);
dispatch_event_handler!(dispatch_mouse_out, MouseOut, MOUSE_OUT_HANDLERS, true);
dispatch_event_handler!(
dispatch_double_click,
DoubleClick,
DOUBLE_CLICK_HANDLERS,
true
);
dispatch_event_handler!(
dispatch_context_menu,
ContextMenu,
CONTEXT_MENU_HANDLERS,
true
);
dispatch_event_handler!(dispatch_click, Click, CLICK_HANDLERS, true);
dispatch_event_handler!(dispatch_wheel, Wheel, WHEEL_HANDLERS, true);
dispatch_event_handler!(dispatch_drop, Drop, DROP_HANDLERS, true);
pub fn dispatch_custom_event(
&self,
identifier: &str,
ctx: &Rc<RuntimeContext>,
) -> Result<(), String> {
let component_origin_instance = borrow!(self.instance_node);
let registry = component_origin_instance
.base()
.handler_registry
.as_ref()
.ok_or_else(|| "no registry present".to_owned())?;
let parent_component = self
.containing_component
.upgrade()
.ok_or_else(|| "can't dispatch from root (has no parent)".to_owned())?;
let properties = borrow!(parent_component.properties);
for handler in borrow!(registry)
.handlers
.get(identifier)
.expect("presence should have been checked when added to custom_event_queue")
{
(handler.function)(Rc::clone(&*properties), &self.get_node_context(ctx), None)
}
Ok(())
}
pub fn chassis_resize_request(self: &Rc<ExpandedNode>, width: f64, height: f64) {
self.rendered_size.set(Some((width, height)));
}
pub fn layout_properties(self: &Rc<ExpandedNode>) -> Property<LayoutProperties> {
let common_props = self.get_common_properties();
let common_props = borrow!(common_props);
let cp_width = common_props.width.clone();
let cp_height = common_props.height.clone();
let cp_transform = common_props.transform.clone();
let cp_anchor_x = common_props.anchor_x.clone();
let cp_anchor_y = common_props.anchor_y.clone();
let cp_scale_x = common_props.scale_x.clone();
let cp_scale_y = common_props.scale_y.clone();
let cp_skew_x = common_props.skew_x.clone();
let cp_skew_y = common_props.skew_y.clone();
let cp_rotate = common_props.rotate.clone();
let cp_x = common_props.x.clone();
let cp_y = common_props.y.clone();
let rendered_size = self.rendered_size.clone();
let deps = [
cp_width.untyped(),
cp_height.untyped(),
cp_transform.untyped(),
cp_anchor_x.untyped(),
cp_anchor_y.untyped(),
cp_scale_x.untyped(),
cp_scale_y.untyped(),
cp_skew_x.untyped(),
cp_skew_y.untyped(),
cp_rotate.untyped(),
cp_x.untyped(),
cp_y.untyped(),
rendered_size.untyped(),
];
Property::computed(
move || {
let fallback = rendered_size.get();
let (w_fallback, h_fallback) = match fallback {
Some((wf, hf)) => (Some(wf), Some(hf)),
None => (None, None),
};
LayoutProperties {
x: cp_x.get(),
y: cp_y.get(),
width: cp_width
.get()
.or(w_fallback.map(|v| Size::Pixels(v.into()))),
height: cp_height
.get()
.or(h_fallback.map(|v| Size::Pixels(v.into()))),
rotate: cp_rotate.get(),
scale_x: cp_scale_x
.get()
.map(|v| Percent((100.0 * v.expect_percent()).into())),
scale_y: cp_scale_y
.get()
.map(|v| Percent((100.0 * v.expect_percent()).into())),
anchor_x: cp_anchor_x.get(),
anchor_y: cp_anchor_y.get(),
skew_x: cp_skew_x.get(),
skew_y: cp_skew_y.get(),
}
},
&deps,
)
}
}
fn flatten_expanded_nodes_for_slot(nodes: &[Rc<ExpandedNode>]) -> Vec<Rc<ExpandedNode>> {
let mut result: Vec<Rc<ExpandedNode>> = vec![];
for node in nodes {
if borrow!(node.instance_node).base().flags().invisible_to_slot {
result.extend(flatten_expanded_nodes_for_slot(
node.children
.get()
.clone()
.into_iter()
.collect::<Vec<_>>()
.as_slice(),
));
} else {
result.push(Rc::clone(&node))
}
}
result
}
impl std::fmt::Debug for ExpandedNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
pub struct Fmt<F>(pub F)
where
F: Fn(&mut fmt::Formatter) -> fmt::Result;
impl<F> fmt::Debug for Fmt<F>
where
F: Fn(&mut fmt::Formatter) -> fmt::Result,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(self.0)(f)
}
}
f.debug_struct("ExpandedNode")
.field(
"instance_node",
&Fmt(|f| borrow!(self.instance_node).resolve_debug(f, Some(self))),
)
.field("id", &self.id)
.field("common_properties", &borrow!(self.common_properties))
.field("transform_and_bounds", &self.transform_and_bounds)
.field("children", &self.children.get().iter().collect::<Vec<_>>())
.field(
"slot_children",
&self
.expanded_and_flattened_slot_children
.get()
.iter()
.map(|v| v.id)
.collect::<Vec<_>>(),
)
.field("occlusion_id", &self.occlusion.get())
.field(
"containing_component",
&self.containing_component.upgrade().map(|v| v.id.clone()),
)
.finish()
}
}