Add ability to get the parent item from the vtable

(still untested)
This commit is contained in:
Olivier Goffart 2021-01-26 10:29:24 +01:00
parent 1fda2e1c99
commit c2982d9ab3
10 changed files with 356 additions and 209 deletions

View file

@ -65,6 +65,7 @@ using cbindgen_private::ItemVTable;
using ComponentRef = vtable::VRef<private_api::ComponentVTable>; using ComponentRef = vtable::VRef<private_api::ComponentVTable>;
using ItemRef = vtable::VRef<private_api::ItemVTable>; using ItemRef = vtable::VRef<private_api::ItemVTable>;
using ItemVisitorRefMut = vtable::VRefMut<cbindgen_private::ItemVisitorVTable>; using ItemVisitorRefMut = vtable::VRefMut<cbindgen_private::ItemVisitorVTable>;
using cbindgen_private::ItemWeak;
} }
using cbindgen_private::ComponentRc; using cbindgen_private::ComponentRc;
using cbindgen_private::EasingCurve; using cbindgen_private::EasingCurve;
@ -165,16 +166,17 @@ using cbindgen_private::NativeStyleMetrics;
namespace private_api { namespace private_api {
constexpr inline ItemTreeNode make_item_node(std::uintptr_t offset, constexpr inline ItemTreeNode make_item_node(std::uintptr_t offset,
const cbindgen_private::ItemVTable *vtable, const cbindgen_private::ItemVTable *vtable,
uint32_t child_count, uint32_t child_index) uint32_t child_count, uint32_t child_index,
uint parent_index)
{ {
return ItemTreeNode { ItemTreeNode::Item_Body { return ItemTreeNode { ItemTreeNode::Item_Body {
ItemTreeNode::Tag::Item, { vtable, offset }, child_count, child_index } }; ItemTreeNode::Tag::Item, { vtable, offset }, child_count, child_index, parent_index } };
} }
constexpr inline ItemTreeNode make_dyn_node(std::uintptr_t offset) constexpr inline ItemTreeNode make_dyn_node(std::uintptr_t offset, std::uint32_t parent_index)
{ {
return ItemTreeNode { ItemTreeNode::DynamicTree_Body { ItemTreeNode::Tag::DynamicTree, return ItemTreeNode { ItemTreeNode::DynamicTree_Body {
offset } }; ItemTreeNode::Tag::DynamicTree, offset, parent_index } };
} }
inline ItemRef get_item_ref(ComponentRef component, Slice<ItemTreeNode> item_tree, int index) inline ItemRef get_item_ref(ComponentRef component, Slice<ItemTreeNode> item_tree, int index)
@ -183,6 +185,17 @@ inline ItemRef get_item_ref(ComponentRef component, Slice<ItemTreeNode> item_tre
return ItemRef { item.vtable, reinterpret_cast<char *>(component.instance) + item.offset }; return ItemRef { item.vtable, reinterpret_cast<char *>(component.instance) + item.offset };
} }
inline ItemWeak parent_item(cbindgen_private::ComponentWeak component,
Slice<ItemTreeNode> item_tree, int index)
{
const auto &node = item_tree.ptr[index];
if (node.tag == ItemTreeNode::Tag::Item) {
return { component, node.item.parent_index };
} else {
return { component, node.dynamic_tree.parent_index };
}
}
} }
using cbindgen_private::FocusEvent; using cbindgen_private::FocusEvent;

View file

@ -167,6 +167,8 @@ public:
inner->strong_ref++; inner->strong_ref++;
return { VRc<VTable, X>(inner) }; return { VRc<VTable, X>(inner) };
} }
VWeak<VTable, Dyn> into_dyn() const { return *reinterpret_cast<const VWeak<VTable, Dyn> *>(this); }
}; };

View file

@ -88,14 +88,18 @@ pub fn generate(
} }
/// Visit each item in order in which they should appear in the children tree array. /// Visit each item in order in which they should appear in the children tree array.
/// The parameter of the visitor are the item, and the first_children_offset, and wether this is the flickable rectangle /// The parameter of the visitor are
/// 1. the item
/// 2. the first_children_offset,
/// 3. the parent index
/// 4. wether this is the flickable rectangle
#[allow(dead_code)] #[allow(dead_code)]
pub fn build_array_helper( pub fn build_array_helper(
component: &Component, component: &Component,
mut visit_item: impl FnMut(&ElementRc, u32, bool), mut visit_item: impl FnMut(&ElementRc, u32, u32, bool),
) { ) {
visit_item(&component.root_element, 1, false); visit_item(&component.root_element, 1, 0, false);
visit_children(&component.root_element, 1, &mut visit_item); visit_children(&component.root_element, &mut 0, 1, &mut visit_item);
fn sub_children_count(e: &ElementRc) -> usize { fn sub_children_count(e: &ElementRc) -> usize {
let mut count = e.borrow().children.len(); let mut count = e.borrow().children.len();
@ -110,29 +114,33 @@ pub fn build_array_helper(
fn visit_children( fn visit_children(
item: &ElementRc, item: &ElementRc,
index: &mut u32,
children_offset: u32, children_offset: u32,
visit_item: &mut impl FnMut(&ElementRc, u32, bool), visit_item: &mut impl FnMut(&ElementRc, u32, u32, bool),
) { ) {
let mut offset = children_offset + item.borrow().children.len() as u32; let mut offset = children_offset + item.borrow().children.len() as u32;
if is_flickable(item) { if is_flickable(item) {
visit_item(item, offset, true); visit_item(item, offset, *index, true);
offset += 1; offset += 1;
} }
for i in &item.borrow().children { for i in &item.borrow().children {
visit_item(i, offset, false); visit_item(i, offset, *index, false);
offset += sub_children_count(i) as u32; offset += sub_children_count(i) as u32;
} }
*index += 1;
let mut offset = children_offset + item.borrow().children.len() as u32; let mut offset = children_offset + item.borrow().children.len() as u32;
if is_flickable(item) { if is_flickable(item) {
offset += 1; offset += 1;
*index += 1;
} }
for e in &item.borrow().children { for e in &item.borrow().children {
visit_children(e, offset, visit_item); visit_children(e, index, offset, visit_item);
offset += sub_children_count(e) as u32; offset += sub_children_count(e) as u32;
} }
} }

View file

@ -1003,15 +1003,18 @@ fn generate_component(
let mut tree_array = vec![]; let mut tree_array = vec![];
let mut item_names_and_vt_symbols = vec![]; let mut item_names_and_vt_symbols = vec![];
let mut repeater_count = 0; let mut repeater_count = 0;
super::build_array_helper(component, |item_rc, children_offset, is_flickable_rect| { super::build_array_helper(
component,
|item_rc, children_offset, parent_index, is_flickable_rect| {
let item = item_rc.borrow(); let item = item_rc.borrow();
if is_flickable_rect { if is_flickable_rect {
tree_array.push(format!( tree_array.push(format!(
"sixtyfps::private_api::make_item_node(offsetof({}, {}) + offsetof(sixtyfps::Flickable, viewport), &sixtyfps::private_api::RectangleVTable, {}, {})", "sixtyfps::private_api::make_item_node(offsetof({}, {}) + offsetof(sixtyfps::Flickable, viewport), &sixtyfps::private_api::RectangleVTable, {}, {}, {})",
&component_id, &component_id,
item.id, item.id,
item.children.len(), item.children.len(),
tree_array.len() + 1, tree_array.len() + 1,
parent_index,
)); ));
} else if item.base_type == Type::Void { } else if item.base_type == Type::Void {
assert!(component.is_global()); assert!(component.is_global());
@ -1019,7 +1022,10 @@ fn generate_component(
handle_property_binding(item_rc, prop_name, binding_expression, &mut init); handle_property_binding(item_rc, prop_name, binding_expression, &mut init);
} }
} else if let Some(repeated) = &item.repeated { } else if let Some(repeated) = &item.repeated {
tree_array.push(format!("sixtyfps::private_api::make_dyn_node({})", repeater_count,)); tree_array.push(format!(
"sixtyfps::private_api::make_dyn_node({}, {})",
repeater_count, parent_index
));
let base_component = item.base_type.as_component(); let base_component = item.base_type.as_component();
let mut friends = Vec::new(); let mut friends = Vec::new();
generate_component(file, base_component, diag, Some(&mut friends)); generate_component(file, base_component, diag, Some(&mut friends));
@ -1044,18 +1050,20 @@ fn generate_component(
repeater_count += 1; repeater_count += 1;
} else { } else {
tree_array.push(format!( tree_array.push(format!(
"sixtyfps::private_api::make_item_node(offsetof({}, {}), &sixtyfps::private_api::{}, {}, {})", "sixtyfps::private_api::make_item_node(offsetof({}, {}), &sixtyfps::private_api::{}, {}, {}, {})",
component_id, component_id,
item.id, item.id,
item.base_type.as_native().vtable_symbol, item.base_type.as_native().vtable_symbol,
if super::is_flickable(item_rc) { 1 } else { item.children.len() }, if super::is_flickable(item_rc) { 1 } else { item.children.len() },
children_offset, children_offset,
parent_index,
)); ));
handle_item(item_rc, &mut component_struct, &mut init); handle_item(item_rc, &mut component_struct, &mut init);
item_names_and_vt_symbols item_names_and_vt_symbols
.push((item.id.clone(), item.base_type.as_native().vtable_symbol.clone())); .push((item.id.clone(), item.base_type.as_native().vtable_symbol.clone()));
} }
}); },
);
if !component.is_global() { if !component.is_global() {
component_struct component_struct
@ -1139,6 +1147,31 @@ fn generate_component(
}), }),
)); ));
let parent_item_from_parent_component = if let Some(parent_index) =
component.parent_element.upgrade().and_then(|e| e.borrow().item_index.get().map(|x| *x))
{
format!(" return {{ self->parent->self_weak.into_dyn(), {} }};", parent_index)
} else {
" return {};".to_owned()
};
component_struct.members.push((
Access::Private,
Declaration::Function(Function {
name: "parent_item".into(),
signature: "(sixtyfps::private_api::ComponentRef component, uintptr_t index) -> sixtyfps::private_api::ItemWeak".into(),
is_static: true,
statements: Some(vec![
format!("auto self = reinterpret_cast<const {}*>(component.instance);", component_id),
"if (index == 0) {".into(),
parent_item_from_parent_component,
"}".into(),
"return sixtyfps::private_api::parent_item(self->self_weak.into_dyn(), item_tree(), index);".into(),
]),
..Default::default()
}),
));
component_struct.members.push(( component_struct.members.push((
Access::Private, Access::Private,
Declaration::Function(Function { Declaration::Function(Function {
@ -1232,7 +1265,7 @@ fn generate_component(
ty: "const sixtyfps::private_api::ComponentVTable".to_owned(), ty: "const sixtyfps::private_api::ComponentVTable".to_owned(),
name: format!("{}::static_vtable", component_id), name: format!("{}::static_vtable", component_id),
init: Some(format!( init: Some(format!(
"{{ visit_children, get_item_ref, layouting_info, apply_layout, sixtyfps::private_api::drop_in_place<{}>, sixtyfps::private_api::dealloc }}", "{{ visit_children, get_item_ref, parent_item, layouting_info, apply_layout, sixtyfps::private_api::drop_in_place<{}>, sixtyfps::private_api::dealloc }}",
component_id) component_id)
), ),
})); }));

View file

@ -373,7 +373,10 @@ fn generate_component(
let mut init = Vec::new(); let mut init = Vec::new();
let mut window_field_init = None; let mut window_field_init = None;
let mut window_parent_param = None; let mut window_parent_param = None;
super::build_array_helper(component, |item_rc, children_index, is_flickable_rect| { super::build_array_helper(
component,
|item_rc, children_index, parent_index, is_flickable_rect| {
let parent_index = parent_index as u32;
let item = item_rc.borrow(); let item = item_rc.borrow();
if is_flickable_rect { if is_flickable_rect {
let field_name = format_ident!("{}", item.id); let field_name = format_ident!("{}", item.id);
@ -385,6 +388,7 @@ fn generate_component(
item: VOffset::new(#inner_component_id::FIELD_OFFSETS.#field_name + sixtyfps::re_exports::Flickable::FIELD_OFFSETS.viewport), item: VOffset::new(#inner_component_id::FIELD_OFFSETS.#field_name + sixtyfps::re_exports::Flickable::FIELD_OFFSETS.viewport),
chilren_count: #children_count, chilren_count: #children_count,
children_index: #children_index, children_index: #children_index,
parent_index: #parent_index
} }
)); ));
} else if item.base_type == Type::Void { } else if item.base_type == Type::Void {
@ -474,8 +478,7 @@ fn generate_component(
let mut model = compile_expression(&repeated.model, component); let mut model = compile_expression(&repeated.model, component);
if repeated.is_conditional_element { if repeated.is_conditional_element {
model = model = quote!(sixtyfps::re_exports::ModelHandle::new(std::rc::Rc::<bool>::new(#model)))
quote!(sixtyfps::re_exports::ModelHandle::new(std::rc::Rc::<bool>::new(#model)))
} }
// FIXME: there could be an optimization if `repeated.model.is_constant()`, we don't need a binding // FIXME: there could be an optimization if `repeated.model.is_constant()`, we don't need a binding
@ -491,7 +494,8 @@ fn generate_component(
}); });
if let Some(listview) = &repeated.is_listview { if let Some(listview) = &repeated.is_listview {
let vp_y = access_named_reference(&listview.viewport_y, component, quote!(_self)); let vp_y =
access_named_reference(&listview.viewport_y, component, quote!(_self));
let vp_h = let vp_h =
access_named_reference(&listview.viewport_height, component, quote!(_self)); access_named_reference(&listview.viewport_height, component, quote!(_self));
let lv_h = let lv_h =
@ -540,6 +544,7 @@ fn generate_component(
item_tree_array.push(quote!( item_tree_array.push(quote!(
sixtyfps::re_exports::ItemTreeNode::DynamicTree { sixtyfps::re_exports::ItemTreeNode::DynamicTree {
index: #repeater_index, index: #repeater_index,
parent_index: #parent_index,
} }
)); ));
@ -555,6 +560,7 @@ fn generate_component(
item: VOffset::new(#inner_component_id::FIELD_OFFSETS.#field_name), item: VOffset::new(#inner_component_id::FIELD_OFFSETS.#field_name),
chilren_count: #children_count, chilren_count: #children_count,
children_index: #children_index, children_index: #children_index,
parent_index: #parent_index,
} }
)); ));
for (k, binding_expression) in &item.bindings { for (k, binding_expression) in &item.bindings {
@ -563,7 +569,8 @@ fn generate_component(
item_names.push(field_name); item_names.push(field_name);
item_types.push(format_ident!("{}", item.base_type.as_native().class_name)); item_types.push(format_ident!("{}", item.base_type.as_native().class_name));
} }
}); },
);
let resource_symbols: Vec<proc_macro2::TokenStream> = component let resource_symbols: Vec<proc_macro2::TokenStream> = component
.embedded_file_resources .embedded_file_resources
@ -661,6 +668,11 @@ fn generate_component(
(None, None) (None, None)
} else { } else {
let item_tree_array_len = item_tree_array.len(); let item_tree_array_len = item_tree_array.len();
let parent_item_index = component
.parent_element
.upgrade()
.and_then(|e| e.borrow().item_index.get().map(|x| *x));
let parent_item_index = parent_item_index.iter();
init.insert(0, quote!(sixtyfps::re_exports::init_component_items(_self, Self::item_tree(), &_self.window);)); init.insert(0, quote!(sixtyfps::re_exports::init_component_items(_self, Self::item_tree(), &_self.window);));
( (
Some(quote! { Some(quote! {
@ -700,6 +712,23 @@ fn generate_component(
} }
} }
fn parent_item(self: ::core::pin::Pin<&Self>, index: usize) -> sixtyfps::re_exports::ItemWeak {
if index == 0 {
#(
if let Some(parent) = self.parent.clone().into_dyn().upgrade() {
return sixtyfps::re_exports::ItemRc::new(parent, #parent_item_index).downgrade();
}
)*
return sixtyfps::re_exports::ItemWeak::default();
}
let parent_index = match &Self::item_tree()[index] {
ItemTreeNode::Item { parent_index, .. } => *parent_index,
ItemTreeNode::DynamicTree { parent_index, .. } => *parent_index,
};
let self_rc = self.self_weak.get().unwrap().clone().into_dyn().upgrade().unwrap();
ItemRc::new(self_rc, parent_index as _).downgrade()
}
} }
}), }),
) )

View file

@ -190,19 +190,22 @@ pub async fn run_passes(
fn generate_item_indices(component: &Rc<object_tree::Component>) { fn generate_item_indices(component: &Rc<object_tree::Component>) {
let mut current_item_index: usize = 0; let mut current_item_index: usize = 0;
generator::build_array_helper(&component, move |item_rc, _, is_flickable_rect| { generator::build_array_helper(&component, move |item_rc, _, _, is_flickable_rect| {
let item = item_rc.borrow(); let item = item_rc.borrow();
if is_flickable_rect { if is_flickable_rect {
current_item_index += 1; current_item_index += 1;
} else if item.base_type == crate::langtype::Type::Void { } else if item.base_type == crate::langtype::Type::Void {
} else if item.repeated.is_some() {
generate_item_indices(&*item.base_type.as_component());
current_item_index += 1;
} else { } else {
if let langtype::Type::Component(c) = &item.base_type {
generate_item_indices(c);
}
item.item_index.set(current_item_index).unwrap(); item.item_index.set(current_item_index).unwrap();
current_item_index += 1; current_item_index += 1;
} }
}); });
for p in component.popup_windows.borrow().iter() {
generate_item_indices(&p.component)
}
} }
generate_item_indices(&doc.root_component); generate_item_indices(&doc.root_component);

View file

@ -13,7 +13,7 @@ LICENSE END */
use crate::graphics::Rect; use crate::graphics::Rect;
use crate::item_tree::{ItemVisitorVTable, TraversalOrder, VisitChildrenResult}; use crate::item_tree::{ItemVisitorVTable, TraversalOrder, VisitChildrenResult};
use crate::items::ItemVTable; use crate::items::{ItemVTable, ItemWeak};
use crate::layout::LayoutInfo; use crate::layout::LayoutInfo;
use crate::window::ComponentWindow; use crate::window::ComponentWindow;
use vtable::*; use vtable::*;
@ -38,6 +38,10 @@ pub struct ComponentVTable {
index: usize, index: usize,
) -> core::pin::Pin<VRef<ItemVTable>>, ) -> core::pin::Pin<VRef<ItemVTable>>,
/// Return the parent item. The return value is an item weak because it can be null if
/// there is no parent
pub parent_item: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, index: usize) -> ItemWeak,
/// Returns the layout info for this component /// Returns the layout info for this component
pub layout_info: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> LayoutInfo, pub layout_info: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> LayoutInfo,

View file

@ -84,12 +84,18 @@ pub enum ItemTreeNode<T> {
/// index of the first children within the item tree /// index of the first children within the item tree
children_index: u32, children_index: u32,
/// The index of the parent item (not valid for the root)
parent_index: u32,
}, },
/// A placeholder for many instance of item in their own component which /// A placeholder for many instance of item in their own component which
/// are instantiated according to a model. /// are instantiated according to a model.
DynamicTree { DynamicTree {
/// the undex which is passed in the visit_dynamic callback. /// the undex which is passed in the visit_dynamic callback.
index: usize, index: usize,
/// The index of the parent item (not valid for the root)
parent_index: u32,
}, },
} }
@ -230,7 +236,7 @@ pub fn visit_item_tree<Base>(
ItemTreeNode::Item { item, .. } => { ItemTreeNode::Item { item, .. } => {
visitor.visit_item(component, idx, item.apply_pin(base)) visitor.visit_item(component, idx, item.apply_pin(base))
} }
ItemTreeNode::DynamicTree { index } => { ItemTreeNode::DynamicTree { index, .. } => {
if let Some(sub_idx) = if let Some(sub_idx) =
visit_dynamic(base, order, visitor.borrow_mut(), *index).aborted_index() visit_dynamic(base, order, visitor.borrow_mut(), *index).aborted_index()
{ {

View file

@ -132,6 +132,7 @@ impl ItemRc {
/// A Weak reference to an item that can be constructed from an ItemRc. /// A Weak reference to an item that can be constructed from an ItemRc.
#[derive(Default, Clone)] #[derive(Default, Clone)]
#[repr(C)]
pub struct ItemWeak { pub struct ItemWeak {
component: crate::component::ComponentWeak, component: crate::component::ComponentWeak,
index: usize, index: usize,

View file

@ -23,7 +23,9 @@ use sixtyfps_corelib::graphics::{Rect, Resource};
use sixtyfps_corelib::item_tree::{ use sixtyfps_corelib::item_tree::{
ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable, TraversalOrder, VisitChildrenResult, ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable, TraversalOrder, VisitChildrenResult,
}; };
use sixtyfps_corelib::items::{Flickable, ItemRef, ItemVTable, PropertyAnimation, Rectangle}; use sixtyfps_corelib::items::{
Flickable, ItemRc, ItemRef, ItemVTable, ItemWeak, PropertyAnimation, Rectangle,
};
use sixtyfps_corelib::layout::{LayoutInfo, Padding}; use sixtyfps_corelib::layout::{LayoutInfo, Padding};
use sixtyfps_corelib::model::RepeatedComponent; use sixtyfps_corelib::model::RepeatedComponent;
use sixtyfps_corelib::model::Repeater; use sixtyfps_corelib::model::Repeater;
@ -209,6 +211,9 @@ impl Component for ErasedComponentBox {
// indirection and call our implementation directly. // indirection and call our implementation directly.
unsafe { get_item_ref(self.get_ref().borrow(), index) } unsafe { get_item_ref(self.get_ref().borrow(), index) }
} }
fn parent_item(self: Pin<&Self>, index: usize) -> ItemWeak {
self.borrow().as_ref().parent_item(index)
}
} }
sixtyfps_corelib::ComponentVTable_static!(static COMPONENT_BOX_VT for ErasedComponentBox); sixtyfps_corelib::ComponentVTable_static!(static COMPONENT_BOX_VT for ErasedComponentBox);
@ -517,19 +522,22 @@ fn generate_component<'id>(
let mut repeater = vec![]; let mut repeater = vec![];
let mut repeater_names = HashMap::new(); let mut repeater_names = HashMap::new();
generator::build_array_helper(component, |rc_item, child_offset, is_flickable_rect| { generator::build_array_helper(
component,
|rc_item, child_offset, parent_index, is_flickable_rect| {
let item = rc_item.borrow(); let item = rc_item.borrow();
if is_flickable_rect { if is_flickable_rect {
use vtable::HasStaticVTable; use vtable::HasStaticVTable;
let offset = let offset = items_types[&item.id].offset
items_types[&item.id].offset + Flickable::FIELD_OFFSETS.viewport.get_byte_offset(); + Flickable::FIELD_OFFSETS.viewport.get_byte_offset();
tree_array.push(ItemTreeNode::Item { tree_array.push(ItemTreeNode::Item {
item: unsafe { vtable::VOffset::from_raw(Rectangle::static_vtable(), offset) }, item: unsafe { vtable::VOffset::from_raw(Rectangle::static_vtable(), offset) },
children_index: tree_array.len() as u32 + 1, children_index: tree_array.len() as u32 + 1,
chilren_count: item.children.len() as _, chilren_count: item.children.len() as _,
parent_index,
}); });
} else if let Some(repeated) = &item.repeated { } else if let Some(repeated) = &item.repeated {
tree_array.push(ItemTreeNode::DynamicTree { index: repeater.len() }); tree_array.push(ItemTreeNode::DynamicTree { index: repeater.len(), parent_index });
let base_component = item.base_type.as_component(); let base_component = item.base_type.as_component();
repeater_names.insert(item.id.clone(), repeater.len()); repeater_names.insert(item.id.clone(), repeater.len());
generativity::make_guard!(guard); generativity::make_guard!(guard);
@ -554,13 +562,15 @@ fn generate_component<'id>(
} else { } else {
item.children.len() as _ item.children.len() as _
}, },
parent_index,
}); });
items_types.insert( items_types.insert(
item.id.clone(), item.id.clone(),
ItemWithinComponent { offset, rtti: rt.clone(), elem: rc_item.clone() }, ItemWithinComponent { offset, rtti: rt.clone(), elem: rc_item.clone() },
); );
} }
}); },
);
let mut custom_properties = HashMap::new(); let mut custom_properties = HashMap::new();
let mut custom_callbacks = HashMap::new(); let mut custom_callbacks = HashMap::new();
@ -672,6 +682,7 @@ fn generate_component<'id>(
layout_info, layout_info,
apply_layout, apply_layout,
get_item_ref, get_item_ref,
parent_item,
drop_in_place, drop_in_place,
dealloc, dealloc,
}; };
@ -1479,6 +1490,43 @@ unsafe extern "C" fn get_item_ref(component: ComponentRefPin, index: usize) -> P
} }
} }
unsafe extern "C" fn parent_item(component: ComponentRefPin, index: usize) -> ItemWeak {
generativity::make_guard!(guard);
let instance_ref = InstanceRef::from_pin_ref(component, guard);
if index == 0 {
let parent_item_index = instance_ref
.component_type
.original
.parent_element
.upgrade()
.and_then(|e| e.borrow().item_index.get().map(|x| *x));
if let (Some(parent_offset), Some(parent_index)) =
(instance_ref.component_type.parent_component_offset, parent_item_index)
{
if let Some(parent) = parent_offset.apply(instance_ref.as_ref()) {
generativity::make_guard!(new_guard);
let parent_instance = InstanceRef::from_pin_ref(*parent, new_guard);
let parent_rc = parent_instance
.self_weak()
.get()
.unwrap()
.clone()
.into_dyn()
.upgrade()
.unwrap();
return ItemRc::new(parent_rc, parent_index).downgrade();
};
}
return ItemWeak::default();
}
let parent_index = match &instance_ref.component_type.item_tree.as_slice()[index] {
ItemTreeNode::Item { parent_index, .. } => parent_index,
ItemTreeNode::DynamicTree { parent_index, .. } => parent_index,
};
let self_rc = instance_ref.self_weak().get().unwrap().clone().into_dyn().upgrade().unwrap();
ItemRc::new(self_rc, *parent_index as _).downgrade()
}
unsafe extern "C" fn drop_in_place(component: vtable::VRefMut<ComponentVTable>) -> vtable::Layout { unsafe extern "C" fn drop_in_place(component: vtable::VRefMut<ComponentVTable>) -> vtable::Layout {
let instance_ptr = component.as_ptr() as *mut Instance<'static>; let instance_ptr = component.as_ptr() as *mut Instance<'static>;
let layout = (*instance_ptr).type_info().layout(); let layout = (*instance_ptr).type_info().layout();